00001 #include "Shared/Config.h"
00002 #include "SoundManager.h"
00003 #include "Shared/LockScope.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 #include <OPENR/OSubject.h>
00011 #include <OPENR/ObjcommEvent.h>
00012
00013
00014 SoundManager * sndman=NULL;
00015
00016
00017 typedef LockScope<ProcessID::NumProcesses> AutoLock;
00018
00019 SoundManager::SoundManager()
00020 : sndlist(),playlist(),chanlist(),mix_mode(Fast),queue_mode(Override),max_chan(4),lock()
00021 {}
00022
00023 void
00024 SoundManager::InitAccess(OSubject* subj) {
00025 subjs[ProcessID::getID()]=subj;
00026 }
00027
00028
00029 SoundManager::Snd_ID
00030 SoundManager::LoadFile(const char* name) {
00031 if(name==NULL || name[0]=='\0')
00032 return invalid_Snd_ID;
00033 AutoLock autolock(lock,ProcessID::getID());
00034 char tmp[MAX_NAME_LEN];
00035 const char* path=makePath(name,tmp);
00036 Snd_ID id=lookupPath(path);
00037 if(id!=invalid_Snd_ID) {
00038
00039 sndlist[id].ref++;
00040 } else {
00041
00042 struct stat buf;
00043 if(stat(path,&buf)==-1) {
00044 cout << "SoundManager::LoadFile(): Sound file not found " << path << endl;
00045 return invalid_Snd_ID;
00046 }
00047 byte * sndbuf=new byte[buf.st_size];
00048 std::ifstream file(path);
00049 file.read(reinterpret_cast<char*>(sndbuf),buf.st_size);
00050 WAV wav;
00051 WAVError error = wav.Set(sndbuf);
00052 if (error != WAV_SUCCESS) {
00053 OSYSLOG1((osyslogERROR, "%s : %s %d","SoundManager::LoadFile()","wav.Set() FAILED", error));
00054 return invalid_Snd_ID;
00055 }
00056 if(wav.GetSamplingRate()!=config->sound.sample_rate || wav.GetBitsPerSample()!=config->sound.sample_bits) {
00057 OSYSLOG1((osyslogERROR, "%s : %s %s","SoundManager::LoadFile()","bad sample rate/bits", error));
00058 return invalid_Snd_ID;
00059 }
00060 id=LoadBuffer(reinterpret_cast<char*>(wav.GetDataStart()),wav.GetDataEnd()-wav.GetDataStart());
00061 delete [] sndbuf;
00062 strncpy(sndlist[id].name,path,MAX_NAME_LEN);
00063 }
00064 return id;
00065 }
00066
00067 SoundManager::Snd_ID
00068 SoundManager::LoadBuffer(const char buf[], unsigned int len) {
00069 cout << "SoundManager::LoadBuffer() of " << len << " bytes" << endl;
00070 if(buf==NULL || len==0)
00071 return invalid_Snd_ID;
00072 AutoLock autolock(lock,ProcessID::getID());
00073
00074 RCRegion * region=initRegion(len+SoundManagerMsg::MSG_SIZE);
00075
00076 SoundManagerMsg * msg=new (reinterpret_cast<SoundManagerMsg*>(region->Base())) SoundManagerMsg;
00077 msg->setAdd(sndlist.new_front());
00078
00079 sndlist[msg->getID()].rcr=NULL;
00080 sndlist[msg->getID()].data=NULL;
00081 sndlist[msg->getID()].ref=1;
00082 sndlist[msg->getID()].len=len;
00083
00084 const byte* src=reinterpret_cast<const byte*>(buf);
00085 byte* dest=reinterpret_cast<byte*>(region->Base())+SoundManagerMsg::MSG_SIZE;
00086 byte* end=dest+len;
00087 if (config->sound.sample_bits==8)
00088 while (dest < end)
00089 *dest++ = *src++ ^ 0x80;
00090 else
00091 while (dest < end)
00092 *dest++ = *src++;
00093
00094 if(ProcessID::getID()==ProcessID::SoundProcess) {
00095
00096 sndlist[msg->getID()].rcr=region;
00097 sndlist[msg->getID()].data=reinterpret_cast<byte*>(region->Base()+SoundManagerMsg::MSG_SIZE);
00098 } else {
00099 subjs[ProcessID::getID()]->SetData(region);
00100 subjs[ProcessID::getID()]->NotifyObservers();
00101 }
00102 return msg->getID();
00103 }
00104
00105 void
00106 SoundManager::ReleaseFile(const char* name) {
00107 if(name==NULL || name[0]=='\0')
00108 return;
00109 AutoLock autolock(lock,ProcessID::getID());
00110 Release(lookup(name));
00111 }
00112
00113 void
00114 SoundManager::Release(Snd_ID id) {
00115 if(id==invalid_Snd_ID)
00116 return;
00117 if(sndlist[id].ref==0) {
00118 cout << "SoundManager::Release() " << id << " extra release" << endl;
00119 return;
00120 }
00121 AutoLock autolock(lock,ProcessID::getID());
00122 sndlist[id].ref--;
00123 if(sndlist[id].ref==0) {
00124
00125
00126 RCRegion * region=initRegion(SoundManagerMsg::MSG_SIZE);
00127
00128 SoundManagerMsg * msg=new (reinterpret_cast<SoundManagerMsg*>(region->Base())) SoundManagerMsg;
00129 msg->setDelete(sndlist[id].rcr);
00130
00131 sndlist.erase(id);
00132
00133 if(ProcessID::getID()==ProcessID::SoundProcess) {
00134 msg->region->RemoveReference();
00135 } else {
00136 subjs[ProcessID::getID()]->SetData(region);
00137 subjs[ProcessID::getID()]->NotifyObservers();
00138 }
00139 }
00140 }
00141
00142 SoundManager::Play_ID
00143 SoundManager::PlayFile(const char* name) {
00144 if(playlist.size()>=playlist_t::MAX_ENTRIES || name==NULL || name[0]=='\0')
00145 return invalid_Play_ID;
00146 AutoLock autolock(lock,ProcessID::getID());
00147 Snd_ID sndid=LoadFile(name);
00148 if(sndid==invalid_Snd_ID)
00149 return invalid_Play_ID;
00150 sndlist[sndid].ref--;
00151 return Play(sndid);
00152 }
00153
00154 SoundManager::Play_ID
00155 SoundManager::PlayBuffer(const char buf[], unsigned int len) {
00156 if(playlist.size()>=playlist_t::MAX_ENTRIES || buf==NULL || len==0)
00157 return invalid_Play_ID;
00158 AutoLock autolock(lock,ProcessID::getID());
00159 Snd_ID sndid=LoadBuffer(buf,len);
00160 if(sndid==invalid_Snd_ID)
00161 return invalid_Play_ID;
00162 sndlist[sndid].ref--;
00163 return Play(sndid);
00164 }
00165
00166 SoundManager::Play_ID
00167 SoundManager::Play(Snd_ID id) {
00168
00169 if(id==invalid_Snd_ID)
00170 return invalid_Play_ID;
00171 AutoLock autolock(lock,ProcessID::getID());
00172 Play_ID playid=playlist.new_front();
00173 if(playid!=invalid_Play_ID) {
00174 sndlist[id].ref++;
00175 playlist[playid].snd_id=id;
00176 playlist[playid].offset=0;
00177
00178
00179 chanlist.push_front(playid);
00180
00181
00182
00183
00184 if(ProcessID::getID()!=ProcessID::SoundProcess) {
00185 RCRegion * region=initRegion(SoundManagerMsg::MSG_SIZE);
00186 ASSERT(region!=NULL,"initRegion returned NULL");
00187 SoundManagerMsg * msg=new (reinterpret_cast<SoundManagerMsg*>(region->Base())) SoundManagerMsg;
00188 msg->setWakeup();
00189 subjs[ProcessID::getID()]->SetData(region);
00190 subjs[ProcessID::getID()]->NotifyObservers();
00191 }
00192
00193
00194 if(sndlist[id].rcr!=NULL)
00195 erouter->postEvent(EventBase::audioEGID,playid,EventBase::activateETID,0);
00196 }
00197 return playid;
00198 }
00199
00200 SoundManager::Play_ID
00201 SoundManager::ChainFile(Play_ID base, const char * next) {
00202 if(base==invalid_Play_ID || next==NULL || next[0]=='\0')
00203 return base;
00204 Play_ID orig=base;
00205 while(playlist[base].next_id!=invalid_Play_ID)
00206 base=playlist[base].next_id;
00207 Play_ID nplay=playlist.new_front();
00208 if(nplay==invalid_Play_ID)
00209 return nplay;
00210 Snd_ID nsnd=LoadFile(next);
00211 if(nsnd==invalid_Snd_ID) {
00212 playlist.pop_front();
00213 return invalid_Play_ID;
00214 }
00215 playlist[nplay].snd_id=nsnd;
00216 playlist[base].next_id=nplay;
00217 return orig;
00218 }
00219
00220 SoundManager::Play_ID
00221 SoundManager::ChainBuffer(Play_ID base, const char buf[], unsigned int len) {
00222 if(base==invalid_Play_ID || buf==NULL || len==0)
00223 return base;
00224 Play_ID orig=base;
00225 while(playlist[base].next_id!=invalid_Play_ID)
00226 base=playlist[base].next_id;
00227 Play_ID nplay=playlist.new_front();
00228 if(nplay==invalid_Play_ID)
00229 return nplay;
00230 Snd_ID nsnd=LoadBuffer(buf,len);
00231 if(nsnd==invalid_Snd_ID) {
00232 playlist.pop_front();
00233 return invalid_Play_ID;
00234 }
00235 playlist[nplay].snd_id=nsnd;
00236 playlist[base].next_id=nplay;
00237 return orig;
00238 }
00239
00240 SoundManager::Play_ID
00241 SoundManager::Chain(Play_ID base, Snd_ID next) {
00242 if(base==invalid_Play_ID || next==invalid_Snd_ID)
00243 return base;
00244 Play_ID orig=base;
00245 while(playlist[base].next_id!=invalid_Play_ID)
00246 base=playlist[base].next_id;
00247 Play_ID nplay=playlist.new_front();
00248 if(nplay==invalid_Play_ID)
00249 return nplay;
00250 playlist[nplay].snd_id=next;
00251 playlist[base].next_id=nplay;
00252 return orig;
00253 }
00254
00255 void
00256 SoundManager::StopPlay() {
00257 while(!playlist.empty())
00258 StopPlay(playlist.begin());
00259 }
00260
00261 void
00262 SoundManager::StopPlay(Play_ID id) {
00263
00264 if(id==invalid_Play_ID)
00265 return;
00266 AutoLock autolock(lock,ProcessID::getID());
00267
00268 for(chanlist_t::index_t it=chanlist.prev(chanlist.end()); it!=chanlist.end(); it=chanlist.prev(it))
00269 if(chanlist[it]==id) {
00270 Release(playlist[id].snd_id);
00271 playlist.erase(id);
00272 chanlist.erase(it);
00273 playlist[id].cumulative+=playlist[id].offset;
00274 unsigned int ms=playlist[id].cumulative/(config->sound.sample_bits/8)/(config->sound.sample_rate/1000);
00275 erouter->postEvent(EventBase::audioEGID,id,EventBase::deactivateETID,ms);
00276 return;
00277 }
00278 cout << "SoundManager::StopPlay(): " << id << " does not seem to be playing" << endl;
00279 }
00280
00281 void
00282 SoundManager::PausePlay(Play_ID id) {
00283 if(id==invalid_Play_ID)
00284 return;
00285 AutoLock autolock(lock,ProcessID::getID());
00286 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it))
00287 if(chanlist[it]==id) {
00288 chanlist.erase(it);
00289 return;
00290 }
00291 }
00292
00293 void
00294 SoundManager::ResumePlay(Play_ID id) {
00295 if(id==invalid_Play_ID)
00296 return;
00297 AutoLock autolock(lock,ProcessID::getID());
00298 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it))
00299 if(chanlist[it]==id)
00300 return;
00301 chanlist.push_front(id);
00302 }
00303
00304 void
00305 SoundManager::SetMode(unsigned int max_channels, MixMode_t mixer_mode, QueueMode_t queuing_mode) {
00306 AutoLock autolock(lock,ProcessID::getID());
00307 max_chan=max_channels;
00308 mix_mode=mixer_mode;
00309 queue_mode=queuing_mode;
00310 }
00311
00312 unsigned int
00313 SoundManager::GetRemainTime(Play_ID id) const {
00314 AutoLock autolock(lock,ProcessID::getID());
00315 unsigned int t=0;
00316 while(id!=invalid_Play_ID) {
00317 t+=sndlist[playlist[id].snd_id].len-playlist[id].offset;
00318 id=playlist[id].next_id;
00319 }
00320 const unsigned int bytesPerMS=config->sound.sample_bits/8*config->sound.sample_rate/1000;
00321 return t/bytesPerMS;
00322 }
00323
00324 unsigned int
00325 SoundManager::CopyTo(OSoundVectorData* data) {
00326 AutoLock autolock(lock,ProcessID::getID());
00327
00328 size_t avail = data->GetInfo(0)->dataSize;
00329 byte* dest = data->GetData(0);
00330 byte* end = dest+avail;
00331
00332 if(chanlist.size()==0) {
00333 memset(dest,0,avail);
00334 return 0;
00335 }
00336
00337 std::vector<Play_ID> mixs;
00338 selectChannels(mixs);
00339
00340 std::vector<byte*> srcs;
00341 std::vector<byte*> ends;
00342 for(std::vector<Play_ID>::iterator it=mixs.begin(); it!=mixs.end(); it++) {
00343 Snd_ID cursnd=playlist[*it].snd_id;
00344 srcs.push_back(sndlist[cursnd].data+playlist[*it].offset);
00345 ends.push_back(sndlist[cursnd].data+sndlist[cursnd].len);
00346 }
00347
00348 if(mixs.size()==0) {
00349 memset(dest,0,avail);
00350 return 1;
00351 } else if(mixs.size()==1) {
00352 size_t remain=ends.front()-srcs.front();
00353 if(remain>=avail) {
00354 memcpy(dest,srcs.front(),avail);
00355 playlist[mixs.front()].offset+=avail;
00356 updateChannels(mixs,avail);
00357 return 1;
00358 } else {
00359 memcpy(dest,srcs.front(),remain);
00360 memset(dest+remain,0,avail-remain);
00361 playlist[mixs.front()].offset=sndlist[playlist[mixs.front()].snd_id].len;
00362 endPlay(mixs.front());
00363 return 0;
00364 }
00365 } else {
00366 if(mix_mode==Fast) {
00367 byte* begin=dest;
00368 unsigned int stopped=0;
00369 if(config->sound.sample_bits==8) {
00370 char size=srcs.size();
00371
00372 for(unsigned int c=0; c<1; c++) {
00373 if((size_t)(ends[c]-srcs[c])>avail) {
00374 for(dest=begin;dest<end;dest++) {
00375 *dest=(*(char*)srcs[c])/size;
00376 srcs[c]++;
00377 }
00378 } else {
00379 for(dest=begin;srcs[c]<ends[c];srcs[c]++) {
00380 *dest=(*(char*)srcs[c])/size;
00381 dest++;
00382 }
00383 playlist[mixs[c]].offset=sndlist[playlist[mixs[c]].snd_id].len;
00384 endPlay(mixs[c]);
00385 stopped++;
00386 memset(dest,0,end-dest);
00387 }
00388 }
00389
00390 for(unsigned int c=1; c<srcs.size(); c++) {
00391 if((size_t)(ends[c]-srcs[c])>avail) {
00392 for(dest=begin;dest<end;dest++) {
00393 *dest+=(*(char*)srcs[c])/size;
00394 srcs[c]++;
00395 }
00396 } else {
00397 for(dest=begin;srcs[c]<ends[c];srcs[c]++) {
00398 *dest+=(*(char*)srcs[c])/size;
00399 dest++;
00400 }
00401 playlist[mixs[c]].offset=sndlist[playlist[mixs[c]].snd_id].len;
00402 endPlay(mixs[c]);
00403 stopped++;
00404 }
00405 }
00406 } else {
00407 short size=srcs.size();
00408
00409 for(unsigned int c=0; c<1; c++) {
00410 if((size_t)(ends[c]-srcs[c])>avail) {
00411 for(dest=begin;dest<end;dest+=2) {
00412 *(short*)dest=(*(short*)srcs[c])/size;
00413 srcs[c]+=2;
00414 }
00415 } else {
00416 for(dest=begin;srcs[c]<ends[c];srcs[c]+=2) {
00417 *(short*)dest=(*(short*)srcs[c])/size;
00418 dest+=2;
00419 }
00420 playlist[mixs[c]].offset=sndlist[playlist[mixs[c]].snd_id].len;
00421 endPlay(mixs[c]);
00422 stopped++;
00423 memset(dest,0,end-dest);
00424 }
00425 }
00426
00427 for(unsigned int c=1; c<srcs.size(); c++) {
00428 if((size_t)(ends[c]-srcs[c])>avail) {
00429 for(dest=begin;dest<end;dest+=2) {
00430 *(short*)dest+=(*(short*)srcs[c])/size;
00431 srcs[c]+=2;
00432 }
00433 } else {
00434 for(dest=begin;srcs[c]<ends[c];srcs[c]+=2) {
00435 *(short*)dest+=(*(short*)srcs[c])/size;
00436 dest+=2;
00437 }
00438 playlist[mixs[c]].offset=sndlist[playlist[mixs[c]].snd_id].len;
00439 endPlay(mixs[c]);
00440 stopped++;
00441 }
00442 }
00443 }
00444 for(unsigned int c=0; c<mixs.size(); c++)
00445 playlist[mixs[c]].offset+=avail;
00446 updateChannels(mixs,avail);
00447 return mixs.size()-stopped;
00448 } else {
00449 if(config->sound.sample_bits==8) {
00450 for(;dest!=end;dest++) {
00451 short total=0;
00452 for(unsigned int c=0; c<srcs.size(); c++) {
00453 if(srcs[c]==ends[c]) {
00454 playlist[mixs[c]].offset=sndlist[playlist[mixs[c]].snd_id].len;
00455 if(endPlay(mixs[c])) {
00456 std::swap(mixs[c],mixs.back());
00457 std::swap(srcs[c],srcs.back());
00458 std::swap(ends[c],ends.back());
00459 mixs.pop_back();
00460 srcs.pop_back();
00461 ends.pop_back();
00462 if(srcs.size()==0) {
00463 memset(dest,0,end-dest);
00464 return 0;
00465 }
00466 continue;
00467 }
00468 }
00469 total+=*(char*)srcs[c];
00470 srcs[c]++;
00471 }
00472 *dest=total/(int)srcs.size();
00473 }
00474 } else {
00475 for(;dest!=end;dest+=2) {
00476 int total=0;
00477 for(unsigned int c=0; c<srcs.size(); c++) {
00478 if(srcs[c]==ends[c]) {
00479 playlist[mixs[c]].offset=sndlist[playlist[mixs[c]].snd_id].len;
00480 if(endPlay(mixs[c])) {
00481 std::swap(mixs[c],mixs.back());
00482 std::swap(srcs[c],srcs.back());
00483 std::swap(ends[c],ends.back());
00484 mixs.pop_back();
00485 srcs.pop_back();
00486 ends.pop_back();
00487 if(srcs.size()==0) {
00488 memset(dest,0,end-dest);
00489 return 0;
00490 }
00491 continue;
00492 }
00493 }
00494 total+=*(short*)srcs[c];
00495 srcs[c]+=2;
00496 }
00497 *(short*)dest=total/(int)srcs.size();
00498 }
00499 }
00500 for(unsigned int c=0; c<mixs.size(); c++)
00501 playlist[mixs[c]].offset+=avail;
00502 updateChannels(mixs,avail);
00503 return mixs.size();
00504 }
00505 }
00506 }
00507
00508 void
00509 SoundManager::ReceivedMsg(const ONotifyEvent& event) {
00510 for(int x=0; x<event.NumOfData(); x++) {
00511 RCRegion * rcr = event.RCData(x);
00512 SoundManagerMsg * msg = reinterpret_cast<SoundManagerMsg*>(rcr->Base());
00513 switch(msg->type) {
00514 case SoundManagerMsg::add: {
00515 rcr->AddReference();
00516 sndlist[msg->id].rcr=rcr;
00517 sndlist[msg->id].data=reinterpret_cast<byte*>(rcr->Base()+SoundManagerMsg::MSG_SIZE);
00518
00519 for(playlist_t::index_t it=playlist.begin();it!=playlist.end();it=playlist.next(it))
00520 if(playlist[it].snd_id==msg->id)
00521
00522 erouter->postEvent(EventBase::audioEGID,it,EventBase::activateETID,0);
00523 } break;
00524 case SoundManagerMsg::del: {
00525 msg->region->RemoveReference();
00526 } break;
00527 case SoundManagerMsg::wakeup: {
00528
00529 } break;
00530 default:
00531 printf("*** WARNING *** unknown SoundManager msg type received\n");
00532 }
00533 }
00534 }
00535
00536
00537
00538 RCRegion*
00539 SoundManager::initRegion(unsigned int size) {
00540 unsigned int pagesize=4096;
00541 sError err=GetPageSize(&pagesize);
00542 ASSERT(err==sSUCCESS,"Error "<<err<<" getting page size");
00543 unsigned int pages=(size+pagesize-1)/pagesize;
00544 return new RCRegion(pages*pagesize);
00545 }
00546
00547 SoundManager::Snd_ID
00548 SoundManager::lookup(const char* name) const {
00549 char tmp[MAX_NAME_LEN];
00550 return lookupPath(makePath(name,tmp));
00551 }
00552 SoundManager::Snd_ID
00553 SoundManager::lookupPath(const char* path) const {
00554 for(sndlist_t::index_t it=sndlist.begin(); it!=sndlist.end(); it=sndlist.next(it))
00555 if(strncasecmp(path,sndlist[it].name,MAX_NAME_LEN)==0)
00556 return it;
00557 return invalid_Snd_ID;
00558 }
00559
00560 const char*
00561 SoundManager::makePath(const char* name, char tmp[MAX_NAME_LEN]) {
00562 const char* path=name;
00563 if(name[0]!='/') {
00564 path=tmp;
00565 strncpy(tmp,config->sound.root.c_str(),MAX_NAME_LEN);
00566 strncat(tmp,"/",MAX_NAME_LEN);
00567 strncat(tmp,name,MAX_NAME_LEN);
00568 }
00569
00570 return path;
00571 }
00572
00573 void
00574 SoundManager::selectChannels(std::vector<Play_ID>& mix) {
00575 unsigned int selected=0;
00576 switch(queue_mode) {
00577 case Enqueue: {
00578 for(chanlist_t::index_t it=chanlist.prev(chanlist.end());it!=chanlist.end();it=chanlist.prev(it)) {
00579 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00580 mix.push_back(chanlist[it]);
00581 selected++;
00582 if(selected==max_chan)
00583 return;
00584 }
00585 }
00586 } break;
00587 case Override:
00588 case Pause: {
00589 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it)) {
00590 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00591 mix.push_back(chanlist[it]);
00592 selected++;
00593 if(selected==max_chan)
00594 return;
00595 }
00596 }
00597 } break;
00598 case Stop: {
00599 unsigned int numkeep=0;
00600 chanlist_t::index_t it=chanlist.begin();
00601 for(;it!=chanlist.end(); it=chanlist.next(it), numkeep++) {
00602 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00603 mix.push_back(chanlist[it]);
00604 selected++;
00605 if(selected==max_chan) {
00606 for(unsigned int i=chanlist.size()-numkeep-1; i>0; i--)
00607 endPlay(chanlist.back());
00608 return;
00609 }
00610 }
00611 }
00612 } break;
00613 default:
00614 cout << "SoundManager::selectChannels(): Illegal queue mode" << endl;
00615 }
00616 }
00617
00618 void
00619 SoundManager::updateChannels(const std::vector<Play_ID>& mixs,size_t used) {
00620 switch(queue_mode) {
00621 case Enqueue:
00622 case Pause:
00623 case Stop:
00624 break;
00625 case Override: {
00626
00627 chanlist_t::index_t it=chanlist.begin();
00628 std::vector<Play_ID>::const_iterator mixit=mixs.begin();
00629 for(;it!=chanlist.end(); it=chanlist.next(it)) {
00630 for(;mixit!=mixs.end(); mixit++)
00631 if(*mixit==chanlist[it])
00632 break;
00633 if(mixit==mixs.end())
00634 break;
00635 }
00636 for(;it!=chanlist.end(); it=chanlist.next(it)) {
00637 Snd_ID cursnd=playlist[chanlist[it]].snd_id;
00638 if(sndlist[cursnd].data!=NULL) {
00639 size_t remain = sndlist[cursnd].len-playlist[chanlist[it]].offset;
00640 if(remain<used) {
00641 playlist[chanlist[it]].offset=sndlist[playlist[chanlist[it]].snd_id].len;
00642 endPlay(chanlist[it]);
00643 } else {
00644 playlist[chanlist[it]].offset+=used;
00645 }
00646 }
00647 }
00648 } break;
00649 default:
00650 cout << "SoundManager::updateChannels(): Illegal queue mode" << endl;
00651 }
00652 }
00653
00654 bool
00655 SoundManager::endPlay(Play_ID id) {
00656 if(playlist[id].next_id==invalid_Play_ID) {
00657 StopPlay(id);
00658 return true;
00659 } else {
00660
00661 Play_ID next=playlist[id].next_id;
00662
00663 Release(playlist[id].snd_id);
00664 playlist[id].snd_id=playlist[next].snd_id;
00665 playlist[id].cumulative+=playlist[id].offset;
00666 playlist[id].offset=0;
00667 playlist[id].next_id=playlist[next].next_id;
00668 playlist.erase(next);
00669 unsigned int ms=playlist[id].cumulative/(config->sound.sample_bits/8)/(config->sound.sample_rate/1000);
00670 erouter->postEvent(EventBase::audioEGID,id,EventBase::statusETID,ms);
00671 return false;
00672 }
00673 }
00674
00675 SoundManager::SoundData::SoundData()
00676 : rcr(NULL), data(NULL), len(0), ref(0)
00677 {
00678 name[0]='\0';
00679 }
00680
00681 SoundManager::PlayState::PlayState()
00682 : snd_id(invalid_Snd_ID), offset(0), cumulative(0), next_id(invalid_Play_ID)
00683 {}
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760