1 /* Copyright 2005-2009 SHINTA
2 * Distributed under the terms of the MIT license
6 #include <InterfaceDefs.h>
13 static const char* kCopyrightString
14 = "Copyright " B_UTF8_COPYRIGHT
" 2005-2009 by SHINTA";
17 TAPEReader::TAPEReader()
26 TAPEReader::~TAPEReader()
32 TAPEReader::AllocateCookie(int32 oStreamNumber
, void** oCookie
)
40 TAPEReader::Copyright()
42 return kCopyrightString
;
47 TAPEReader::CurrentTime() const
49 return mDecomp
->GetInfo(APE_DECOMPRESS_CURRENT_MS
)
50 * static_cast<bigtime_t
>(1000);
55 TAPEReader::FreeCookie(void* oCookie
)
62 TAPEReader::GetFileFormatInfo(media_file_format
* oMFF
)
64 oMFF
->capabilities
= media_file_format::B_READABLE
65 | media_file_format::B_PERFECTLY_SEEKABLE
66 // | media_file_format::B_IMPERFECTLY_SEEKABLE
67 | media_file_format::B_KNOWS_RAW_AUDIO
68 | media_file_format::B_KNOWS_ENCODED_AUDIO
;
69 oMFF
->family
= B_ANY_FORMAT_FAMILY
;
70 oMFF
->version
= MEDIA_FILE_FORMAT_VERSION
;
71 strcpy(oMFF
->mime_type
, MIME_TYPE_APE
);
72 strcpy(oMFF
->pretty_name
, MIME_TYPE_APE_LONG_DESCRIPTION
);
73 strcpy(oMFF
->short_name
, MIME_TYPE_APE_SHORT_DESCRIPTION
);
74 strcpy(oMFF
->file_extension
, MIME_TYPE_APE_EXTENSION
);
79 TAPEReader::GetNextChunk(void* oCookie
, const void** oChunkBuffer
,
80 size_t* oChunkSize
, media_header
* oMediaHeader
)
84 // check whether song is finished or not
85 if (mReadPosTotal
- mReadPos
+ mPlayPos
>= mDataSize
)
89 if (mPlayPos
>= mReadPos
)
93 if (mReadPos
-mPlayPos
>= BUFFER_SIZE
)
94 aOutSize
= BUFFER_SIZE
;
96 aOutSize
= mReadPos
-mPlayPos
;
98 *oChunkBuffer
= &mDecodedData
[mPlayPos
];
102 *oChunkSize
= aOutSize
;
103 oMediaHeader
->start_time
= CurrentTime();
104 oMediaHeader
->file_pos
= mPlayPos
;
110 TAPEReader::GetStreamInfo(void* oCookie
, int64
* oFrameCount
,
111 bigtime_t
* oDuration
, media_format
* oFormat
, const void** oInfoBuffer
,
114 if (LoadAPECheck() != B_OK
)
115 return LoadAPECheck();
117 *oFrameCount
= mDataSize
/ (mDecomp
->GetInfo(APE_INFO_BITS_PER_SAMPLE
) / 8
118 * mDecomp
->GetInfo(APE_INFO_CHANNELS
));
119 *oDuration
= mDecomp
->GetInfo(APE_INFO_LENGTH_MS
)
120 * static_cast<bigtime_t
>(1000);
122 oFormat
->type
= B_MEDIA_RAW_AUDIO
;
123 oFormat
->u
.raw_audio
.frame_rate
= mDecomp
->GetInfo(APE_INFO_SAMPLE_RATE
);
124 oFormat
->u
.raw_audio
.channel_count
= mDecomp
->GetInfo(APE_INFO_CHANNELS
);
125 if ( mDecomp
->GetInfo(APE_INFO_BITS_PER_SAMPLE
) == 16 )
126 oFormat
->u
.raw_audio
.format
= media_raw_audio_format::B_AUDIO_SHORT
;
128 oFormat
->u
.raw_audio
.format
= media_raw_audio_format::B_AUDIO_UCHAR
;
130 oFormat
->u
.raw_audio
.byte_order
= B_MEDIA_LITTLE_ENDIAN
;
131 oFormat
->u
.raw_audio
.buffer_size
= BUFFER_SIZE
;
139 TAPEReader::LoadAPECheck() const
141 return mLoadAPECheck
;
146 TAPEReader::ReadBlocks()
151 aRetVal
= mDecomp
->GetData(reinterpret_cast<char*>(mDecodedData
),
152 BLOCK_COUNT
, &aBlocksRead
);
153 if (aRetVal
!= ERROR_SUCCESS
)
157 mReadPos
= aBlocksRead
*mDecomp
->GetInfo(APE_INFO_BLOCK_ALIGN
);
158 mReadPosTotal
+= mReadPos
;
164 TAPEReader::FindKeyFrame(void* cookie
, uint32 flags
, int64
* frame
,
167 if (flags
& B_MEDIA_SEEK_TO_FRAME
) {
168 *time
= *frame
* 1000 / mDecomp
->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS
)
169 * mDecomp
->GetInfo(APE_DECOMPRESS_LENGTH_MS
);
170 printf("FindKeyFrame for frame %Ld: %Ld\n", *frame
, *time
);
171 } else if (flags
& B_MEDIA_SEEK_TO_TIME
) {
172 *frame
= (*time
) / 1000 * mDecomp
->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS
)
173 / mDecomp
->GetInfo(APE_DECOMPRESS_LENGTH_MS
);
174 printf("FindKeyFrame for time %Ld: %Ld\n", *time
, *frame
);
183 TAPEReader::Seek(void *cookie
, uint32 flags
, int64
*frame
, bigtime_t
*time
)
187 if (flags
& B_MEDIA_SEEK_TO_FRAME
) {
188 printf("Seek to frame %Ld\n", *frame
);
190 } else if (flags
& B_MEDIA_SEEK_TO_TIME
) {
191 printf("Seek for time %Ld\n", *time
);
192 aNewBlock
= (*time
) / 1000 * mDecomp
->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS
)
193 / mDecomp
->GetInfo(APE_DECOMPRESS_LENGTH_MS
);
197 int64 aNewTime
= aNewBlock
* mDecomp
->GetInfo(APE_INFO_BLOCK_ALIGN
);
198 if (mReadPosTotal
- mReadPos
< aNewTime
&& mReadPosTotal
> aNewTime
) {
199 // Requested seek frame is already in the current buffer, no need to
200 // actually seek, just set the play position
201 mPlayPos
= aNewTime
- mReadPosTotal
+ mReadPos
;
203 mReadPosTotal
= aNewBlock
* mDecomp
->GetInfo(APE_INFO_BLOCK_ALIGN
);
204 mDecomp
->Seek(aNewBlock
);
212 TAPEReader::Sniff(int32
* oStreamCount
)
215 // prepare about file
216 mSrcPIO
= dynamic_cast<BPositionIO
*>(Source());
220 BMediaIO
* mediaIO
= dynamic_cast<BMediaIO
*>(Source());
221 if (mediaIO
!= NULL
) {
223 mediaIO
->GetFlags(&flags
);
224 // This plugin doesn't support streamed data.
225 // The APEHeader::FindDescriptor function always
226 // analyze the whole file to find the APE_DESCRIPTOR.
227 if ((flags
& B_MEDIA_STREAMING
) == true)
231 int nFunctionRetVal
= ERROR_SUCCESS
;
232 mPositionBridgeIO
.SetPositionIO(mSrcPIO
);
234 mDecomp
= CreateIAPEDecompressEx(&mPositionBridgeIO
, &nFunctionRetVal
);
235 if (mDecomp
== NULL
|| nFunctionRetVal
!= ERROR_SUCCESS
)
238 // prepare about data
239 mDataSize
= static_cast<int64
>(mDecomp
->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS
))
240 *mDecomp
->GetInfo(APE_INFO_BLOCK_ALIGN
);
241 mDecodedData
= new char [max_c(BUFFER_SIZE
*mDecomp
->GetInfo(APE_INFO_CHANNELS
),
242 BLOCK_COUNT
*mDecomp
->GetInfo(APE_INFO_BLOCK_ALIGN
))];
243 mLoadAPECheck
= B_OK
;
252 mLoadAPECheck
= B_NO_INIT
;
254 mPositionBridgeIO
.SetPositionIO(NULL
);
262 delete [] mDecodedData
;
266 TAPEReaderPlugin::TAPEReaderPlugin()
271 TAPEReaderPlugin::~TAPEReaderPlugin()
277 TAPEReaderPlugin::NewReader()
279 return new TAPEReader();
286 return new TAPEReaderPlugin();