xref: /haiku/src/add-ons/media/plugins/ape_reader/APEReader.cpp (revision 58481f0f6ef1a61ba07283f012cafbc2ed874ead)
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