00001 #include "Shared/Config.h"
00002 #include "SoundManager.h"
00003 #include "Shared/MarkScope.h"
00004 #include "WAV.h"
00005 #include "Events/EventRouter.h"
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <unistd.h>
00009 #include <fstream>
00010 #ifdef PLATFORM_APERIOS
00011 # include <OPENR/OSubject.h>
00012 # include <OPENR/ObjcommEvent.h>
00013 #endif
00014
00015 using namespace std;
00016
00017 SoundManager * sndman=NULL;
00018
00019
00020 typedef MarkScope AutoLock;
00021
00022 SoundManager::SoundManager()
00023 : mixerBuffer(0), mixerBufferSize(0), sndlist(),playlist(),chanlist(),mix_mode(Fast),queue_mode(Override),max_chan(4),lock(),sn(0)
00024 {}
00025
00026 #ifdef PLATFORM_APERIOS
00027 void
00028 SoundManager::InitAccess(OSubject* subj) {
00029 subjs[ProcessID::getID()]=subj;
00030 }
00031 #else //PLATFORM_LOCAL
00032 void
00033 SoundManager::InitAccess(MessageQueueBase& sndbufq) {
00034 subjs[ProcessID::getID()]=&sndbufq;
00035 }
00036 #endif //PLATFORM-specific initialization
00037
00038 SoundManager::~SoundManager() {
00039 stopPlay();
00040 if(!sndlist.empty())
00041 cerr << "Warning: SoundManager was deleted with active sound buffer references" << endl;
00042 while(!sndlist.empty()) {
00043 sndlist_t::index_t it=sndlist.begin();
00044 if(sndlist[it].rcr==NULL)
00045 cerr << sndlist[it].name << " was still inflight (IPC), with " << sndlist[it].ref << " sound references" << endl;
00046 else {
00047 cerr << sndlist[it].name << " was deleted, with " << sndlist[it].ref << " sound references and " << sndlist[it].rcr->NumberOfReference() << " region references (one will be removed)" << endl;
00048 sndlist[it].rcr->RemoveReference();
00049 }
00050 sndlist.erase(it);
00051 }
00052 delete[] mixerBuffer;
00053 }
00054
00055
00056 SoundManager::Snd_ID
00057 SoundManager::loadFile(std::string const &name) {
00058 AutoLock autolock(lock);
00059 if (name.size() == 0) {
00060 cout << "SoundManager::loadFile() null filename" << endl;
00061 return invalid_Snd_ID;
00062 };
00063 std::string path(config->sound.makePath(name));
00064 Snd_ID id=lookupPath(path);
00065 if(id!=invalid_Snd_ID) {
00066
00067 sndlist[id].ref++;
00068 } else {
00069
00070 struct stat buf;
00071 if(stat(path.c_str(),&buf)==-1) {
00072 cout << "SoundManager::loadFile(): Sound file not found: " << path << endl;
00073 return invalid_Snd_ID;
00074 }
00075 byte * sndbuf=new byte[buf.st_size];
00076 std::ifstream file(path.c_str());
00077 file.read(reinterpret_cast<char*>(sndbuf),buf.st_size);
00078 WAV wav;
00079 WAVError error = wav.Set(sndbuf);
00080 if (error != WAV_SUCCESS) {
00081 printf("%s : %s %d: '%s'","SoundManager::loadFile()","wav.Set() FAILED",error, path.c_str());
00082 return invalid_Snd_ID;
00083 }
00084 if(wav.GetSamplingRate()!=config->sound.sample_rate || wav.GetBitsPerSample()!=config->sound.sample_bits) {
00085 printf("%s : %s %d","SoundManager::loadFile()","bad sample rate/bits", error);
00086 return invalid_Snd_ID;
00087 }
00088 cout << "Loading " << name << endl;
00089 id=loadBuffer(reinterpret_cast<char*>(wav.GetDataStart()),wav.GetDataEnd()-wav.GetDataStart());
00090 delete [] sndbuf;
00091 if(path.size()>MAX_NAME_LEN)
00092 strncpy(sndlist[id].name,path.substr(path.size()-MAX_NAME_LEN).c_str(),MAX_NAME_LEN);
00093 else
00094 strncpy(sndlist[id].name,path.c_str(),MAX_NAME_LEN);
00095 }
00096 return id;
00097 }
00098
00099 SoundManager::Snd_ID
00100 SoundManager::loadBuffer(const char buf[], unsigned int len) {
00101
00102 if(buf==NULL || len==0)
00103 return invalid_Snd_ID;
00104 AutoLock autolock(lock);
00105
00106 RCRegion * region=initRegion(len+MSG_SIZE);
00107
00108 SoundManagerMsg * msg=new (reinterpret_cast<SoundManagerMsg*>(region->Base())) SoundManagerMsg;
00109 Snd_ID msgid=sndlist.new_front();
00110 msg->setAdd(msgid,sn);
00111
00112 sndlist[msg->getID()].rcr=NULL;
00113 sndlist[msg->getID()].data=NULL;
00114 sndlist[msg->getID()].ref=1;
00115 sndlist[msg->getID()].len=len;
00116 sndlist[msg->getID()].sn=sn;
00117
00118 const byte* src=reinterpret_cast<const byte*>(buf);
00119 byte* dest=reinterpret_cast<byte*>(region->Base())+MSG_SIZE;
00120 byte* end=dest+len;
00121 if (config->sound.sample_bits==8)
00122 while (dest < end)
00123 *dest++ = *src++ ^ 0x80;
00124 else
00125 while (dest < end)
00126 *dest++ = *src++;
00127
00128
00129 if(ProcessID::getID()==ProcessID::SoundProcess) {
00130
00131 sndlist[msg->getID()].rcr=region;
00132 sndlist[msg->getID()].data=reinterpret_cast<byte*>(region->Base()+MSG_SIZE);
00133 } else {
00134 #ifdef PLATFORM_APERIOS
00135
00136 subjs[ProcessID::getID()]->SetData(region);
00137 subjs[ProcessID::getID()]->NotifyObservers();
00138
00139 #else
00140 subjs[ProcessID::getID()]->sendMessage(region);
00141 region->RemoveReference();
00142 #endif
00143 }
00144 return msgid;
00145 }
00146
00147 void
00148 SoundManager::releaseFile(std::string const &name) {
00149 AutoLock autolock(lock);
00150 release(lookupPath(config->sound.makePath(name)));
00151 }
00152
00153 void
00154 SoundManager::release(Snd_ID id) {
00155 if(id==invalid_Snd_ID)
00156 return;
00157 if(sndlist[id].ref==0) {
00158 cerr << "SoundManager::release() " << id << " extra release" << endl;
00159 return;
00160 }
00161 AutoLock autolock(lock);
00162 sndlist[id].ref--;
00163 if(sndlist[id].ref==0) {
00164 if(sndlist[id].rcr!=NULL) {
00165
00166
00167
00168
00169 if(ProcessID::getID()==ProcessID::SoundProcess) {
00170
00171 sndlist[id].rcr->RemoveReference();
00172 sndlist[id].rcr=NULL;
00173 } else {
00174
00175
00176 RCRegion * region=initRegion(MSG_SIZE);
00177
00178 SoundManagerMsg * msg=new (reinterpret_cast<SoundManagerMsg*>(region->Base())) SoundManagerMsg;
00179 msg->setDelete(sndlist[id].rcr);
00180
00181
00182 #ifdef PLATFORM_APERIOS
00183
00184 subjs[ProcessID::getID()]->SetData(region);
00185 subjs[ProcessID::getID()]->NotifyObservers();
00186
00187 #else
00188 subjs[ProcessID::getID()]->sendMessage(region);
00189 region->RemoveReference();
00190 #endif
00191 }
00192 }
00193
00194 sndlist[id].sn=0;
00195 sndlist.erase(id);
00196 }
00197 }
00198
00199 SoundManager::Play_ID
00200 SoundManager::playFile(std::string const &name) {
00201 if(playlist.size()>=playlist_t::MAX_ENTRIES)
00202 return invalid_Play_ID;
00203 AutoLock autolock(lock);
00204 Snd_ID sndid=loadFile(name);
00205 if(sndid==invalid_Snd_ID)
00206 return invalid_Play_ID;
00207 sndlist[sndid].ref--;
00208 cout << "Playing " << name << endl;
00209 return play(sndid);
00210 }
00211
00212 SoundManager::Play_ID
00213 SoundManager::playBuffer(const char buf[], unsigned int len) {
00214 if(playlist.size()>=playlist_t::MAX_ENTRIES || buf==NULL || len==0)
00215 return invalid_Play_ID;
00216 AutoLock autolock(lock);
00217 Snd_ID sndid=loadBuffer(buf,len);
00218 if(sndid==invalid_Snd_ID)
00219 return invalid_Play_ID;
00220 sndlist[sndid].ref--;
00221 return play(sndid);
00222 }
00223
00224 SoundManager::Play_ID
00225 SoundManager::play(Snd_ID id) {
00226
00227 if(id==invalid_Snd_ID)
00228 return invalid_Play_ID;
00229 AutoLock autolock(lock);
00230 Play_ID playid=playlist.new_front();
00231 if(playid!=invalid_Play_ID) {
00232 sndlist[id].ref++;
00233 playlist[playid].snd_id=id;
00234 playlist[playid].offset=0;
00235
00236
00237 chanlist.push_front(playid);
00238
00239
00240
00241
00242 if(ProcessID::getID()!=ProcessID::SoundProcess) {
00243 RCRegion * region=initRegion(MSG_SIZE);
00244 ASSERT(region!=NULL,"initRegion returned NULL");
00245 SoundManagerMsg * msg=new (reinterpret_cast<SoundManagerMsg*>(region->Base())) SoundManagerMsg;
00246 msg->setWakeup();
00247 #ifdef PLATFORM_APERIOS
00248
00249 subjs[ProcessID::getID()]->SetData(region);
00250 subjs[ProcessID::getID()]->NotifyObservers();
00251
00252 #else
00253 subjs[ProcessID::getID()]->sendMessage(region);
00254 region->RemoveReference();
00255 #endif
00256 }
00257
00258
00259 if(sndlist[id].rcr!=NULL) {
00260 const char * name=sndlist[playlist[playid].snd_id].name;
00261 if(name[0]!='\0')
00262 erouter->postEvent(EventBase::audioEGID,playid,EventBase::activateETID,0,name,1);
00263 else
00264 erouter->postEvent(EventBase::audioEGID,playid,EventBase::activateETID,0);
00265 }
00266 }
00267 return playid;
00268 }
00269
00270 SoundManager::Play_ID
00271 SoundManager::chainFile(Play_ID base, std::string const &next) {
00272 if(base==invalid_Play_ID)
00273 return playFile(next);
00274 Play_ID orig=base;
00275 while(playlist[base].next_id!=invalid_Play_ID)
00276 base=playlist[base].next_id;
00277 Play_ID nplay=playlist.new_front();
00278 if(nplay==invalid_Play_ID)
00279 return nplay;
00280 Snd_ID nsnd=loadFile(next);
00281 if(nsnd==invalid_Snd_ID) {
00282 playlist.pop_front();
00283 return invalid_Play_ID;
00284 }
00285 playlist[nplay].snd_id=nsnd;
00286 playlist[base].next_id=nplay;
00287 return orig;
00288 }
00289
00290 SoundManager::Play_ID
00291 SoundManager::chainBuffer(Play_ID base, const char buf[], unsigned int len) {
00292 if(base==invalid_Play_ID || buf==NULL || len==0)
00293 return playBuffer(buf,len);
00294 Play_ID orig=base;
00295 while(playlist[base].next_id!=invalid_Play_ID)
00296 base=playlist[base].next_id;
00297 Play_ID nplay=playlist.new_front();
00298 if(nplay==invalid_Play_ID)
00299 return nplay;
00300 Snd_ID nsnd=loadBuffer(buf,len);
00301 if(nsnd==invalid_Snd_ID) {
00302 playlist.pop_front();
00303 return invalid_Play_ID;
00304 }
00305 playlist[nplay].snd_id=nsnd;
00306 playlist[base].next_id=nplay;
00307 return orig;
00308 }
00309
00310 SoundManager::Play_ID
00311 SoundManager::chain(Play_ID base, Snd_ID next) {
00312 if(base==invalid_Play_ID || next==invalid_Snd_ID)
00313 return play(next);
00314 Play_ID orig=base;
00315 while(playlist[base].next_id!=invalid_Play_ID)
00316 base=playlist[base].next_id;
00317 Play_ID nplay=playlist.new_front();
00318 if(nplay==invalid_Play_ID)
00319 return nplay;
00320 playlist[nplay].snd_id=next;
00321 playlist[base].next_id=nplay;
00322 return orig;
00323 }
00324
00325 void
00326 SoundManager::stopPlay() {
00327 while(!playlist.empty())
00328 stopPlay(playlist.begin());
00329 }
00330
00331 void
00332 SoundManager::stopPlay(Play_ID id) {
00333 if(id==invalid_Play_ID)
00334 return;
00335 AutoLock autolock(lock);
00336
00337
00338 for(chanlist_t::index_t it=chanlist.prev(chanlist.end()); it!=chanlist.end(); it=chanlist.prev(it))
00339 if(chanlist[it]==id) {
00340 std::string name=sndlist[playlist[id].snd_id].name;
00341 release(playlist[id].snd_id);
00342 playlist.erase(id);
00343 chanlist.erase(it);
00344 playlist[id].cumulative+=playlist[id].offset;
00345 unsigned int ms=playlist[id].cumulative/(config->sound.sample_bits/8)/(config->sound.sample_rate/1000);
00346 if(name.size()>0)
00347 erouter->postEvent(EventBase::audioEGID,id,EventBase::deactivateETID,ms,name,0);
00348 else
00349 erouter->postEvent(EventBase::audioEGID,id,EventBase::deactivateETID,ms);
00350 return;
00351 }
00352 cerr << "SoundManager::stopPlay(): " << id << " does not seem to be playing" << endl;
00353 }
00354
00355 void
00356 SoundManager::pausePlay(Play_ID id) {
00357 if(id==invalid_Play_ID)
00358 return;
00359 AutoLock autolock(lock);
00360 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it))
00361 if(chanlist[it]==id) {
00362 chanlist.erase(it);
00363 return;
00364 }
00365 }
00366
00367 void
00368 SoundManager::resumePlay(Play_ID id) {
00369 if(id==invalid_Play_ID)
00370 return;
00371 AutoLock autolock(lock);
00372 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it))
00373 if(chanlist[it]==id)
00374 return;
00375 chanlist.push_front(id);
00376 }
00377
00378 void
00379 SoundManager::setMode(unsigned int max_channels, MixMode_t mixer_mode, QueueMode_t queuing_mode) {
00380 AutoLock autolock(lock);
00381 max_chan=max_channels;
00382 mix_mode=mixer_mode;
00383 queue_mode=queuing_mode;
00384 }
00385
00386 unsigned int
00387 SoundManager::getRemainTime(Play_ID id) const {
00388 AutoLock autolock(lock);
00389 unsigned int t=0;
00390 while(id!=invalid_Play_ID) {
00391 t+=sndlist[playlist[id].snd_id].len-playlist[id].offset;
00392 id=playlist[id].next_id;
00393 }
00394 const unsigned int bytesPerMS=config->sound.sample_bits/8*config->sound.sample_rate/1000;
00395 return t/bytesPerMS;
00396 }
00397
00398 void
00399 SoundManager::mixChannel(Play_ID channelId, void* buf, size_t destSize) {
00400 char *dest = (char*) buf;
00401
00402 PlayState& channel = playlist[channelId];
00403 while (destSize > 0) {
00404 const SoundData& buffer = sndlist[channel.snd_id];
00405 const char* samples = ((char*) (buffer.data)) + channel.offset;
00406 const unsigned int samplesSize = buffer.len - channel.offset;
00407 if (samplesSize > destSize) {
00408 memcpy(dest, samples, destSize);
00409 channel.offset += destSize;
00410 dest += destSize;
00411 destSize = 0;
00412 return;
00413 } else {
00414 memcpy(dest, samples, samplesSize);
00415 channel.offset += samplesSize;
00416 dest += samplesSize;
00417 destSize -= samplesSize;
00418 if (endPlay(channelId)) {
00419 break;
00420 }
00421 }
00422 }
00423 if (destSize > 0) {
00424 memset(dest, 0, destSize);
00425 }
00426 }
00427
00428 void
00429 SoundManager::mixChannelAdditively(Play_ID channelId, int bitsPerSample, MixMode_t mode,
00430 short scalingFactor, void* buf, size_t destSize)
00431 {
00432 PlayState& channel = playlist[channelId];
00433 while (destSize > 0) {
00434 const SoundData& buffer = sndlist[channel.snd_id];
00435 const unsigned int samplesSize = buffer.len - channel.offset;
00436 const unsigned int mixedSamplesSize =
00437 ((mode == Fast)
00438 ? ((samplesSize > destSize) ? destSize : samplesSize)
00439 : ((samplesSize > destSize / 2) ? destSize / 2 : samplesSize));
00440
00441 if (bitsPerSample == 8) {
00442
00443 const char* samples = (char*) (buffer.data + channel.offset);
00444 if (mode == Fast) {
00445
00446 char *dest = (char*) buf;
00447 for (size_t i = 0; i < mixedSamplesSize; i++) {
00448 *dest += samples[i] / scalingFactor;
00449 dest++;
00450 }
00451 destSize -= (char*) dest - (char*) buf;
00452 buf = dest;
00453 } else {
00454
00455 short* dest = (short*) buf;
00456 for (size_t i = 0; i < mixedSamplesSize; i++) {
00457 *dest += samples[i];
00458 *dest++;
00459 }
00460 destSize -= (char*) dest - (char*) buf;
00461 buf = dest;
00462 }
00463 } else {
00464
00465 const short* samples = (short*) (buffer.data + channel.offset);
00466 if (mode == Fast) {
00467
00468 short* dest = (short*) buf;
00469 for (size_t i = 0; i < mixedSamplesSize / 2; i++) {
00470 *dest += samples[i] / scalingFactor;
00471 *dest++;
00472 }
00473 destSize -= (char*) dest - (char*) buf;
00474 buf = dest;
00475 } else {
00476
00477 int* dest = (int*) buf;
00478 for (size_t i = 0; i < mixedSamplesSize / 2; i++) {
00479 *dest += samples[i];
00480 *dest++;
00481 }
00482 destSize -= (char*) dest - (char*) buf;
00483 buf = dest;
00484 }
00485 }
00486 channel.offset += mixedSamplesSize;
00487 if (destSize == 0) {
00488 return;
00489 } else {
00490 if (endPlay(channelId)) {
00491 return;
00492 }
00493 }
00494 }
00495 }
00496
00497 #ifdef PLATFORM_APERIOS
00498 unsigned int
00499 SoundManager::CopyTo(OSoundVectorData* data) {
00500 AutoLock autolock(lock);
00501 return CopyTo(data->GetData(0), data->GetInfo(0)->dataSize);
00502 }
00503
00504 void
00505 SoundManager::ReceivedMsg(const ONotifyEvent& event) {
00506
00507 for(int x=0; x<event.NumOfData(); x++)
00508 ProcessMsg(event.RCData(x));
00509 }
00510 #endif
00511
00512 unsigned int SoundManager::CopyTo(void * dest, size_t destSize) {
00513 AutoLock autolock(lock);
00514
00515 void * origdest=dest;
00516 size_t origDestSize=destSize;
00517 if(chanlist.size() == 0) {
00518 memset(dest, 0, destSize);
00519 return 0;
00520 }
00521
00522 std::vector<Play_ID> channels;
00523 selectChannels(channels);
00524
00525 if (channels.size() == 0) {
00526
00527 memset(dest, 0, destSize);
00528 } else if (channels.size() == 1) {
00529
00530 mixChannel(channels.front(), dest, destSize);
00531 } else {
00532
00533 const MixMode_t mode = mix_mode;
00534 const int bitsPerSample = config->sound.sample_bits;
00535 if (mode == Quality) {
00536
00537 if ((mixerBuffer == 0) || (mixerBufferSize < destSize * 2)) {
00538 delete[] mixerBuffer;
00539 mixerBuffer = 0;
00540 mixerBufferSize = destSize * 2;
00541 mixerBuffer = new int[(mixerBufferSize / 4) + 1];
00542 }
00543 memset(mixerBuffer, 0, mixerBufferSize);
00544 dest = mixerBuffer;
00545 destSize *= 2;
00546 } else {
00547
00548 memset(dest, 0, destSize);
00549 }
00550
00551 const int channelCount = channels.size();
00552 const short scalingFactor = (short) ((mode == Fast) ? channelCount : 1);
00553 for(std::vector<Play_ID>::iterator i = channels.begin(); i != channels.end(); i++)
00554 mixChannelAdditively(*i, bitsPerSample, mode, scalingFactor, dest, destSize);
00555
00556 if (mode == Quality) {
00557
00558
00559 destSize /= 2;
00560 if (bitsPerSample == 8) {
00561
00562 char* destChar = (char*) origdest;
00563 short* mixerBufferShort = (short*) mixerBuffer;
00564 for (size_t i = 0; i < destSize; i++) {
00565 destChar[i] = (char) (mixerBufferShort[i] / channelCount);
00566 }
00567 } else {
00568
00569 short* destShort = (short*) origdest;
00570 const size_t destSampleCount = destSize / 2;
00571 for (size_t i = 0; i < destSampleCount; i++) {
00572 destShort[i] = (short) (mixerBuffer[i] / channelCount);
00573 }
00574 }
00575 }
00576 }
00577
00578 updateChannels(channels, origDestSize);
00579 return channels.size();
00580 }
00581
00582 void SoundManager::ProcessMsg(RCRegion * rcr) {
00583 SoundManagerMsg * msg = reinterpret_cast<SoundManagerMsg*>(rcr->Base());
00584
00585 switch(msg->type) {
00586 case SoundManagerMsg::add: {
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 if(sndlist[msg->id].sn!=msg->sn) {
00604
00605
00606
00607
00608
00609 cerr << "Warning: serial numbers don't match... may be pathological sound usage (many load/releases very quickly)" << endl;
00610 break;
00611 }
00612 ASSERT(sndlist[msg->id].rcr==NULL,"The sndlist entry for an add message already has an attached region, I'm going to leak the old region")
00613 rcr->AddReference();
00614 sndlist[msg->id].rcr=rcr;
00615 sndlist[msg->id].data=reinterpret_cast<byte*>(rcr->Base()+MSG_SIZE);
00616
00617 for(playlist_t::index_t it=playlist.begin();it!=playlist.end();it=playlist.next(it))
00618 if(playlist[it].snd_id==msg->id) {
00619
00620 const char * name=sndlist[playlist[it].snd_id].name;
00621 if(name[0]!='\0')
00622 erouter->postEvent(EventBase::audioEGID,it,EventBase::activateETID,0,name,1);
00623 else
00624 erouter->postEvent(EventBase::audioEGID,it,EventBase::activateETID,0);
00625 }
00626 } break;
00627 case SoundManagerMsg::del: {
00628
00629 if(msg->region==NULL) {
00630 cerr << "SoundManager received a delete message for a NULL region" << endl;
00631 } else {
00632 msg->region->RemoveReference();
00633 }
00634 } break;
00635 case SoundManagerMsg::wakeup: {
00636
00637
00638 } break;
00639 default:
00640 printf("*** WARNING *** unknown SoundManager msg type received\n");
00641 }
00642 }
00643
00644
00645
00646
00647 RCRegion*
00648 SoundManager::initRegion(unsigned int size) {
00649 sn++;
00650 #ifdef PLATFORM_APERIOS
00651 unsigned int pagesize=4096;
00652 sError err=GetPageSize(&pagesize);
00653 if(err!=sSUCCESS)
00654 cerr << "Error "<<err<<" getting page size " << pagesize << endl;
00655 unsigned int pages=(size+pagesize-1)/pagesize;
00656 return new RCRegion(pages*pagesize);
00657 #else
00658 char name[RCRegion::MAX_NAME_LEN];
00659 snprintf(name,RCRegion::MAX_NAME_LEN,"SndMsg.%d.%d",ProcessID::getID(),sn);
00660 name[RCRegion::MAX_NAME_LEN-1]='\0';
00661
00662 return new RCRegion(name,size);
00663 #endif
00664 }
00665
00666 SoundManager::Snd_ID
00667 SoundManager::lookupPath(std::string const &path) const {
00668 std::string clippedPath;
00669 const char* cpath=NULL;
00670 if(path.size()>MAX_NAME_LEN) {
00671 clippedPath=path.substr(path.size()-MAX_NAME_LEN);
00672 cpath=clippedPath.c_str();
00673 } else
00674 cpath=path.c_str();
00675 for(sndlist_t::index_t it=sndlist.begin(); it!=sndlist.end(); it=sndlist.next(it)) {
00676 if(strncasecmp(cpath,sndlist[it].name,MAX_NAME_LEN)==0)
00677 return it;
00678 }
00679 return invalid_Snd_ID;
00680 }
00681
00682 void
00683 SoundManager::selectChannels(std::vector<Play_ID>& mix) {
00684 unsigned int selected=0;
00685 switch(queue_mode) {
00686 case Enqueue: {
00687 for(chanlist_t::index_t it=chanlist.prev(chanlist.end());it!=chanlist.end();it=chanlist.prev(it)) {
00688 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00689 mix.push_back(chanlist[it]);
00690 selected++;
00691 if(selected==max_chan)
00692 return;
00693 }
00694 }
00695 } break;
00696 case Override:
00697 case Pause: {
00698 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it)) {
00699 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00700 mix.push_back(chanlist[it]);
00701 selected++;
00702 if(selected==max_chan)
00703 return;
00704 }
00705 }
00706 } break;
00707 case Stop: {
00708 unsigned int numkeep=0;
00709 chanlist_t::index_t it=chanlist.begin();
00710 for(;it!=chanlist.end(); it=chanlist.next(it), numkeep++) {
00711 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00712 mix.push_back(chanlist[it]);
00713 selected++;
00714 if(selected==max_chan) {
00715 for(unsigned int i=chanlist.size()-numkeep-1; i>0; i--)
00716 endPlay(chanlist.back());
00717 return;
00718 }
00719 }
00720 }
00721 } break;
00722 default:
00723 cout << "SoundManager::selectChannels(): Illegal queue mode" << endl;
00724 }
00725 }
00726
00727 void
00728 SoundManager::updateChannels(const std::vector<Play_ID>& mixs,size_t used) {
00729 switch(queue_mode) {
00730 case Enqueue:
00731 case Pause:
00732 case Stop:
00733 break;
00734 case Override: {
00735
00736 chanlist_t::index_t it=chanlist.begin();
00737 std::vector<Play_ID>::const_iterator mixit=mixs.begin();
00738 for(;it!=chanlist.end(); it=chanlist.next(it)) {
00739 for(;mixit!=mixs.end(); mixit++)
00740 if(*mixit==chanlist[it])
00741 break;
00742 if(mixit==mixs.end())
00743 break;
00744 }
00745 for(;it!=chanlist.end(); it=chanlist.next(it)) {
00746 const Play_ID channelId = chanlist[it];
00747 PlayState &channel = playlist[channelId];
00748 size_t skip = used;
00749 while (skip > 0) {
00750 SoundData &buffer = sndlist[channel.snd_id];
00751
00752 if (buffer.data != 0) {
00753 size_t remain = buffer.len - channel.offset;
00754 if (remain < skip) {
00755 channel.offset = buffer.len;
00756 skip -= buffer.len;
00757 if (endPlay(channelId)) {
00758 break;
00759 }
00760 } else {
00761 channel.offset += skip;
00762 skip = 0;
00763 }
00764 } else {
00765 break;
00766 }
00767 }
00768 }
00769 } break;
00770 default:
00771 cout << "SoundManager::updateChannels(): Illegal queue mode" << endl;
00772 }
00773 }
00774
00775 bool
00776 SoundManager::endPlay(Play_ID id) {
00777 if(playlist[id].next_id==invalid_Play_ID) {
00778 stopPlay(id);
00779 return true;
00780 } else {
00781
00782 Play_ID next=playlist[id].next_id;
00783
00784 release(playlist[id].snd_id);
00785 playlist[id].snd_id=playlist[next].snd_id;
00786 playlist[id].cumulative+=playlist[id].offset;
00787 playlist[id].offset=0;
00788 playlist[id].next_id=playlist[next].next_id;
00789 playlist.erase(next);
00790 unsigned int ms=playlist[id].cumulative/(config->sound.sample_bits/8)/(config->sound.sample_rate/1000);
00791 const char * name=sndlist[playlist[id].snd_id].name;
00792 if(name[0]!='\0')
00793 erouter->postEvent(EventBase::audioEGID,id,EventBase::statusETID,ms,name,1);
00794 else
00795 erouter->postEvent(EventBase::audioEGID,id,EventBase::statusETID,ms);
00796 return false;
00797 }
00798 }
00799
00800 SoundManager::SoundData::SoundData()
00801 : rcr(NULL), data(NULL), len(0), ref(0), sn(0)
00802 {
00803 name[0]='\0';
00804 }
00805
00806 SoundManager::PlayState::PlayState()
00807 : snd_id(invalid_Snd_ID), offset(0), cumulative(0), next_id(invalid_Play_ID)
00808 {}
00809
00810
00811 SoundManager::Snd_ID SoundManager::LoadFile(std::string const &name) { return loadFile(name); }
00812 SoundManager::Snd_ID SoundManager::LoadBuffer(const char buf[], unsigned int len) { return loadBuffer(buf,len); }
00813 void SoundManager::ReleaseFile(std::string const &name) { releaseFile(name); }
00814 void SoundManager::Release(Snd_ID id) { release(id); }
00815 SoundManager::Play_ID SoundManager::PlayFile(std::string const &name) { return playFile(name); }
00816 SoundManager::Play_ID SoundManager::PlayBuffer(const char buf[], unsigned int len) { return playBuffer(buf,len); }
00817 SoundManager::Play_ID SoundManager::Play(Snd_ID id) { return play(id); }
00818 SoundManager::Play_ID SoundManager::ChainFile(Play_ID base, std::string const &next) { return chainFile(base,next); }
00819 SoundManager::Play_ID SoundManager::ChainBuffer(Play_ID base, const char buf[], unsigned int len) { return chainBuffer(base,buf,len); }
00820 SoundManager::Play_ID SoundManager::Chain(Play_ID base, Snd_ID next) { return chain(base,next); }
00821 void SoundManager::StopPlay() { stopPlay(); }
00822 void SoundManager::StopPlay(Play_ID id) { stopPlay(id); }
00823 void SoundManager::PausePlay(Play_ID id) { pausePlay(id); }
00824 void SoundManager::ResumePlay(Play_ID id) { resumePlay(id); }
00825 void SoundManager::SetMode(unsigned int max_channels, MixMode_t mixer_mode, QueueMode_t queuing_mode) { setMode(max_channels,mixer_mode,queuing_mode); }
00826 unsigned int SoundManager::GetRemainTime(Play_ID id) const { return getRemainTime(id); }
00827 unsigned int SoundManager::GetNumPlaying() { return getNumPlaying(); }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904