1 /* 2 * Copyright 2009, Haiku Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marcus Overhagen 7 * Michael Lotz <mmlr@mlotz.ch> 8 */ 9 10 #include <Sound.h> 11 #include <File.h> 12 13 #include "TrackReader.h" 14 15 #include <MediaDebug.h> 16 #include <new> 17 #include <string.h> 18 19 20 BSound::BSound(void* data, size_t size, const media_raw_audio_format& format, 21 bool freeWhenDone) 22 : fData(data), 23 fDataSize(size), 24 fFile(NULL), 25 fRefCount(1), 26 fStatus(B_NO_INIT), 27 fFormat(format), 28 fFreeWhenDone(freeWhenDone), 29 fTrackReader(NULL) 30 { 31 if (fData == NULL) 32 return; 33 34 fStatus = B_OK; 35 } 36 37 38 BSound::BSound(const entry_ref* soundFile, bool loadIntoMemory) 39 : fData(NULL), 40 fDataSize(0), 41 fFile(new(std::nothrow) BFile(soundFile, B_READ_ONLY)), 42 fRefCount(1), 43 fStatus(B_NO_INIT), 44 fFreeWhenDone(false), 45 fTrackReader(NULL) 46 { 47 if (fFile == NULL) { 48 fStatus = B_NO_MEMORY; 49 return; 50 } 51 52 fStatus = fFile->InitCheck(); 53 if (fStatus != B_OK) 54 return; 55 56 memset(&fFormat, 0, sizeof(fFormat)); 57 fTrackReader = new(std::nothrow) BPrivate::BTrackReader(fFile, fFormat); 58 if (fTrackReader == NULL) { 59 fStatus = B_NO_MEMORY; 60 return; 61 } 62 63 fStatus = fTrackReader->InitCheck(); 64 if (fStatus != B_OK) 65 return; 66 67 fFormat = fTrackReader->Format(); 68 fStatus = B_OK; 69 } 70 71 72 BSound::BSound(const media_raw_audio_format& format) 73 : fData(NULL), 74 fDataSize(0), 75 fFile(NULL), 76 fRefCount(1), 77 fStatus(B_ERROR), 78 fFormat(format), 79 fFreeWhenDone(false), 80 fTrackReader(NULL) 81 { 82 // unimplemented protected constructor 83 UNIMPLEMENTED(); 84 } 85 86 87 BSound::~BSound() 88 { 89 delete fTrackReader; 90 delete fFile; 91 92 if (fFreeWhenDone) 93 free(fData); 94 } 95 96 97 status_t 98 BSound::InitCheck() 99 { 100 return fStatus; 101 } 102 103 104 BSound* 105 BSound::AcquireRef() 106 { 107 atomic_add(&fRefCount, 1); 108 return this; 109 } 110 111 112 bool 113 BSound::ReleaseRef() 114 { 115 if (atomic_add(&fRefCount, -1) == 1) { 116 delete this; 117 return false; 118 } 119 120 // TODO: verify those returns 121 return true; 122 } 123 124 125 int32 126 BSound::RefCount() const 127 { 128 return fRefCount; 129 } 130 131 132 bigtime_t 133 BSound::Duration() const 134 { 135 UNIMPLEMENTED(); 136 return 0; 137 } 138 139 140 const media_raw_audio_format& 141 BSound::Format() const 142 { 143 return fFormat; 144 } 145 146 147 const void* 148 BSound::Data() const 149 { 150 return fData; 151 } 152 153 154 off_t 155 BSound::Size() const 156 { 157 if (fFile != NULL) { 158 off_t result = 0; 159 fFile->GetSize(&result); 160 return result; 161 } 162 163 return fDataSize; 164 } 165 166 167 bool 168 BSound::GetDataAt(off_t offset, void* intoBuffer, size_t bufferSize, 169 size_t* outUsed) 170 { 171 if (intoBuffer == NULL) 172 return false; 173 174 if (fData != NULL) { 175 size_t copySize = MIN(bufferSize, fDataSize - offset); 176 memcpy(intoBuffer, (uint8*)fData + offset, copySize); 177 if (outUsed != NULL) 178 *outUsed = copySize; 179 return true; 180 } 181 182 if (fTrackReader != NULL) { 183 int32 frameSize = fTrackReader->FrameSize(); 184 int64 frameCount = fTrackReader->CountFrames(); 185 int64 startFrame = offset / frameSize; 186 if (startFrame > frameCount) 187 return false; 188 189 if (fTrackReader->SeekToFrame(&startFrame) != B_OK) 190 return false; 191 192 off_t bufferOffset = offset - startFrame * frameSize; 193 int64 directStartFrame = (offset + frameSize - 1) / frameSize; 194 int64 directFrameCount = (offset + bufferSize - directStartFrame 195 * frameSize) / frameSize; 196 197 if (bufferOffset != 0) { 198 int64 indirectFrameCount = directStartFrame - startFrame; 199 size_t indirectSize = indirectFrameCount * frameSize; 200 void* buffer = malloc(indirectSize); 201 if (buffer == NULL) 202 return false; 203 204 if (fTrackReader->ReadFrames(buffer, indirectFrameCount) != B_OK) { 205 free(buffer); 206 return false; 207 } 208 209 memcpy(intoBuffer, (uint8*)buffer + bufferOffset, 210 indirectSize - bufferOffset); 211 if (outUsed != NULL) 212 *outUsed = indirectSize - bufferOffset; 213 214 free(buffer); 215 } else if (outUsed != NULL) 216 *outUsed = 0; 217 218 if (fTrackReader->ReadFrames((uint8*)intoBuffer + bufferOffset, 219 directFrameCount) != B_OK) 220 return false; 221 222 if (outUsed != NULL) 223 *outUsed += directFrameCount * frameSize; 224 225 return true; 226 } 227 228 return false; 229 } 230 231 232 status_t 233 BSound::BindTo(BSoundPlayer* player, const media_raw_audio_format& format) 234 { 235 UNIMPLEMENTED(); 236 return B_ERROR; 237 } 238 239 240 status_t 241 BSound::UnbindFrom(BSoundPlayer* player) 242 { 243 UNIMPLEMENTED(); 244 return B_ERROR; 245 } 246 247 248 status_t 249 BSound::Perform(int32 code, ...) 250 { 251 UNIMPLEMENTED(); 252 return B_ERROR; 253 } 254 255 256 status_t BSound::_Reserved_Sound_0(void*) { return B_ERROR; } 257 status_t BSound::_Reserved_Sound_1(void*) { return B_ERROR; } 258 status_t BSound::_Reserved_Sound_2(void*) { return B_ERROR; } 259 status_t BSound::_Reserved_Sound_3(void*) { return B_ERROR; } 260 status_t BSound::_Reserved_Sound_4(void*) { return B_ERROR; } 261 status_t BSound::_Reserved_Sound_5(void*) { return B_ERROR; } 262