home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2004 April
/
CMCD0404.ISO
/
Software
/
Freeware
/
Multimedia
/
xcd
/
core
/
xcd_media_reader.h
< prev
Wrap
C/C++ Source or Header
|
2002-07-14
|
7KB
|
191 lines
/*************************************************************************
XCD reader class
(currently supports only single mode2 form2 file without error corrections)
Written by Avi Halachmi (avih [avihpit@yahoo.com])
**************************************************************************
*/
#ifndef _XCD_MEDIA_READER_H_
#define _XCD_MEDIA_READER_H_
#include "portab.h"
#include "utils.h"
#define DEFAULT_BUFFER_SIZE_KB 1000
//This class is able to produce a single media stream out of one or two related XCD files.
// current implementation supports single m2f2 file only.
class XCD_Media_Reader{
public:
XCD_Media_Reader(const char* baseFileName, int forceNoSkipEmptySectors=0, int bufferSizeKB=DEFAULT_BUFFER_SIZE_KB);
int isOpenedOK();
long size(){return m_mediaSize;};
long read(void* dest, long mediaPosition, long size);
~XCD_Media_Reader();
long readNext(void* dest, long size){return read(dest, m_mediaPosition, size);};
long readNonStripped(void* dest, long position, long size); // for direct access to the file as seen by the OS.
// int isSVCD();
// int isVCD();
// char* getMediaFileName();
private:
void init(int virtualHeaderSizeByOS=RIFF_SIZE);
long m_posFirstSectorInFile;
long m_posFirstMediaSectorInFile;
int m_forceNoSkipEmptySectors;
FILE* m_m2f1MediaHandle; //header file, should contain auxilary media data
FILE* m_m2f2MediaHandle; //the unprotected media stream itself (if some of the file is unprotected)
char m_sectorBuffer[SECTOR_SIZE];
long m_m2f2FileSize;
long m_mediaSize;
long m_mediaPosition;
};
#define MAX_EMPTY_SECTORS 1000
XCD_Media_Reader::XCD_Media_Reader(const char* baseFileName, int forceNoSkipEmptySectors, int bufferSizeKB){
m_posFirstSectorInFile=m_posFirstMediaSectorInFile=m_forceNoSkipEmptySectors=m_m2f2FileSize=m_mediaSize=-1;
m_mediaPosition=-1;
m_m2f1MediaHandle=m_m2f2MediaHandle=NULL;
m_m2f2MediaHandle=fopen(baseFileName,"rb");
m_forceNoSkipEmptySectors=forceNoSkipEmptySectors;
//currently only m2f2 file is supported.
init(); //default value for init is 44 bytes added by windows as a RIFF header.
// init(0);// use in OSs that don't add virtual headers
}
long XCD_Media_Reader::readNonStripped(void* dest, long position, long size){ // for direct access to the file as seen via the OS.
//should 'overlay' backups when implemented.
if (fseek(m_m2f2MediaHandle, position, SEEK_SET)){//unsuccessfull seek
dprintf ("fseek(%d) NO success\n",position);
return 0;
}
long result=fread(dest, 1, size, m_m2f2MediaHandle);
dprintf ("fread(pos=%d, size=%d)=%d\n",position, size,result);
return result;
}
void XCD_Media_Reader::init(int virtualHeaderSizeByOS){
int i, bytesRead;
m_posFirstSectorInFile=virtualHeaderSizeByOS;
if (!m_forceNoSkipEmptySectors){
//try to find leading empty sectors. currently to cope with S/VCD (identified by subheader)
for (i=0; i<MAX_EMPTY_SECTORS; i++){
if (bytesRead=readSector(m_m2f2MediaHandle, m_posFirstSectorInFile, m_sectorBuffer, i)==SECTOR_SIZE){
if (!isEmptySector(m_sectorBuffer)){
m_posFirstMediaSectorInFile=m_posFirstSectorInFile+i*SECTOR_SIZE;
dprintf ("XCD_Media_Reader::init, sector#%d: Non-Empty\n", i);
break;
} else {
dprintf ("XCD_Media_Reader::init, sector#%d: Empty\n", i);
}
} else {
if (bytesRead<0)
dprintf ("XCD_Media_Reader::init, sector#%d: read ERROR\n", i);
else
dprintf ("XCD_Media_Reader::init, sector#%d: read %d bytes\n", i, bytesRead);
}
}
if (i>=MAX_EMPTY_SECTORS){ // didn't find non-empty sector. fallback to read all sectors (->assumming isEmptySector doesn't work properly).
dprintf ("Too many 'empty' sectors... fallback to 'forceNoSkipEmpty'\n");
m_posFirstMediaSectorInFile=m_posFirstSectorInFile;
}
} else {
dprintf("forced no skip empty sectors. skipped empty sectors detection.");
}
dprintf ("XCD_Media_Reader::init, m_posFirstMediaSectorInFile=%d\n", m_posFirstMediaSectorInFile);
dprintf ("before fsize()\n");
m_m2f2FileSize=fsize(m_m2f2MediaHandle);
m_mediaSize=mediaPosition(m_m2f2FileSize, m_posFirstMediaSectorInFile);
dprintf ("XCD_Media_Reader::init, m2f2FileSize=%d, mediaSize=%d\n",m_m2f2FileSize, m_mediaSize);
}
int XCD_Media_Reader::isOpenedOK(){
// should modify to test also m2f1 file when implemented.
return (m_m2f2MediaHandle!=NULL);
}
//return value is number of bytes actually read.
long XCD_Media_Reader::read(void* dest, long mediaPosition, long size){
long origSize=size;
m_mediaPosition=mediaPosition =min( max(mediaPosition, 0), m_mediaSize);
size =min( max(size, 0), m_mediaSize-mediaPosition);
long actualSize=size;
long actualStart=filePosition(mediaPosition, m_posFirstMediaSectorInFile);
dprintf ("XCD_Media_Reader::read, mediaPos=%d, size=%d, actualSize=%d, actualStart=%d\n",
mediaPosition, origSize, size, actualStart);
// dprintf ("XCD_Media_Reader::read, actualStart=%d\n",actualStart);
long startForPrintf=actualStart;
if (size<= (SECTOR_USER_DATA - mediaPosition%SECTOR_USER_DATA)){ // inside single USER_DATA block
readNonStripped(dest, actualStart, (uint32_t)size);
} else { //extends over more than single USER_DATA block
long firstLength=SECTOR_USER_DATA - mediaPosition%SECTOR_USER_DATA;
readNonStripped(dest, actualStart, (DWORD)firstLength);
size-=firstLength;
dest=(char*)dest+firstLength;
actualStart+=firstLength+SECTOR_EDC+SECTOR_HEADERS;//points to the start of next USER_DATA block
while (size>0){
if (size<=SECTOR_USER_DATA){ // last copy, smaller or equal to USER_DATA size.
readNonStripped(dest, actualStart, (DWORD)size);
break;
} else {
readNonStripped(dest, actualStart, SECTOR_USER_DATA);
size-=SECTOR_USER_DATA;
dest=(char*)dest+SECTOR_USER_DATA;
actualStart+=SECTOR_SIZE;
}
}
}
dprintf ("ActualStart(%d)=%d, returning %d",(long)mediaPosition, (long)startForPrintf, actualSize);
m_mediaPosition+=actualSize;
return actualSize; //should we change that in case we didn't read origSize??
}
XCD_Media_Reader::~XCD_Media_Reader(){
if (m_m2f1MediaHandle){
if (fclose(m_m2f1MediaHandle))
dprintf ("XCD_Media_Reader::~XCD_Media_Reader, Error closing m2f1 media\n");
else
dprintf ("XCD_Media_Reader::~XCD_Media_Reader, closed m2f1 media\n");
} else
dprintf ("XCD_Media_Reader::~XCD_Media_Reader, m2f1 media was not open. not closing\n");
if (m_m2f2MediaHandle){
if (fclose(m_m2f2MediaHandle))
dprintf ("XCD_Media_Reader::~XCD_Media_Reader, Error closing m2f2 media\n");
else
dprintf ("XCD_Media_Reader::~XCD_Media_Reader, closed m2f2 media\n");
} else
dprintf ("XCD_Media_Reader::~XCD_Media_Reader, m2f2 media was not open. not closing\n");
}
#endif