00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "MP3FileSource.hh"
00022 #include "MP3StreamState.hh"
00023 #include "InputFile.hh"
00024
00026
00027 MP3FileSource::MP3FileSource(UsageEnvironment& env, FILE* fid)
00028 : FramedFileSource(env, fid),
00029 fStreamState(new MP3StreamState(env)) {
00030 }
00031
00032 MP3FileSource::~MP3FileSource() {
00033 delete fStreamState;
00034 }
00035
00036 char const* MP3FileSource::MIMEtype() const {
00037 return "audio/MPEG";
00038 }
00039
00040 MP3FileSource* MP3FileSource::createNew(UsageEnvironment& env, char const* fileName) {
00041 MP3FileSource* newSource = NULL;
00042
00043 do {
00044 FILE* fid;
00045
00046 fid = OpenInputFile(env, fileName);
00047 if (fid == NULL) break;
00048
00049 newSource = new MP3FileSource(env, fid);
00050 if (newSource == NULL) break;
00051
00052 unsigned fileSize = (unsigned)GetFileSize(fileName, fid);
00053 newSource->assignStream(fid, fileSize);
00054 if (!newSource->initializeStream()) break;
00055
00056 return newSource;
00057 } while (0);
00058
00059 Medium::close(newSource);
00060 return NULL;
00061 }
00062
00063 float MP3FileSource::filePlayTime() const {
00064 return fStreamState->filePlayTime();
00065 }
00066
00067 unsigned MP3FileSource::fileSize() const {
00068 return fStreamState->fileSize();
00069 }
00070
00071 void MP3FileSource::setPresentationTimeScale(unsigned scale) {
00072 fStreamState->setPresentationTimeScale(scale);
00073 }
00074
00075 void MP3FileSource::seekWithinFile(double seekNPT, double streamDuration) {
00076 float fileDuration = filePlayTime();
00077
00078
00079 if (seekNPT < 0.0) {
00080 seekNPT = 0.0;
00081 } else if (seekNPT > fileDuration) {
00082 seekNPT = fileDuration;
00083 }
00084 if (streamDuration < 0.0) {
00085 streamDuration = 0.0;
00086 } else if (seekNPT + streamDuration > fileDuration) {
00087 streamDuration = fileDuration - seekNPT;
00088 }
00089
00090 float seekFraction = (float)seekNPT/fileDuration;
00091 unsigned seekByteNumber = fStreamState->getByteNumberFromPositionFraction(seekFraction);
00092 fStreamState->seekWithinFile(seekByteNumber);
00093
00094 fLimitNumBytesToStream = False;
00095 if (streamDuration > 0.0) {
00096 float endFraction = (float)(seekNPT + streamDuration)/fileDuration;
00097 unsigned endByteNumber = fStreamState->getByteNumberFromPositionFraction(endFraction);
00098 if (endByteNumber > seekByteNumber) {
00099 fNumBytesToStream = endByteNumber - seekByteNumber;
00100 fLimitNumBytesToStream = True;
00101 }
00102 } else {
00103 }
00104 }
00105
00106 void MP3FileSource::getAttributes() const {
00107 char buffer[200];
00108 fStreamState->getAttributes(buffer, sizeof buffer);
00109 envir().setResultMsg(buffer);
00110 }
00111
00112 void MP3FileSource::doGetNextFrame() {
00113 if (!doGetNextFrame1()) {
00114 handleClosure(this);
00115 return;
00116 }
00117
00118
00119 #if defined(__WIN32__) || defined(_WIN32)
00120
00121
00122
00123
00124
00125
00126 afterGetting(this);
00127 #else
00128 nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
00129 (TaskFunc*)afterGetting, this);
00130 #endif
00131 }
00132
00133 Boolean MP3FileSource::doGetNextFrame1() {
00134 if (fLimitNumBytesToStream && fNumBytesToStream == 0) return False;
00135
00136 if (!fHaveJustInitialized) {
00137 if (fStreamState->findNextHeader(fPresentationTime) == 0) return False;
00138 } else {
00139 fPresentationTime = fFirstFramePresentationTime;
00140 fHaveJustInitialized = False;
00141 }
00142
00143 if (!fStreamState->readFrame(fTo, fMaxSize, fFrameSize, fDurationInMicroseconds)) {
00144 char tmp[200];
00145 sprintf(tmp,
00146 "Insufficient buffer size %d for reading MPEG audio frame (needed %d)\n",
00147 fMaxSize, fFrameSize);
00148 envir().setResultMsg(tmp);
00149 fFrameSize = fMaxSize;
00150 return False;
00151 }
00152 if (fNumBytesToStream > fFrameSize) fNumBytesToStream -= fFrameSize; else fNumBytesToStream = 0;
00153
00154 return True;
00155 }
00156
00157 void MP3FileSource::assignStream(FILE* fid, unsigned fileSize) {
00158 fStreamState->assignStream(fid, fileSize);
00159 }
00160
00161
00162 Boolean MP3FileSource::initializeStream() {
00163
00164 if (fStreamState->findNextHeader(fFirstFramePresentationTime) == 0) {
00165 envir().setResultMsg("not an MPEG audio file");
00166 return False;
00167 }
00168
00169 fStreamState->checkForXingHeader();
00170
00171 fHaveJustInitialized = True;
00172 fLimitNumBytesToStream = False;
00173 fNumBytesToStream = 0;
00174
00175
00176
00177 envir().setResultMsg(name());
00178 return True;
00179 }