1 #include <InterfaceDefs.h> 2 3 /*============================================================================*/ 4 const char* gAppName = "APE (Monkey's Audio) reader"; 5 const char* gAppVer = "Ver 1.13"; 6 const char* gCright = "Copyright " B_UTF8_COPYRIGHT " 2005-2009 by SHINTA"; 7 const char* gAppSignature = "application/x-vnd.SHINTA-MediaKitAPEReader"; 8 /*============================================================================*/ 9 10 /*=== Memo ===================================================================== 11 ==============================================================================*/ 12 13 //------------------------------------------------------------------------------ 14 #include "APEReader.h" 15 //------------------------------------------------------------------------------ 16 // BeOS 17 // C++ 18 // MAC 19 #include "MACLib.h" 20 // Proj 21 //------------------------------------------------------------------------------ 22 //============================================================================== 23 TAPEReader::TAPEReader() 24 : SUPER() 25 { 26 mDecodedData = NULL; 27 mDecomp = NULL; 28 Unset(); 29 } 30 //------------------------------------------------------------------------------ 31 TAPEReader::~TAPEReader() 32 { 33 } 34 //------------------------------------------------------------------------------ 35 status_t TAPEReader::AllocateCookie(int32 oStreamNumber, void** oCookie) 36 { 37 *oCookie = NULL; 38 return B_OK; 39 } 40 //------------------------------------------------------------------------------ 41 const char* TAPEReader::Copyright() 42 { 43 return gCright; 44 } 45 //------------------------------------------------------------------------------ 46 bigtime_t TAPEReader::CurrentTime() const 47 { 48 return mDecomp->GetInfo(APE_DECOMPRESS_CURRENT_MS)*static_cast<bigtime_t>(1000); 49 } 50 //------------------------------------------------------------------------------ 51 status_t TAPEReader::FreeCookie(void* oCookie) 52 { 53 return B_OK; 54 } 55 //------------------------------------------------------------------------------ 56 void TAPEReader::GetFileFormatInfo(media_file_format* oMFF) 57 { 58 oMFF->capabilities = media_file_format::B_READABLE 59 | media_file_format::B_PERFECTLY_SEEKABLE 60 // | media_file_format::B_IMPERFECTLY_SEEKABLE 61 | media_file_format::B_KNOWS_RAW_AUDIO 62 | media_file_format::B_KNOWS_ENCODED_AUDIO; 63 oMFF->family = B_ANY_FORMAT_FAMILY; 64 oMFF->version = MEDIA_FILE_FORMAT_VERSION; 65 strcpy(oMFF->mime_type, MIME_TYPE_APE); 66 strcpy(oMFF->pretty_name, MIME_TYPE_APE_LONG_DESCRIPTION); 67 strcpy(oMFF->short_name, MIME_TYPE_APE_SHORT_DESCRIPTION); 68 strcpy(oMFF->file_extension, MIME_TYPE_APE_EXTENSION); 69 } 70 //------------------------------------------------------------------------------ 71 status_t TAPEReader::GetNextChunk(void* oCookie, const void** oChunkBuffer, size_t* oChunkSize, media_header* oMediaHeader) 72 { 73 int64 aOutSize; 74 75 // check whether song is finished or not 76 if ( mReadPosTotal-mReadPos+mPlayPos >= mDataSize ) 77 return B_ERROR; 78 // reading data 79 if ( mPlayPos >= mReadPos ) { 80 ReadBlocks(); 81 } 82 // passing data 83 if ( mReadPos-mPlayPos >= BUFFER_SIZE ) { 84 aOutSize = BUFFER_SIZE; 85 } else { 86 aOutSize = mReadPos-mPlayPos; 87 } 88 *oChunkBuffer = &mDecodedData[mPlayPos]; 89 mPlayPos += aOutSize; 90 // passing info 91 *oChunkSize = aOutSize; 92 oMediaHeader->start_time = CurrentTime(); 93 oMediaHeader->file_pos = mPlayPos; 94 return B_OK; 95 } 96 //------------------------------------------------------------------------------ 97 status_t TAPEReader::GetStreamInfo(void* oCookie, int64* oFrameCount, bigtime_t* oDuration, media_format* oFormat, 98 const void** oInfoBuffer, size_t* oInfoSize) 99 { 100 if ( LoadAPECheck() != B_OK ) 101 return LoadAPECheck(); 102 *oFrameCount = mDataSize/(mDecomp->GetInfo(APE_INFO_BITS_PER_SAMPLE)/8*mDecomp->GetInfo(APE_INFO_CHANNELS)); 103 *oDuration = mDecomp->GetInfo(APE_INFO_LENGTH_MS)*static_cast<bigtime_t>(1000); 104 // media_format 105 oFormat->type = B_MEDIA_RAW_AUDIO; 106 oFormat->u.raw_audio.frame_rate = mDecomp->GetInfo(APE_INFO_SAMPLE_RATE); 107 oFormat->u.raw_audio.channel_count = mDecomp->GetInfo(APE_INFO_CHANNELS); 108 if ( mDecomp->GetInfo(APE_INFO_BITS_PER_SAMPLE) == 16 ) { 109 oFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; 110 } else { 111 oFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_UCHAR; 112 } 113 oFormat->u.raw_audio.byte_order = B_MEDIA_LITTLE_ENDIAN; 114 oFormat->u.raw_audio.buffer_size = BUFFER_SIZE; 115 oInfoBuffer = NULL; 116 oInfoSize = NULL; 117 return B_OK; 118 } 119 //------------------------------------------------------------------------------ 120 status_t TAPEReader::LoadAPECheck() const 121 { 122 return mLoadAPECheck; 123 } 124 //------------------------------------------------------------------------------ 125 status_t TAPEReader::ReadBlocks() 126 { 127 int aBlocksRead; 128 int aRetVal = 0; 129 130 aRetVal = mDecomp->GetData(reinterpret_cast<char*>(mDecodedData), BLOCK_COUNT, &aBlocksRead); 131 if ( aRetVal != ERROR_SUCCESS ) { 132 return B_ERROR; 133 } 134 mPlayPos = 0; 135 mReadPos = aBlocksRead*mDecomp->GetInfo(APE_INFO_BLOCK_ALIGN); 136 mReadPosTotal += mReadPos; 137 return B_OK; 138 } 139 //------------------------------------------------------------------------------ 140 141 status_t TAPEReader::FindKeyFrame(void* cookie, uint32 flags, 142 int64* frame, bigtime_t* time) 143 { 144 printf("FindKeyFrame for time %Ld or frame %Ld\n",*time,*frame); 145 if ( flags & B_MEDIA_SEEK_TO_FRAME ) { 146 *time = *frame * 1000 / mDecomp->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS) * mDecomp->GetInfo(APE_DECOMPRESS_LENGTH_MS); 147 } else if ( flags & B_MEDIA_SEEK_TO_TIME ) { 148 *frame = (*time)/1000*mDecomp->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS)/mDecomp->GetInfo(APE_DECOMPRESS_LENGTH_MS); 149 } else { 150 return B_ERROR; 151 } 152 153 return B_OK; 154 } 155 156 status_t TAPEReader::Seek(void *cookie, uint32 flags, 157 int64 *frame, bigtime_t *time) 158 { 159 int32 aNewBlock; 160 161 printf("Seek for time %Ld or frame %Ld\n",*time,*frame); 162 if ( flags & B_MEDIA_SEEK_TO_FRAME ) { 163 aNewBlock = *frame; 164 } else if ( flags & B_MEDIA_SEEK_TO_TIME ) { 165 aNewBlock = (*time)/1000*mDecomp->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS)/mDecomp->GetInfo(APE_DECOMPRESS_LENGTH_MS); 166 } else { 167 return B_ERROR; 168 } 169 mReadPosTotal = aNewBlock*mDecomp->GetInfo(APE_INFO_BLOCK_ALIGN); 170 mDecomp->Seek(aNewBlock); 171 ReadBlocks(); 172 return B_OK; 173 } 174 //------------------------------------------------------------------------------ 175 status_t TAPEReader::Sniff(int32* oStreamCount) 176 { 177 Unset(); 178 // prepare about file 179 mSrcPIO = dynamic_cast<BPositionIO*>(Source()); 180 if ( mSrcPIO == NULL ) 181 return B_ERROR; 182 mPositionBridgeIO.SetPositionIO(mSrcPIO); 183 mDecomp = CreateIAPEDecompressEx(&mPositionBridgeIO); 184 if ( mDecomp == NULL ) 185 return B_ERROR; 186 // prepare about data 187 mDataSize = static_cast<int64>(mDecomp->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS)) 188 *mDecomp->GetInfo(APE_INFO_BLOCK_ALIGN); 189 mDecodedData = new char [max_c(BUFFER_SIZE*mDecomp->GetInfo(APE_INFO_CHANNELS), 190 BLOCK_COUNT*mDecomp->GetInfo(APE_INFO_BLOCK_ALIGN))]; 191 mLoadAPECheck = B_OK; 192 *oStreamCount = 1; 193 return B_OK; 194 } 195 //------------------------------------------------------------------------------ 196 void TAPEReader::Unset() 197 { 198 mLoadAPECheck = B_NO_INIT; 199 // about file 200 mPositionBridgeIO.SetPositionIO(NULL); 201 mSrcPIO = NULL; 202 delete mDecomp; 203 // about data 204 mDataSize = 0; 205 mReadPos = 0; 206 mReadPosTotal = 0; 207 mPlayPos = 0; 208 delete [] mDecodedData; 209 } 210 //------------------------------------------------------------------------------ 211 //============================================================================== 212 TAPEReaderPlugin::TAPEReaderPlugin() 213 { 214 } 215 //------------------------------------------------------------------------------ 216 TAPEReaderPlugin::~TAPEReaderPlugin() 217 { 218 } 219 //------------------------------------------------------------------------------ 220 Reader* TAPEReaderPlugin::NewReader() 221 { 222 return new TAPEReader(); 223 } 224 //------------------------------------------------------------------------------ 225 //============================================================================== 226 MediaPlugin* instantiate_plugin() 227 { 228 return new TAPEReaderPlugin(); 229 } 230 //------------------------------------------------------------------------------ 231 //============================================================================== 232