00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <vlc/vlc.h>
00033 #include <vlc/intf.h>
00034 #include <vlc/input.h>
00035 #include "vlc_keys.h"
00036
00037 #include <cdio/cdio.h>
00038 #include <cdio/cd_types.h>
00039 #include <cdio/logging.h>
00040 #include <cdio/util.h>
00041 #include <libvcd/info.h>
00042 #include <libvcd/logging.h>
00043 #include "vcd.h"
00044 #include "info.h"
00045 #include "intf.h"
00046
00047 #define FREE_AND_NULL(ptr) free(ptr); ptr = NULL;
00048
00049 extern void VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track,
00050 const vcdinfo_itemid_t *p_itemid );
00051
00052
00053
00054
00055
00056
00057 static block_t *VCDReadBlock ( access_t * );
00058
00059 static int VCDControl ( access_t *p_access, int i_query,
00060 va_list args );
00061
00062
00063 static vlc_bool_t VCDEntryPoints ( access_t * );
00064 static vlc_bool_t VCDLIDs ( access_t * );
00065 static vlc_bool_t VCDSegments ( access_t * );
00066 static int VCDTitles ( access_t * );
00067 static char *VCDParse ( access_t *,
00068 vcdinfo_itemid_t * p_itemid ,
00069 vlc_bool_t *play_single_item );
00070
00071 static void VCDUpdateVar( access_t *p_access, int i_entry, int i_action,
00072 const char *p_varname, char *p_label,
00073 const char *p_debug_label );
00074
00075 static vcdinfo_obj_t *vcd_Open ( vlc_object_t *p_this, const char *psz_dev );
00076
00077
00078
00079
00080
00081
00082
00083
00084 static access_t *p_vcd_access = NULL;
00085
00086
00087 static void
00088 cdio_log_handler (cdio_log_level_t level, const char message[])
00089 {
00090 const vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys;
00091 switch (level) {
00092 case CDIO_LOG_DEBUG:
00093 case CDIO_LOG_INFO:
00094 if (p_vcdplayer->i_debug & INPUT_DBG_CDIO)
00095 msg_Dbg( p_vcd_access, message);
00096 break;
00097 case CDIO_LOG_WARN:
00098 msg_Warn( p_vcd_access, message);
00099 break;
00100 case CDIO_LOG_ERROR:
00101 case CDIO_LOG_ASSERT:
00102 msg_Err( p_vcd_access, message);
00103 break;
00104 default:
00105 msg_Warn( p_vcd_access, message,
00106 _("The above message had unknown log level"),
00107 level);
00108 }
00109 return;
00110 }
00111
00112
00113 static void
00114 vcd_log_handler (vcd_log_level_t level, const char message[])
00115 {
00116 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys;
00117 switch (level) {
00118 case VCD_LOG_DEBUG:
00119 case VCD_LOG_INFO:
00120 if (p_vcdplayer->i_debug & INPUT_DBG_VCDINFO)
00121 msg_Dbg( p_vcd_access, message);
00122 break;
00123 case VCD_LOG_WARN:
00124 msg_Warn( p_vcd_access, message);
00125 break;
00126 case VCD_LOG_ERROR:
00127 case VCD_LOG_ASSERT:
00128 msg_Err( p_vcd_access, message);
00129 break;
00130 default:
00131 msg_Warn( p_vcd_access, "%s\n%s %d", message,
00132 _("The above message had unknown vcdimager log level"),
00133 level);
00134 }
00135 return;
00136 }
00137
00138
00139
00140
00141
00142 static block_t *
00143 VCDReadBlock( access_t * p_access )
00144 {
00145 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
00146 const int i_blocks = p_vcdplayer->i_blocks_per_read;
00147 block_t *p_block;
00148 int i_read;
00149 uint8_t *p_buf;
00150
00151 i_read = 0;
00152
00153 dbg_print( (INPUT_DBG_LSN), "lsn: %lu",
00154 (long unsigned int) p_vcdplayer->i_lsn );
00155
00156
00157 if( !( p_block = block_New( p_access, i_blocks * M2F2_SECTOR_SIZE ) ) )
00158 {
00159 msg_Err( p_access, "cannot get a new block of size: %i",
00160 i_blocks * M2F2_SECTOR_SIZE );
00161 block_Release( p_block );
00162 return NULL;
00163 }
00164
00165 p_buf = (uint8_t *) p_block->p_buffer;
00166 for ( i_read = 0 ; i_read < i_blocks ; i_read++ )
00167 {
00168 vcdplayer_read_status_t read_status = vcdplayer_read(p_access, p_buf);
00169
00170 p_access->info.i_pos += M2F2_SECTOR_SIZE;
00171
00172 switch ( read_status ) {
00173 case READ_END:
00174
00175
00176
00177
00178
00179 #if 0
00180 if ( p_access->info.i_pos != p_access->info.i_size ) {
00181 msg_Warn( p_access,
00182 "At end but pos (%llu) is not size (%llu). Adjusting.",
00183 p_access->info.i_pos, p_access->info.i_size );
00184 p_access->info.i_pos = p_access->info.i_size;
00185 }
00186 #endif
00187
00188 block_Release( p_block );
00189 return NULL;
00190
00191 case READ_ERROR:
00192
00193
00194 block_Release( p_block );
00195 return NULL;
00196 case READ_STILL_FRAME:
00197 {
00198
00199
00200
00201 #if 1
00202 msleep( MILLISECONDS_PER_SEC * *p_buf );
00203 VCDSetOrigin(p_access, p_vcdplayer->origin_lsn, p_vcdplayer->i_track,
00204 &(p_vcdplayer->play_item));
00205
00206 dbg_print(INPUT_DBG_STILL, "still wait time done");
00207 #else
00208 vcdIntfStillTime(p_vcdplayer->p_intf, *p_buf);
00209 #endif
00210
00211 block_Release( p_block );
00212 return NULL;
00213 }
00214
00215 default:
00216 case READ_BLOCK:
00217
00218 ;
00219 }
00220
00221 p_buf += M2F2_SECTOR_SIZE;
00222
00223 if ( VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type )
00224 {
00225 unsigned int i_entry = p_vcdplayer->play_item.num+1;
00226 lsn_t i_lsn = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i_entry);
00227 if ( p_vcdplayer->i_lsn >= i_lsn && i_lsn != VCDINFO_NULL_LSN )
00228 {
00229 const track_t i_track = p_vcdplayer->i_track;
00230
00231 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
00232 "entry change to %d, current LSN %u >= end %u",
00233 i_entry, p_vcdplayer->i_lsn, i_lsn);
00234
00235 p_vcdplayer->play_item.num = i_entry;
00236
00237 VCDSetOrigin( p_access, i_lsn, i_track,
00238 &(p_vcdplayer->play_item) );
00239 }
00240 }
00241 }
00242
00243 return p_block;
00244 }
00245
00246
00247
00248
00249
00250 int
00251 VCDSeek( access_t * p_access, int64_t i_pos )
00252 {
00253 if (!p_access || !p_access->p_sys) return VLC_EGENERIC;
00254
00255 {
00256 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys;
00257 const input_title_t *t = p_vcdplayer->p_title[p_access->info.i_title];
00258 unsigned int i_entry = VCDINFO_INVALID_ENTRY;
00259 int i_seekpoint;
00260
00261
00262 p_access->info.i_pos = i_pos;
00263 p_vcdplayer->i_lsn = (i_pos / (int64_t) M2F2_SECTOR_SIZE) +
00264 p_vcdplayer->origin_lsn;
00265
00266 switch (p_vcdplayer->play_item.type) {
00267 case VCDINFO_ITEM_TYPE_TRACK:
00268 case VCDINFO_ITEM_TYPE_ENTRY:
00269 break ;
00270 default:
00271 p_vcdplayer->b_valid_ep = VLC_FALSE;
00272 }
00273
00274
00275 if( p_vcdplayer->b_valid_ep )
00276 {
00277 for( i_entry = 0 ; i_entry < p_vcdplayer->i_entries ; i_entry ++ )
00278 {
00279 if( p_vcdplayer->i_lsn < p_vcdplayer->p_entries[i_entry] )
00280 {
00281 VCDUpdateVar( p_access, i_entry, VLC_VAR_SETVALUE,
00282 "chapter", _("Entry"), "Setting entry" );
00283 break;
00284 }
00285 }
00286
00287 {
00288 vcdinfo_itemid_t itemid;
00289 itemid.num = i_entry;
00290 itemid.type = VCDINFO_ITEM_TYPE_ENTRY;
00291 VCDSetOrigin(p_access, p_vcdplayer->i_lsn, p_vcdplayer->i_track,
00292 &itemid);
00293 }
00294 }
00295
00296 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
00297 "orig %lu, cur: %lu, offset: %lld, entry %d",
00298 (long unsigned int) p_vcdplayer->origin_lsn,
00299 (long unsigned int) p_vcdplayer->i_lsn, i_pos,
00300 i_entry );
00301
00302
00303 for( i_seekpoint = 0; i_seekpoint < t->i_seekpoint; i_seekpoint++ )
00304 {
00305 if( i_seekpoint + 1 >= t->i_seekpoint ) break;
00306 if( i_pos < t->seekpoint[i_seekpoint + 1]->i_byte_offset ) break;
00307 }
00308
00309
00310 if( i_seekpoint != p_access->info.i_seekpoint )
00311 {
00312 dbg_print( (INPUT_DBG_SEEK), "seekpoint change %lu",
00313 (long unsigned int) i_seekpoint );
00314 p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;
00315 p_access->info.i_seekpoint = i_seekpoint;
00316 }
00317
00318 }
00319 return VLC_SUCCESS;
00320
00321 }
00322
00323
00324
00325
00326
00327
00328 static vlc_bool_t
00329 VCDEntryPoints( access_t * p_access )
00330 {
00331 if (!p_access || !p_access->p_sys) return VLC_FALSE;
00332
00333 {
00334 vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
00335 const unsigned int i_entries =
00336 vcdinfo_get_num_entries(p_vcdplayer->vcd);
00337 const track_t i_last_track
00338 = cdio_get_num_tracks(vcdinfo_get_cd_image(p_vcdplayer->vcd))
00339 + cdio_get_first_track_num(vcdinfo_get_cd_image(p_vcdplayer->vcd));
00340 unsigned int i;
00341
00342 if (0 == i_entries) {
00343 LOG_ERR ("no entires found -- something is wrong" );
00344 return VLC_FALSE;
00345 }
00346
00347 p_vcdplayer->p_entries = malloc( sizeof( lsn_t ) * i_entries );
00348
00349 if( p_vcdplayer->p_entries == NULL )
00350 {
00351 LOG_ERR ("not enough memory for entry points treatment" );
00352 return VLC_FALSE;
00353 }
00354
00355 p_vcdplayer->i_entries = i_entries;
00356
00357 for( i = 0 ; i < i_entries ; i++ )
00358 {
00359 const track_t i_track = vcdinfo_get_track(p_vcdplayer->vcd, i);
00360 if( i_track <= i_last_track ) {
00361 seekpoint_t *s = vlc_seekpoint_New();
00362 char psz_entry[100];
00363
00364 snprintf(psz_entry, sizeof(psz_entry), "%s%02d", _("Entry "), i );
00365
00366 p_vcdplayer->p_entries[i] = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i);
00367
00368 s->psz_name = strdup(psz_entry);
00369 s->i_byte_offset =
00370 (p_vcdplayer->p_entries[i] - vcdinfo_get_track_lsn(p_vcdplayer->vcd, i_track))
00371 * M2F2_SECTOR_SIZE;
00372
00373 dbg_print( INPUT_DBG_MRL,
00374 "%s, lsn %d, byte_offset %ld",
00375 s->psz_name, p_vcdplayer->p_entries[i],
00376 (unsigned long int) s->i_byte_offset);
00377 TAB_APPEND( p_vcdplayer->p_title[i_track-1]->i_seekpoint,
00378 p_vcdplayer->p_title[i_track-1]->seekpoint, s );
00379
00380 } else
00381 msg_Warn( p_access, "wrong track number found in entry points" );
00382 }
00383 p_vcdplayer->b_valid_ep = VLC_TRUE;
00384 return VLC_TRUE;
00385 }
00386 }
00387
00388
00389
00390
00391 static vlc_bool_t
00392 VCDSegments( access_t * p_access )
00393 {
00394 vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
00395 unsigned int i;
00396 input_title_t *t;
00397
00398 p_vcdplayer->i_segments = vcdinfo_get_num_segments(p_vcdplayer->vcd);
00399
00400 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),
00401 "Segments: %d", p_vcdplayer->i_segments);
00402
00403 if ( 0 == p_vcdplayer->i_segments ) return VLC_FALSE;
00404
00405 t = p_vcdplayer->p_title[p_vcdplayer->i_titles] = vlc_input_title_New();
00406 p_vcdplayer->i_titles++;
00407
00408 t->i_size = 0;
00409 t->psz_name = strdup(_("Segments"));
00410
00411
00412
00413
00414 p_vcdplayer->p_segments =
00415 malloc( sizeof( lsn_t ) * (p_vcdplayer->i_segments+1) );
00416 if( p_vcdplayer->p_segments == NULL )
00417 {
00418 LOG_ERR ("not enough memory for segment treatment" );
00419 return VLC_FALSE;
00420 }
00421
00422 for( i = 0 ; i < p_vcdplayer->i_segments ; i++ )
00423 {
00424 char psz_segment[100];
00425 seekpoint_t *s = vlc_seekpoint_New();
00426 p_vcdplayer->p_segments[i] = vcdinfo_get_seg_lsn(p_vcdplayer->vcd, i);
00427
00428 snprintf( psz_segment, sizeof(psz_segment), "%s%02d", _("Segment "),
00429 i );
00430
00431 s->i_byte_offset = 0;
00432 s->psz_name = strdup(psz_segment);
00433 TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
00434 }
00435
00436 p_vcdplayer->p_segments[p_vcdplayer->i_segments] =
00437 p_vcdplayer->p_segments[p_vcdplayer->i_segments-1]+
00438 vcdinfo_get_seg_sector_count(p_vcdplayer->vcd,
00439 p_vcdplayer->i_segments-1);
00440
00441 return VLC_TRUE;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450 static int
00451 VCDTitles( access_t * p_access )
00452 {
00453
00454
00455
00456
00457
00458
00459 if (!p_access || !p_access->p_sys) return VLC_EGENERIC;
00460
00461 {
00462 vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
00463 track_t i;
00464
00465 p_vcdplayer->i_titles = 0;
00466 for( i = 1 ; i <= p_vcdplayer->i_tracks ; i++ )
00467 {
00468 input_title_t *t = p_vcdplayer->p_title[i-1] =
00469 vlc_input_title_New();
00470 char psz_track[80];
00471
00472 snprintf( psz_track, sizeof(psz_track), "%s%02d", _("Track "),
00473 i );
00474 t->i_size = (int64_t) vcdinfo_get_track_size( p_vcdplayer->vcd,
00475 i )
00476 * M2F2_SECTOR_SIZE / CDIO_CD_FRAMESIZE ;
00477 t->psz_name = strdup(psz_track);
00478
00479 dbg_print( INPUT_DBG_MRL, "track[%d] i_size: %lld", i, t->i_size );
00480
00481 p_vcdplayer->i_titles++;
00482 }
00483
00484 return VLC_SUCCESS;
00485 }
00486 }
00487
00488
00489
00490
00491 static vlc_bool_t
00492 VCDLIDs( access_t * p_access )
00493 {
00494 vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
00495 input_title_t *t;
00496 unsigned int i_lid, i_title;
00497
00498 p_vcdplayer->i_lids = vcdinfo_get_num_LIDs(p_vcdplayer->vcd);
00499 p_vcdplayer->i_lid = VCDINFO_INVALID_ENTRY;
00500
00501 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),
00502 "LIDs: %d", p_vcdplayer->i_lids);
00503
00504 if ( 0 == p_vcdplayer->i_lids ) return VLC_FALSE;
00505
00506 if (vcdinfo_read_psd (p_vcdplayer->vcd)) {
00507
00508 vcdinfo_visit_lot (p_vcdplayer->vcd, false);
00509
00510 #if FIXED
00511
00512
00513
00514
00515
00516
00517 if (vcdinfo_get_psd_x_size(p_vcdplayer->vcd))
00518 vcdinfo_visit_lot (p_vcdplayer->vcd, VLC_TRUE);
00519 #endif
00520 }
00521
00522
00523 t = vlc_input_title_New();
00524 t->b_menu = VLC_TRUE;
00525 t->psz_name = strdup( "LIDs" );
00526
00527 i_title = p_vcdplayer->i_tracks;
00528 for( i_lid = 1 ; i_lid <= p_vcdplayer->i_lids ; i_lid++ )
00529 {
00530 char psz_lid[100];
00531 seekpoint_t *s = vlc_seekpoint_New();
00532
00533 snprintf( psz_lid, sizeof(psz_lid), "%s%02d", _("LID "),
00534 i_lid );
00535
00536 s->i_byte_offset = 0;
00537
00538 s->psz_name = strdup(psz_lid);
00539 TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
00540 }
00541
00542 #if DYNAMICALLY_ALLOCATED
00543 TAB_APPEND( p_vcdplayer->i_titles, p_vcdplayer->p_title, t );
00544 #else
00545 p_vcdplayer->p_title[p_vcdplayer->i_titles] = t;
00546 p_vcdplayer->i_titles++;
00547 #endif
00548
00549 return VLC_TRUE;
00550 }
00551
00552
00553
00554
00555 static char *
00556 VCDParse( access_t * p_access, vcdinfo_itemid_t * p_itemid,
00557 vlc_bool_t *play_single_item )
00558 {
00559 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
00560 char *psz_parser;
00561 char *psz_source;
00562 char *psz_next;
00563
00564 if( config_GetInt( p_access, MODULE_STRING "-PBC" ) ) {
00565 p_itemid->type = VCDINFO_ITEM_TYPE_LID;
00566 p_itemid->num = 1;
00567 *play_single_item = VLC_FALSE;
00568 }
00569 else
00570 {
00571 p_itemid->type = VCDINFO_ITEM_TYPE_ENTRY;
00572 p_itemid->num = 0;
00573 }
00574
00575 #ifdef WIN32
00576
00577
00578 if( !p_access->psz_access || !*p_access->psz_access ) return NULL;
00579 #endif
00580
00581 if( !p_access->psz_path )
00582 {
00583 return NULL;
00584 }
00585
00586 psz_parser = psz_source = strdup( p_access->psz_path );
00587
00588
00589
00590 while( *psz_parser && *psz_parser != '@' )
00591 {
00592 psz_parser++;
00593 }
00594
00595 if( *psz_parser == '@' )
00596 {
00597
00598
00599 unsigned int num;
00600
00601 *psz_parser = '\0';
00602 ++psz_parser;
00603 if( *psz_parser )
00604 {
00605 switch(*psz_parser) {
00606 case 'E':
00607 p_itemid->type = VCDINFO_ITEM_TYPE_ENTRY;
00608 ++psz_parser;
00609 *play_single_item = VLC_TRUE;
00610 break;
00611 case 'P':
00612 p_itemid->type = VCDINFO_ITEM_TYPE_LID;
00613 ++psz_parser;
00614 *play_single_item = VLC_FALSE;
00615 break;
00616 case 'S':
00617 p_itemid->type = VCDINFO_ITEM_TYPE_SEGMENT;
00618 ++psz_parser;
00619 *play_single_item = VLC_TRUE;
00620 break;
00621 case 'T':
00622 p_itemid->type = VCDINFO_ITEM_TYPE_TRACK;
00623 ++psz_parser;
00624 *play_single_item = VLC_TRUE;
00625 break;
00626 default: ;
00627 }
00628 }
00629
00630 num = strtol( psz_parser, &psz_next, 10 );
00631 if ( *psz_parser != '\0' && *psz_next == '\0')
00632 {
00633 p_itemid->num = num;
00634 }
00635
00636 } else {
00637 *play_single_item = ( VCDINFO_ITEM_TYPE_LID == p_itemid->type );
00638 }
00639
00640
00641 if( !*psz_source ) {
00642
00643
00644 if( !p_access->psz_access ) return NULL;
00645
00646 psz_source = config_GetPsz( p_access, "vcd" );
00647
00648 if( !psz_source || 0==strlen(psz_source) ) {
00649
00650 char **cd_drives = cdio_get_devices_with_cap( NULL,
00651 ( CDIO_FS_ANAL_SVCD | CDIO_FS_ANAL_CVD
00652 |CDIO_FS_ANAL_VIDEOCD | CDIO_FS_UNKNOWN ),
00653 VLC_TRUE );
00654 if( NULL == cd_drives ) return NULL;
00655 if( cd_drives[0] == NULL )
00656 {
00657 cdio_free_device_list( cd_drives );
00658 return NULL;
00659 }
00660 psz_source = strdup( cd_drives[0] );
00661 cdio_free_device_list( cd_drives );
00662 }
00663 }
00664
00665 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),
00666 "source=%s entry=%d type=%d",
00667 psz_source, p_itemid->num, p_itemid->type);
00668
00669 return psz_source;
00670 }
00671
00672
00673
00674
00675 void
00676 VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track,
00677 const vcdinfo_itemid_t *p_itemid )
00678 {
00679 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
00680
00681 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_LSN),
00682 "i_lsn: %lu, track: %d", (long unsigned int) i_lsn,
00683 i_track );
00684
00685 vcdplayer_set_origin(p_access, i_lsn, i_track, p_itemid);
00686
00687 switch (p_vcdplayer->play_item.type) {
00688 case VCDINFO_ITEM_TYPE_ENTRY:
00689 VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE,
00690 "chapter", _("Entry"), "Setting entry/segment");
00691 p_access->info.i_title = i_track-1;
00692 if (p_vcdplayer->b_track_length)
00693 {
00694 p_access->info.i_size = p_vcdplayer->p_title[i_track-1]->i_size;
00695 p_access->info.i_pos = (int64_t) M2F2_SECTOR_SIZE *
00696 (vcdinfo_get_track_lsn(p_vcdplayer->vcd, i_track) - i_lsn) ;
00697 } else {
00698 p_access->info.i_size = M2F2_SECTOR_SIZE * (int64_t)
00699 vcdinfo_get_entry_sect_count(p_vcdplayer->vcd, p_itemid->num);
00700 p_access->info.i_pos = 0;
00701 }
00702 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "size: %llu, pos: %llu",
00703 p_access->info.i_size, p_access->info.i_pos );
00704 p_access->info.i_seekpoint = p_itemid->num;
00705 break;
00706
00707 case VCDINFO_ITEM_TYPE_SEGMENT:
00708 VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE,
00709 "chapter", _("Segment"), "Setting entry/segment");
00710
00711
00712
00713
00714 p_access->info.i_title = p_vcdplayer->i_titles - 1;
00715 p_access->info.i_size = 0;
00716 p_access->info.i_pos = 0;
00717 p_access->info.i_seekpoint = p_vcdplayer->i_entries
00718 + p_vcdplayer->i_lids + p_itemid->num;
00719 break;
00720
00721 case VCDINFO_ITEM_TYPE_TRACK:
00722 p_access->info.i_title = i_track-1;
00723 p_access->info.i_size = p_vcdplayer->p_title[i_track-1]->i_size;
00724 p_access->info.i_pos = 0;
00725 p_access->info.i_seekpoint = vcdinfo_track_get_entry(p_vcdplayer->vcd,
00726 i_track);
00727 break;
00728
00729 default:
00730 msg_Warn( p_access, "can't set origin for play type %d",
00731 p_vcdplayer->play_item.type );
00732 }
00733
00734 p_access->info.i_update = INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE
00735 | INPUT_UPDATE_SEEKPOINT;
00736
00737 VCDUpdateTitle( p_access );
00738
00739 }
00740
00741
00742
00743
00744
00745 static vcdinfo_obj_t *
00746 vcd_Open( vlc_object_t *p_this, const char *psz_dev )
00747 {
00748 access_t *p_access = (access_t *)p_this;
00749 vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
00750 vcdinfo_obj_t *p_vcdobj;
00751 char *actual_dev;
00752 unsigned int i;
00753
00754 dbg_print(INPUT_DBG_CALL, "called with %s", psz_dev);
00755
00756 if( !psz_dev ) return NULL;
00757
00758 actual_dev=strdup(psz_dev);
00759 if ( vcdinfo_open(&p_vcdobj, &actual_dev, DRIVER_UNKNOWN, NULL) !=
00760 VCDINFO_OPEN_VCD) {
00761 free(actual_dev);
00762 return NULL;
00763 }
00764 free(actual_dev);
00765
00766
00767
00768
00769
00770 if ( 0 < (p_vcdplayer->i_tracks = vcdinfo_get_num_tracks(p_vcdobj)) ) {
00771 p_vcdplayer->track = (vcdplayer_play_item_info_t *)
00772 calloc(p_vcdplayer->i_tracks, sizeof(vcdplayer_play_item_info_t));
00773
00774 for (i=0; i<p_vcdplayer->i_tracks; i++) {
00775 unsigned int track_num=i+1;
00776 p_vcdplayer->track[i].size =
00777 vcdinfo_get_track_sect_count(p_vcdobj, track_num);
00778 p_vcdplayer->track[i].start_LSN =
00779 vcdinfo_get_track_lsn(p_vcdobj, track_num);
00780 }
00781 } else
00782 p_vcdplayer->track = NULL;
00783
00784 if ( 0 < (p_vcdplayer->i_entries = vcdinfo_get_num_entries(p_vcdobj)) ) {
00785 p_vcdplayer->entry = (vcdplayer_play_item_info_t *)
00786 calloc(p_vcdplayer->i_entries, sizeof(vcdplayer_play_item_info_t));
00787
00788 for (i=0; i<p_vcdplayer->i_entries; i++) {
00789 p_vcdplayer->entry[i].size =
00790 vcdinfo_get_entry_sect_count(p_vcdobj, i);
00791 p_vcdplayer->entry[i].start_LSN = vcdinfo_get_entry_lsn(p_vcdobj, i);
00792 }
00793 } else
00794 p_vcdplayer->entry = NULL;
00795
00796 if ( 0 < (p_vcdplayer->i_segments = vcdinfo_get_num_segments(p_vcdobj)) ) {
00797 p_vcdplayer->segment = (vcdplayer_play_item_info_t *)
00798 calloc(p_vcdplayer->i_segments, sizeof(vcdplayer_play_item_info_t));
00799
00800 for (i=0; i<p_vcdplayer->i_segments; i++) {
00801 p_vcdplayer->segment[i].size =
00802 vcdinfo_get_seg_sector_count(p_vcdobj, i);
00803 p_vcdplayer->segment[i].start_LSN = vcdinfo_get_seg_lsn(p_vcdobj, i);
00804 }
00805 } else
00806 p_vcdplayer->segment = NULL;
00807
00808 return p_vcdobj;
00809 }
00810
00811
00812
00813
00814 static void
00815 VCDUpdateVar( access_t *p_access, int i_num, int i_action,
00816 const char *p_varname, char *p_label,
00817 const char *p_debug_label)
00818 {
00819 vlc_value_t val;
00820 val.i_int = i_num;
00821 if (p_access) {
00822 const vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys;
00823 dbg_print( INPUT_DBG_PBC, "%s %d", p_debug_label, i_num );
00824 }
00825 if (p_label) {
00826 vlc_value_t text;
00827 text.psz_string = p_label;
00828 var_Change( p_access, p_varname, VLC_VAR_SETTEXT, &text, NULL );
00829 }
00830 var_Change( p_access, p_varname, i_action, &val, NULL );
00831 }
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847 int
00848 VCDOpen ( vlc_object_t *p_this )
00849 {
00850 access_t *p_access = (access_t *)p_this;
00851 vcdplayer_t *p_vcdplayer;
00852 char *psz_source;
00853 vcdinfo_itemid_t itemid;
00854 vlc_bool_t play_single_item = VLC_FALSE;
00855
00856 p_access->pf_read = NULL;
00857 p_access->pf_block = VCDReadBlock;
00858 p_access->pf_control = VCDControl;
00859 p_access->pf_seek = VCDSeek;
00860
00861 p_access->info.i_update = 0;
00862 p_access->info.i_size = 0;
00863 p_access->info.i_pos = 0;
00864 p_access->info.b_eof = VLC_FALSE;
00865 p_access->info.i_title = 0;
00866 p_access->info.i_seekpoint = 0;
00867
00868 p_vcdplayer = malloc( sizeof(vcdplayer_t) );
00869
00870 if( p_vcdplayer == NULL )
00871 {
00872 LOG_ERR ("out of memory" );
00873 return VLC_ENOMEM;
00874 }
00875
00876 p_vcdplayer->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
00877 p_access->p_sys = (access_sys_t *) p_vcdplayer;
00878
00879
00880 p_vcd_access = p_access;
00881 cdio_log_set_handler ( cdio_log_handler );
00882 vcd_log_set_handler ( vcd_log_handler );
00883
00884 psz_source = VCDParse( p_access, &itemid, &play_single_item );
00885
00886 if ( NULL == psz_source )
00887 {
00888 free( p_vcdplayer );
00889 return( VLC_EGENERIC );
00890 }
00891
00892 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "source: %s: mrl: %s",
00893 psz_source, p_access->psz_path );
00894
00895 p_vcdplayer->psz_source = strdup(psz_source);
00896 p_vcdplayer->i_blocks_per_read = config_GetInt( p_this, MODULE_STRING
00897 "-blocks-per-read" );
00898 p_vcdplayer->b_track_length = config_GetInt( p_this, MODULE_STRING
00899 "-track-length" );
00900 p_vcdplayer->in_still = VLC_FALSE;
00901 p_vcdplayer->play_item.type = VCDINFO_ITEM_TYPE_NOTFOUND;
00902 p_vcdplayer->p_input = vlc_object_find( p_access,
00903 VLC_OBJECT_INPUT,
00904 FIND_PARENT );
00905 p_vcdplayer->p_meta = vlc_meta_New();
00906 p_vcdplayer->p_segments = NULL;
00907 p_vcdplayer->p_entries = NULL;
00908
00909
00910
00911 if( !(p_vcdplayer->vcd = vcd_Open( p_this, psz_source )) )
00912 {
00913 goto err_exit;
00914 }
00915
00916 p_vcdplayer->b_svd= (vlc_bool_t) vcdinfo_get_tracksSVD(p_vcdplayer->vcd);;
00917
00918
00919 p_vcdplayer->i_tracks = vcdinfo_get_num_tracks(p_vcdplayer->vcd);
00920
00921 if( p_vcdplayer->i_tracks < 1 || CDIO_INVALID_TRACK == p_vcdplayer->i_tracks ) {
00922 vcdinfo_close( p_vcdplayer->vcd );
00923 LOG_ERR ("no movie tracks found" );
00924 goto err_exit;
00925 }
00926
00927
00928 VCDTitles( p_access );
00929
00930
00931 if( ! VCDEntryPoints( p_access ) )
00932 {
00933 msg_Warn( p_access, "could not read entry points, will not use them" );
00934 p_vcdplayer->b_valid_ep = VLC_FALSE;
00935 }
00936
00937
00938 if( ! VCDLIDs( p_access ) )
00939 {
00940 msg_Warn( p_access, "could not read entry LIDs" );
00941 }
00942
00943
00944 p_vcdplayer->i_lid =
00945 ( VCDINFO_ITEM_TYPE_LID == itemid.type
00946 && p_vcdplayer->i_lids > itemid.num )
00947 ? itemid.num
00948 : VCDINFO_INVALID_ENTRY;
00949
00950
00951 VCDSegments( p_access );
00952
00953 vcdplayer_play( p_access, itemid );
00954
00955 p_access->psz_demux = strdup( "ps" );
00956
00957 #if FIXED
00958 if (play_single_item)
00959 VCDFixupPlayList( p_access, p_vcd, psz_source, &itemid,
00960 play_single_item );
00961 #endif
00962
00963 #if FIXED
00964 p_vcdplayer->p_intf = intf_Create( p_access, "vcdx" );
00965 p_vcdplayer->p_intf->b_block = VLC_FALSE;
00966 #endif
00967 p_vcdplayer->p_access = p_access;
00968
00969 #ifdef FIXED
00970 intf_RunThread( p_vcdplayer->p_intf );
00971 #endif
00972
00973 free( psz_source );
00974
00975 return VLC_SUCCESS;
00976 err_exit:
00977 if( p_vcdplayer->p_input ) vlc_object_release( p_vcdplayer->p_input );
00978 free( psz_source );
00979 free( p_vcdplayer );
00980 return VLC_EGENERIC;
00981 }
00982
00983
00984
00985
00986 void
00987 VCDClose ( vlc_object_t *p_this )
00988 {
00989 access_t *p_access = (access_t *)p_this;
00990 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
00991
00992 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "VCDClose" );
00993
00994 {
00995 unsigned int i;
00996 for (i=0 ; i<p_vcdplayer->i_titles; i++)
00997 if (p_vcdplayer->p_title[i])
00998 free(p_vcdplayer->p_title[i]->psz_name);
00999 }
01000
01001 vcdinfo_close( p_vcdplayer->vcd );
01002
01003 if( p_vcdplayer->p_input ) vlc_object_release( p_vcdplayer->p_input );
01004
01005 FREE_AND_NULL( p_vcdplayer->p_entries );
01006 FREE_AND_NULL( p_vcdplayer->p_segments );
01007 FREE_AND_NULL( p_vcdplayer->psz_source );
01008 FREE_AND_NULL( p_vcdplayer->track );
01009 FREE_AND_NULL( p_vcdplayer->segment );
01010 FREE_AND_NULL( p_vcdplayer->entry );
01011 FREE_AND_NULL( p_access->psz_demux );
01012 FREE_AND_NULL( p_vcdplayer );
01013 p_vcd_access = NULL;
01014 }
01015
01016
01017
01018
01019
01020
01021 static int VCDControl( access_t *p_access, int i_query, va_list args )
01022 {
01023 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
01024 int *pi_int;
01025 int i;
01026
01027 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
01028 "query %d", i_query );
01029
01030 switch( i_query )
01031 {
01032
01033
01034
01035 case ACCESS_GET_META:
01036 {
01037 vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
01038
01039 dbg_print( INPUT_DBG_EVENT, "get meta info" );
01040
01041 if ( p_vcdplayer->p_meta ) {
01042 *pp_meta = vlc_meta_Duplicate( p_vcdplayer->p_meta );
01043 dbg_print( INPUT_DBG_META, "%s", "Meta copied" );
01044 } else
01045 msg_Warn( p_access, "tried to copy NULL meta info" );
01046
01047 return VLC_SUCCESS;
01048 }
01049 return VLC_EGENERIC;
01050
01051 case ACCESS_CAN_SEEK:
01052 case ACCESS_CAN_FASTSEEK:
01053 case ACCESS_CAN_PAUSE:
01054 case ACCESS_CAN_CONTROL_PACE:
01055 {
01056 vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
01057
01058 dbg_print( INPUT_DBG_EVENT,
01059 "seek/fastseek/pause/can_control_pace" );
01060 *pb_bool = VLC_TRUE;
01061 return VLC_SUCCESS;
01062 break;
01063 }
01064
01065
01066 case ACCESS_GET_MTU:
01067 pi_int = (int*)va_arg( args, int * );
01068 *pi_int = (p_vcdplayer->i_blocks_per_read * M2F2_SECTOR_SIZE);
01069 dbg_print( INPUT_DBG_EVENT, "GET MTU: %d", *pi_int );
01070 break;
01071
01072 case ACCESS_GET_PTS_DELAY:
01073 {
01074 int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
01075 *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
01076 * MILLISECONDS_PER_SEC;
01077 dbg_print( INPUT_DBG_EVENT, "GET PTS DELAY" );
01078 return VLC_SUCCESS;
01079 break;
01080 }
01081
01082
01083 case ACCESS_SET_PAUSE_STATE:
01084 dbg_print( INPUT_DBG_EVENT, "SET PAUSE STATE" );
01085 return VLC_SUCCESS;
01086 break;
01087
01088 case ACCESS_GET_TITLE_INFO:
01089 {
01090 unsigned int psz_mrl_max = strlen(VCD_MRL_PREFIX)
01091 + strlen(p_vcdplayer->psz_source) + sizeof("@E999")+3;
01092 input_title_t ***ppp_title
01093 = (input_title_t***)va_arg( args, input_title_t*** );
01094 char *psz_mrl = malloc( psz_mrl_max );
01095 unsigned int i;
01096
01097 pi_int = (int*)va_arg( args, int* );
01098
01099 dbg_print( INPUT_DBG_EVENT, "GET TITLE: i_titles %d",
01100 p_vcdplayer->i_titles );
01101
01102 if( psz_mrl == NULL ) {
01103 msg_Warn( p_access, "out of memory" );
01104 } else {
01105 snprintf(psz_mrl, psz_mrl_max, "%s%s",
01106 VCD_MRL_PREFIX, p_vcdplayer->psz_source);
01107 VCDMetaInfo( p_access, psz_mrl );
01108 free(psz_mrl);
01109 }
01110
01111
01112 if( p_vcdplayer->i_titles == 0 )
01113 {
01114 *pi_int = 0; ppp_title = NULL;
01115 return VLC_SUCCESS;
01116 }
01117 *pi_int = p_vcdplayer->i_titles;
01118 *ppp_title = malloc( sizeof( input_title_t **)
01119 * p_vcdplayer->i_titles );
01120
01121 if (!*ppp_title) return VLC_ENOMEM;
01122
01123 for( i = 0; i < p_vcdplayer->i_titles; i++ )
01124 {
01125 if ( p_vcdplayer->p_title[i] )
01126 (*ppp_title)[i] =
01127 vlc_input_title_Duplicate( p_vcdplayer->p_title[i] );
01128 }
01129 }
01130 break;
01131
01132 case ACCESS_SET_TITLE:
01133 i = (int)va_arg( args, int );
01134
01135 dbg_print( INPUT_DBG_EVENT, "set title %d" , i);
01136 if( i != p_access->info.i_title )
01137 {
01138 vcdinfo_itemid_t itemid;
01139 track_t i_track = i+1;
01140 unsigned int i_entry =
01141 vcdinfo_track_get_entry( p_vcdplayer->vcd, i_track);
01142
01143 if( i < p_vcdplayer->i_tracks )
01144 {
01145
01146
01147 itemid.num = i_track;
01148 itemid.type = VCDINFO_ITEM_TYPE_TRACK;
01149 }
01150 else
01151 {
01152
01153
01154
01155
01156
01157 msg_Warn( p_access,
01158 "Trying to set track (%u) beyond end of last track (%u).",
01159 i+1, p_vcdplayer->i_tracks );
01160 return VLC_EGENERIC;
01161 }
01162
01163 VCDSetOrigin(p_access,
01164 vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i_entry),
01165 i_track, &itemid );
01166 }
01167 break;
01168
01169 case ACCESS_SET_SEEKPOINT:
01170 {
01171 input_title_t *t = p_vcdplayer->p_title[p_access->info.i_title];
01172 unsigned int i = (unsigned int)va_arg( args, unsigned int );
01173
01174 dbg_print( INPUT_DBG_EVENT, "set seekpoint %d", i );
01175 if( t->i_seekpoint > 0 )
01176 {
01177 track_t i_track = p_access->info.i_title+1;
01178 lsn_t lsn;
01179
01180
01181
01182
01183
01184
01185
01186 if (i < p_vcdplayer->i_entries)
01187 {
01188 p_vcdplayer->play_item.num = i;
01189 p_vcdplayer->play_item.type = VCDINFO_ITEM_TYPE_ENTRY;
01190 lsn = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i);
01191 } else if ( i < p_vcdplayer->i_entries + p_vcdplayer->i_lids )
01192 {
01193 p_vcdplayer->play_item.num = i
01194 = i - p_vcdplayer->i_entries;
01195 p_vcdplayer->play_item.type = VCDINFO_ITEM_TYPE_LID;
01196 lsn = 0;
01197 } else
01198 {
01199 p_vcdplayer->play_item.num = i
01200 = i - p_vcdplayer->i_entries - p_vcdplayer->i_lids;
01201 p_vcdplayer->play_item.type = VCDINFO_ITEM_TYPE_SEGMENT;
01202 lsn = vcdinfo_get_seg_lsn(p_vcdplayer->vcd, i);
01203 }
01204
01205 VCDSetOrigin( p_access,
01206 vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i),
01207 i_track, &(p_vcdplayer->play_item) );
01208 }
01209 return VLC_SUCCESS;
01210 }
01211
01212 case ACCESS_SET_PRIVATE_ID_STATE:
01213 dbg_print( INPUT_DBG_EVENT, "set private id" );
01214 return VLC_EGENERIC;
01215
01216 default:
01217 msg_Warn( p_access, "unimplemented query in control" );
01218 return VLC_EGENERIC;
01219
01220 }
01221 return VLC_SUCCESS;
01222 }