vfs: check userland buffers before reading them.
[haiku.git] / src / kits / media / SoundFile.cpp
blob3a18e4bb46b7d73af262403c2da6ee4e3f7d22c1
1 /***********************************************************************
2 * AUTHOR: Marcus Overhagen
3 * FILE: SoundFile.cpp
4 * DESCR:
5 ***********************************************************************/
6 #include <MediaFile.h>
7 #include <MediaTrack.h>
8 #include <SoundFile.h>
10 #include <string.h>
12 #include "debug.h"
14 /*************************************************************
15 * public BSoundFile
16 *************************************************************/
18 BSoundFile::BSoundFile()
20 _init_raw_stats();
24 BSoundFile::BSoundFile(const entry_ref *ref,
25 uint32 open_mode)
27 _init_raw_stats();
28 SetTo(ref,open_mode);
31 /* virtual */
32 BSoundFile::~BSoundFile()
34 delete fSoundFile;
35 delete fMediaFile;
36 // fMediaTrack will be deleted by the BMediaFile destructor
40 status_t
41 BSoundFile::InitCheck() const
43 if (!fSoundFile) {
44 return B_NO_INIT;
46 return fSoundFile->InitCheck();
50 status_t
51 BSoundFile::SetTo(const entry_ref *ref,
52 uint32 open_mode)
54 if (fMediaTrack) {
55 BMediaTrack * track = fMediaTrack;
56 fMediaTrack = 0;
57 fMediaFile->ReleaseTrack(track);
59 if (fMediaFile) {
60 BMediaFile * file = fMediaFile;
61 fMediaFile = 0;
62 delete file;
64 if (fSoundFile) {
65 BFile * file = fSoundFile;
66 fSoundFile = 0;
67 delete file;
69 if (open_mode == B_READ_ONLY) {
70 return _ref_to_file(ref);
71 } else {
72 UNIMPLEMENTED();
73 return B_ERROR;
78 int32
79 BSoundFile::FileFormat() const
81 return fFileFormat;
85 int32
86 BSoundFile::SamplingRate() const
88 return fSamplingRate;
92 int32
93 BSoundFile::CountChannels() const
95 return fChannelCount;
99 int32
100 BSoundFile::SampleSize() const
102 return fSampleSize;
106 int32
107 BSoundFile::ByteOrder() const
109 return fByteOrder;
113 int32
114 BSoundFile::SampleFormat() const
116 return fSampleFormat;
120 int32
121 BSoundFile::FrameSize() const
123 return fSampleSize * fChannelCount;
127 off_t
128 BSoundFile::CountFrames() const
130 return fFrameCount;
134 bool
135 BSoundFile::IsCompressed() const
137 return fIsCompressed;
141 int32
142 BSoundFile::CompressionType() const
144 return fCompressionType;
148 char *
149 BSoundFile::CompressionName() const
151 return fCompressionName;
155 /* virtual */ int32
156 BSoundFile::SetFileFormat(int32 format)
158 fFileFormat = format;
159 return fFileFormat;
163 /* virtual */ int32
164 BSoundFile::SetSamplingRate(int32 fps)
166 fSamplingRate = fps;
167 return fSamplingRate;
171 /* virtual */ int32
172 BSoundFile::SetChannelCount(int32 spf)
174 fChannelCount = spf;
175 return fChannelCount;
179 /* virtual */ int32
180 BSoundFile::SetSampleSize(int32 bps)
182 fSampleSize = bps;
183 return fSampleSize;
187 /* virtual */ int32
188 BSoundFile::SetByteOrder(int32 bord)
190 fByteOrder = bord;
191 return fByteOrder;
195 /* virtual */ int32
196 BSoundFile::SetSampleFormat(int32 fmt)
198 fSampleFormat = fmt;
199 return fSampleFormat;
203 /* virtual */ int32
204 BSoundFile::SetCompressionType(int32 type)
206 return 0;
210 /* virtual */ char *
211 BSoundFile::SetCompressionName(char *name)
213 return NULL;
217 /* virtual */ bool
218 BSoundFile::SetIsCompressed(bool tf)
220 return false;
224 /* virtual */ off_t
225 BSoundFile::SetDataLocation(off_t offset)
227 UNIMPLEMENTED();
229 return 0;
233 /* virtual */ off_t
234 BSoundFile::SetFrameCount(off_t count)
236 fFrameCount = count;
237 return fFrameCount;
241 size_t
242 BSoundFile::ReadFrames(char *buf,
243 size_t count)
245 size_t frameRead = 0;
246 int64 frames = count;
247 while (count > 0) {
248 status_t status = fMediaTrack->ReadFrames(
249 reinterpret_cast<void *>(buf), &frames);
250 count -= frames;
251 frameRead += frames;
252 buf += fSampleSize * fChannelCount * frames;
253 if (status != B_OK) {
254 if (frameRead > 0)
255 break;
256 return status;
259 return frameRead;
263 size_t
264 BSoundFile::WriteFrames(char *buf,
265 size_t count)
267 return fMediaTrack->WriteFrames(
268 reinterpret_cast<void *>(buf), count);
272 /* virtual */ off_t
273 BSoundFile::SeekToFrame(off_t n)
275 int64 frames = n;
276 status_t status = fMediaTrack->SeekToFrame(&frames);
278 if (status != B_OK)
279 return status;
281 return frames;
285 off_t
286 BSoundFile::FrameIndex() const
288 return fFrameIndex;
292 off_t
293 BSoundFile::FramesRemaining() const
295 return fFrameCount - FrameIndex();
298 /*************************************************************
299 * private BSoundFile
300 *************************************************************/
303 void BSoundFile::_ReservedSoundFile1() {}
304 void BSoundFile::_ReservedSoundFile2() {}
305 void BSoundFile::_ReservedSoundFile3() {}
307 void
308 BSoundFile::_init_raw_stats()
310 fSoundFile = 0;
311 fMediaFile = 0;
312 fMediaTrack = 0;
313 fFileFormat = B_UNKNOWN_FILE;
314 fSamplingRate = 44100;
315 fChannelCount = 2;
316 fSampleSize = 2;
317 fByteOrder = B_BIG_ENDIAN;
318 fSampleFormat = B_LINEAR_SAMPLES;
319 fFrameCount = 0;
320 fFrameIndex = 0;
321 fIsCompressed = false;
322 fCompressionType = -1;
323 fCompressionName = NULL;
327 static int32
328 _ParseMimeType(char *mime_type)
330 if (strcmp(mime_type, "audio/x-aiff") == 0)
331 return B_AIFF_FILE;
332 if (strcmp(mime_type, "audio/x-wav") == 0)
333 return B_WAVE_FILE;
334 return B_UNKNOWN_FILE;
338 status_t
339 BSoundFile::_ref_to_file(const entry_ref *ref)
341 status_t status;
342 BFile * file = new BFile(ref, B_READ_ONLY);
343 status = file->InitCheck();
344 if (status != B_OK) {
345 fSoundFile = file;
346 return status;
348 BMediaFile * media = new BMediaFile(file);
349 status = media->InitCheck();
350 if (status != B_OK) {
351 delete media;
352 delete file;
353 return status;
355 media_file_format mfi;
356 media->GetFileFormatInfo(&mfi);
357 switch (mfi.family) {
358 case B_AIFF_FORMAT_FAMILY: fFileFormat = B_AIFF_FILE; break;
359 case B_WAV_FORMAT_FAMILY: fFileFormat = B_WAVE_FILE; break;
360 default: fFileFormat = _ParseMimeType(mfi.mime_type); break;
362 int trackNum = 0;
363 BMediaTrack * track = 0;
364 media_format mf;
365 while (trackNum < media->CountTracks()) {
366 track = media->TrackAt(trackNum);
367 status = track->DecodedFormat(&mf);
368 if (status != B_OK) {
369 media->ReleaseTrack(track);
370 delete media;
371 delete file;
372 return status;
374 if (mf.IsAudio()) {
375 break;
377 media->ReleaseTrack(track);
378 track = 0;
380 if (track == 0) {
381 delete media;
382 delete file;
383 return B_ERROR;
385 media_raw_audio_format * raw = 0;
386 if (mf.type == B_MEDIA_ENCODED_AUDIO) {
387 raw = &mf.u.encoded_audio.output;
389 if (mf.type == B_MEDIA_RAW_AUDIO) {
390 raw = &mf.u.raw_audio;
393 if (raw == NULL) {
394 delete media;
395 delete file;
396 return B_ERROR;
399 fSamplingRate = (int)raw->frame_rate;
400 fChannelCount = raw->channel_count;
401 fSampleSize = raw->format & 0xf;
402 fByteOrder = raw->byte_order;
403 switch (raw->format) {
404 case media_raw_audio_format::B_AUDIO_FLOAT:
405 fSampleFormat = B_FLOAT_SAMPLES;
406 break;
407 case media_raw_audio_format::B_AUDIO_INT:
408 case media_raw_audio_format::B_AUDIO_SHORT:
409 case media_raw_audio_format::B_AUDIO_UCHAR:
410 case media_raw_audio_format::B_AUDIO_CHAR:
411 fSampleFormat = B_LINEAR_SAMPLES;
412 break;
413 default:
414 fSampleFormat = B_UNDEFINED_SAMPLES;
416 fByteOffset = 0;
417 fFrameCount = track->CountFrames();
418 fFrameIndex = 0;
419 if (mf.type == B_MEDIA_ENCODED_AUDIO) {
420 fIsCompressed = true;
421 fCompressionType = mf.u.encoded_audio.encoding;
423 fMediaFile = media;
424 fMediaTrack = track;
425 fSoundFile = file;
426 return B_OK;