/* $Id: vcdio.c,v 1.3 2004/09/07 19:29:49 valtri Exp $ Copyright (C) 2002, 2003, 2004 Rocky Bernstein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Standard includes */ #include #include #include #include #include #include #include #include #ifdef HAVE_STRINGS_H #include #endif #include #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_VCDNAV #include #include #include #else #include "libvcd/types.h" #include "libvcd/files.h" #include "cdio/iso9660.h" #endif #include "vcdplayer.h" #include "vcdio.h" #define LOG_ERR(this, s, args...) \ if (this != NULL && this->log_err != NULL) \ this->log_err("%s: "s, __func__ , ##args) #define FREE_AND_NULL(ptr) if (NULL != ptr) free(ptr); ptr = NULL; /*! Closes VCD device specified via "this", and also wipes memory of it from it inside "this". */ int vcdio_close(vcdplayer_input_t *this) { this->opened = false; FREE_AND_NULL(this->current_vcd_device); FREE_AND_NULL(this->track); FREE_AND_NULL(this->segment); FREE_AND_NULL(this->entry); return vcdinfo_close(this->vcd); } /*! Opens VCD device and initializes things. - do nothing if the device had already been open and is the same device. - if the device had been open and is a different, close it before trying to open new device. */ bool vcdio_open(vcdplayer_input_t *this, char *intended_vcd_device) { vcdinfo_obj_t *obj = this->vcd; unsigned int i; dbg_print(INPUT_DBG_CALL, "called with %s\n", intended_vcd_device); if ( this->opened ) { if ( strcmp(intended_vcd_device, this->current_vcd_device)==0 ) { /* Already open and the same device, so do nothing */ return true; } else { /* Changing VCD device */ vcdio_close(this); } } if ( vcdinfo_open(&this->vcd, &intended_vcd_device, DRIVER_UNKNOWN, NULL) != VCDINFO_OPEN_VCD) { return false; } obj = this->vcd; this->current_vcd_device=strdup(intended_vcd_device); this->opened = true; this->num_LIDs = vcdinfo_get_num_LIDs(obj); if (vcdinfo_read_psd (obj)) { vcdinfo_visit_lot (obj, false); #if FIXED /* We need to change libvcdinfo to be more robust when there are problems reading the extended PSD. Given that area-highlighting and selection features in the extended PSD haven't been implemented, it's best then to not try to read this at all. */ if (vcdinfo_get_psd_x_size(obj)) vcdinfo_visit_lot (obj, true); #endif } /* Save summary info on tracks, segments and entries... */ if ( 0 < (this->num_tracks = vcdinfo_get_num_tracks(obj)) ) { this->track = (vcdplayer_play_item_info *) calloc(this->num_tracks, sizeof(vcdplayer_play_item_info)); for (i=0; inum_tracks; i++) { unsigned int track_num=i+1; this->track[i].size = vcdinfo_get_track_sect_count(obj, track_num); this->track[i].start_LSN = vcdinfo_get_track_lsn(obj, track_num); } } else this->track = NULL; if ( 0 < (this->num_entries = vcdinfo_get_num_entries(obj)) ) { this->entry = (vcdplayer_play_item_info *) calloc(this->num_entries, sizeof(vcdplayer_play_item_info)); for (i=0; inum_entries; i++) { this->entry[i].size = vcdinfo_get_entry_sect_count(obj, i); this->entry[i].start_LSN = vcdinfo_get_entry_lsn(obj, i); } } else this->entry = NULL; if ( 0 < (this->num_segments = vcdinfo_get_num_segments(obj)) ) { this->segment = (vcdplayer_play_item_info *) calloc(this->num_segments, sizeof(vcdplayer_play_item_info)); for (i=0; inum_segments; i++) { this->segment[i].size = vcdinfo_get_seg_sector_count(obj, i); this->segment[i].start_LSN = vcdinfo_get_seg_lsn(obj, i); } } else this->segment = NULL; return true; } /*! seek position, return new position if seeking failed, -1 is returned */ off_t vcdio_seek (vcdplayer_input_t *this, off_t offset, int origin) { switch (origin) { case SEEK_SET: { lsn_t old_lsn = this->cur_lsn; this->cur_lsn = this->origin_lsn + (offset / M2F2_SECTOR_SIZE); dbg_print(INPUT_DBG_SEEK_SET, "seek_set to %ld => %u (start is %u)\n", (long int) offset, this->cur_lsn, this->origin_lsn); /* Seek was successful. Invalidate entry location by setting entry number back to 1. Over time it will adjust upward to the correct value. */ if ( !vcdplayer_pbc_is_on(this) && this->play_item.type != VCDINFO_ITEM_TYPE_TRACK && this->cur_lsn < old_lsn) { dbg_print(INPUT_DBG_SEEK_SET, "seek_set entry backwards\n"); this->next_entry = 1; } break; } case SEEK_CUR: { off_t diff; if (offset) { LOG_ERR(this, "%s: %d\n", _("SEEK_CUR not implemented for nozero offset"), (int) offset); return (off_t) -1; } if (this->slider_length == VCDPLAYER_SLIDER_LENGTH_TRACK) { diff = this->cur_lsn - this->track_lsn; dbg_print(INPUT_DBG_SEEK_CUR, "current pos: %u, track diff %ld\n", this->cur_lsn, (long int) diff); } else { diff = this->cur_lsn - this->origin_lsn; dbg_print(INPUT_DBG_SEEK_CUR, "current pos: %u, entry diff %ld\n", this->cur_lsn, (long int) diff); } if (diff < 0) { dbg_print(INPUT_DBG_SEEK_CUR, "Error: diff < 0\n"); return (off_t) 0; } else { return (off_t)diff * M2F2_SECTOR_SIZE; } break; } case SEEK_END: LOG_ERR(this, "%s\n", _("SEEK_END not implemented yet.")); return (off_t) -1; default: LOG_ERR(this, "%s %d\n", _("seek not implemented yet for"), origin); return (off_t) -1; } return offset ; /* FIXME */ } /* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */