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