00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "ArExport.h"
00028 #include "ArLog.h"
00029 #include "ariaUtil.h"
00030 #include "ArSoundsQueue.h"
00031 #include "ArSoundPlayer.h"
00032 #include <assert.h>
00033
00034
00035
00036
00037
00038
00039
00040 #define debuglog(msg) {}
00041
00042 using namespace std;
00043
00044
00045 ArSoundsQueue::Item::Item() :
00046 data(""), type(OTHER), params(""), priority(0)
00047 {
00048 }
00049
00050 ArSoundsQueue::Item::Item(std::string _data, ItemType _type, std::string _params, int _priority, std::list<PlayItemFunctor*> _callbacks) :
00051 data(_data), type(_type), params(_params), priority(_priority), playCallbacks(_callbacks)
00052 {
00053 }
00054
00055 ArSoundsQueue::Item::Item(std::string _data, ItemType _type, std::string _params, int _priority) :
00056 data(_data), type(_type), params(_params), priority(_priority)
00057 {
00058 }
00059
00060 ArSoundsQueue::Item::Item(const Item& toCopy)
00061 {
00062 data = toCopy.data;
00063 type = toCopy.type;
00064 params = toCopy.params;
00065 priority = toCopy.priority;
00066 playCallbacks = toCopy.playCallbacks;
00067 interruptCallbacks = toCopy.interruptCallbacks;
00068 }
00069
00070 void ArSoundsQueue::Item::play()
00071 {
00072 for(std::list<PlayItemFunctor*>::const_iterator i = playCallbacks.begin(); i != playCallbacks.end(); i++)
00073 if(*i) {
00074 (*i)->invokeR(data.c_str(), params.c_str());
00075 }
00076 }
00077
00078 void ArSoundsQueue::Item::interrupt()
00079 {
00080 for(std::list<ArFunctor*>::const_iterator i = interruptCallbacks.begin(); i != interruptCallbacks.end(); i++)
00081 if(*i) (*i)->invoke();
00082 }
00083
00084
00088 class ItemComparator {
00089 protected:
00090 ArSoundsQueue::Item myItem;
00091 public:
00092 ItemComparator(string data = "", ArSoundsQueue::ItemType type = ArSoundsQueue::OTHER, string params = "", int priority = 0) :
00093 myItem(data, type, params, priority)
00094 {}
00095 virtual ~ItemComparator() {}
00096 virtual bool operator()(const ArSoundsQueue::Item& other)
00097 {
00098 return (other == myItem && other.priority == myItem.priority);
00099 }
00100 };
00101
00105 class ItemComparator_OnlyData : public virtual ItemComparator {
00106 public:
00107 ItemComparator_OnlyData(string data) :
00108 ItemComparator(data)
00109 {}
00110 virtual bool operator()(const ArSoundsQueue::Item& other)
00111 {
00112 return(other.data == myItem.data);
00113 }
00114 };
00115
00119 class ItemComparator_TypeAndData : public virtual ItemComparator {
00120 public:
00121 ItemComparator_TypeAndData(string data, ArSoundsQueue::ItemType type) :
00122 ItemComparator(data, type)
00123 {}
00124 virtual bool operator()(const ArSoundsQueue::Item& other)
00125 {
00126 return(other.type == myItem.type && other.data == myItem.data);
00127 }
00128 };
00129
00133 class ItemComparator_PriorityLessThan : public virtual ItemComparator {
00134 int myPriority;
00135 public:
00136 ItemComparator_PriorityLessThan(int priority) : myPriority(priority)
00137 {}
00138 virtual bool operator()(const ArSoundsQueue::Item& other)
00139 {
00140 return(other.priority < myPriority);
00141 }
00142 };
00143
00147 class ItemComparator_WithTypePriorityLessThan : public virtual ItemComparator {
00148 ArSoundsQueue::ItemType myType;
00149 int myPriority;
00150 public:
00151 ItemComparator_WithTypePriorityLessThan(ArSoundsQueue::ItemType type, int priority) : myType(type), myPriority(priority)
00152 {}
00153 virtual bool operator()(const ArSoundsQueue::Item& other)
00154 {
00155 return(other.type == myType && other.priority < myPriority);
00156 }
00157 };
00158
00163 class ItemComparator_WithType : public virtual ItemComparator {
00164 ArSoundsQueue::ItemType myType;
00165 public:
00166 ItemComparator_WithType(ArSoundsQueue::ItemType type) : myType(type)
00167 {}
00168 virtual bool operator()(const ArSoundsQueue::Item& other)
00169 {
00170 return(other.type == myType);
00171 }
00172 };
00173
00174
00175 ArSoundsQueue::ArSoundsQueue() :
00176 myInitialized(false),
00177 myPlayingSomething(false),
00178 myDefaultSpeakCB(0), myDefaultInterruptSpeechCB(0),
00179 myDefaultPlayFileCB(0), myDefaultInterruptFileCB(0),
00180 myPauseRequestCount(0)
00181 {
00182 setThreadName("ArSoundsQueue");
00183 }
00184
00185 ArSoundsQueue::ArSoundsQueue(ArRetFunctor<bool> *speakInitCB,
00186 PlayItemFunctor *speakCB,
00187 InterruptItemFunctor *interruptSpeechCB,
00188 ArRetFunctor<bool> *playInitCB,
00189 PlayItemFunctor *playCB,
00190 InterruptItemFunctor *interruptFileCB) :
00191 myInitialized(false), myPlayingSomething(false),
00192 myDefaultSpeakCB(speakCB), myDefaultInterruptSpeechCB(interruptSpeechCB),
00193 myDefaultPlayFileCB(playCB), myDefaultInterruptFileCB(interruptFileCB),
00194 myPauseRequestCount(0)
00195 {
00196 setThreadName("ArSoundsQueue");
00197 if(speakInitCB)
00198 myInitCallbacks.push_back(speakInitCB);
00199 if(playInitCB)
00200 myInitCallbacks.push_back(playInitCB);
00201 if(playCB == 0)
00202 myDefaultPlayFileCB = ArSoundPlayer::getPlayWavFileCallback();
00203 if(interruptFileCB == 0)
00204 myDefaultInterruptFileCB = ArSoundPlayer::getStopPlayingCallback();
00205 }
00206
00207 ArSoundsQueue::ArSoundsQueue(ArSpeechSynth* speechSynth,
00208 ArRetFunctor<bool> *playInitCB,
00209 PlayItemFunctor *playFileCB,
00210 InterruptItemFunctor *interruptFileCB)
00211 : myInitialized(false), myPlayingSomething(false),
00212 myDefaultSpeakCB(0), myDefaultInterruptSpeechCB(0),
00213 myDefaultPlayFileCB(playFileCB), myDefaultInterruptFileCB(interruptFileCB),
00214 myPauseRequestCount(0)
00215 {
00216 setThreadName("ArSoundsQueue");
00217 if(playInitCB)
00218 myInitCallbacks.push_back(playInitCB);
00219 if(speechSynth)
00220 {
00221 myInitCallbacks.push_back(speechSynth->getInitCallback());
00222 myDefaultSpeakCB = speechSynth->getSpeakCallback();
00223 myDefaultInterruptSpeechCB = speechSynth->getInterruptCallback();
00224 }
00225 }
00226
00227 ArSoundsQueue::~ArSoundsQueue()
00228 {
00229
00230 }
00231
00232
00233 void ArSoundsQueue::invokeCallbacks(const std::list<ArFunctor*>& lst)
00234 {
00235 for(std::list<ArFunctor*>::const_iterator i = lst.begin(); i != lst.end(); i++)
00236 {
00237 if(*i) (*i)->invoke();
00238 else ArLog::log(ArLog::Verbose, "ArSoundsQueue: warning: skipped NULL callback (simple functor).");
00239 }
00240 }
00241
00242 void ArSoundsQueue::invokeCallbacks(const std::list<ArRetFunctor<bool>*>& lst)
00243 {
00244 for(std::list<ArRetFunctor<bool>*>::const_iterator i = lst.begin(); i != lst.end(); i++)
00245 {
00246 if(*i) (*i)->invokeR();
00247 else ArLog::log(ArLog::Verbose, "ArSoundsQueue: warning: skipped NULL callback (bool ret. funct.).");
00248 }
00249 }
00250
00251
00252
00253
00254 void ArSoundsQueue::addItem(ItemType type, const char* data, std::list<PlayItemFunctor*> callbacks, int priority, const char* params)
00255 {
00256 assert(data);
00257 pushQueueItem(Item(data, type, params?params:"", priority, callbacks));
00258 }
00259
00260
00261
00262 void ArSoundsQueue::addItem(ArSoundsQueue::Item item)
00263 {
00264 pushQueueItem(item);
00265 }
00266
00267
00268 void ArSoundsQueue::pushQueueItem(ArSoundsQueue::Item item)
00269 {
00270 lock();
00271 pushQueueItem_NoLock(item);
00272 unlock();
00273 }
00274
00275
00276
00277 void ArSoundsQueue::pushQueueItem_NoLock(ArSoundsQueue::Item item)
00278 {
00279 ArLog::log(ArLog::Verbose, "ArSoundsQueue: pushing \"%s\" with type=%d, priority=%d, params=\"%s\".", item.data.c_str(), item.type, item.priority, item.params.c_str());
00280 myQueue.push_back(item);
00281 }
00282
00283 ArSoundsQueue::Item ArSoundsQueue::popQueueItem()
00284 {
00285 lock();
00286 ArSoundsQueue::Item item = *(myQueue.begin());
00287 myQueue.pop_front();
00288 unlock();
00289 return item;
00290 }
00291
00292 ArSoundsQueue::Item ArSoundsQueue::popQueueItem_NoLock()
00293 {
00294 ArSoundsQueue::Item item = *(myQueue.begin());
00295 myQueue.pop_front();
00296 return item;
00297 }
00298
00299 ArSoundsQueue::Item ArSoundsQueue::createDefaultSpeechItem(const char* speech)
00300 {
00301 Item item;
00302 item.type = SPEECH;
00303 if(myDefaultSpeakCB)
00304 item.playCallbacks.push_back(myDefaultSpeakCB);
00305 if(myDefaultInterruptSpeechCB)
00306 item.interruptCallbacks.push_back(myDefaultInterruptSpeechCB);
00307 if(speech)
00308 item.data = speech;
00309 return item;
00310 }
00311
00312 void ArSoundsQueue::speak(const char *str, ...)
00313 {
00314 if(myQueue.size() == 0)
00315 invokeCallbacks(myQueueNonemptyCallbacks);
00316
00317 char *buf;
00318 size_t buflen = (strlen(str) + 1000 * 2);
00319 buf = new char[buflen];
00320
00321 Item item = createDefaultSpeechItem();
00322
00323 lock();
00324 va_list ptr;
00325 va_start(ptr, str);
00326 vsnprintf(buf, buflen, str, ptr);
00327 item.data = buf;
00328 pushQueueItem_NoLock(item);
00329 va_end(ptr);
00330 delete[] buf;
00331 unlock();
00332 }
00333
00334 void ArSoundsQueue::speakWithVoice(const char* voice, const char* str, ...)
00335 {
00336 if(myQueue.size() == 0)
00337 invokeCallbacks(myQueueNonemptyCallbacks);
00338
00339 char *buf;
00340 size_t buflen = (strlen(str) + 1000 * 2);
00341 buf = new char[buflen];
00342
00343 Item item = createDefaultSpeechItem();
00344 string params = "name=";
00345 params += voice;
00346 item.params = params;
00347
00348 lock();
00349 va_list ptr;
00350 va_start(ptr, str);
00351 vsnprintf(buf, buflen, str, ptr);
00352 item.data = buf;
00353 pushQueueItem_NoLock(item);
00354 va_end(ptr);
00355 delete[] buf;
00356 unlock();
00357 }
00358
00359 void ArSoundsQueue::speakWithPriority(int priority, const char* str, ...)
00360 {
00361 if(myQueue.size() == 0)
00362 invokeCallbacks(myQueueNonemptyCallbacks);
00363
00364 char *buf;
00365 size_t buflen = (strlen(str) + 1000 * 2);
00366 buf = new char[buflen];
00367
00368 Item item = createDefaultSpeechItem();
00369 item.priority = priority;
00370
00371 lock();
00372 va_list ptr;
00373 va_start(ptr, str);
00374 vsnprintf(buf, buflen, str, ptr);
00375 item.data = buf;
00376 pushQueueItem_NoLock(item);
00377 va_end(ptr);
00378 delete[] buf;
00379 unlock();
00380 }
00381
00382 ArSoundsQueue::Item ArSoundsQueue::createDefaultFileItem(const char* filename)
00383 {
00384 Item item;
00385 item.type = SOUND_FILE;
00386 if(myDefaultPlayFileCB)
00387 item.playCallbacks.push_back(myDefaultPlayFileCB);
00388 else
00389 ArLog::log(ArLog::Normal, "ArSoundsQueue: Internal Warning: no default PlayFile callback.");
00390 if(myDefaultInterruptFileCB)
00391 item.interruptCallbacks.push_back(myDefaultInterruptFileCB);
00392 if(filename)
00393 item.data = filename;
00394 return item;
00395 }
00396
00397 void ArSoundsQueue::play(const char *str, ...)
00398 {
00399 if(myQueue.size() == 0)
00400 invokeCallbacks(myQueueNonemptyCallbacks);
00401
00402 char buf[2048];
00403 Item item = createDefaultFileItem();
00404
00405 lock();
00406 va_list ptr;
00407 va_start(ptr, str);
00408 vsnprintf(buf, 2048, str, ptr);
00409 item.data = buf;
00410 va_end(ptr);
00411 unlock();
00412
00413 pushQueueItem(item);
00414 }
00415
00416 void *ArSoundsQueue::runThread(void *arg)
00417 {
00418 threadStarted();
00419 invokeCallbacks(myInitCallbacks);
00420 debuglog("the init callbacks were called.");
00421 myInitialized = true;
00422
00423 while (getRunning())
00424 {
00425 lock();
00426 if(myPauseRequestCount > 0)
00427 {
00428 unlock();
00429 myPausedCondition.wait();
00430 lock();
00431 }
00432 if (myQueue.size() > 0)
00433 {
00434 myLastItem = popQueueItem_NoLock();
00435 myPlayingSomething = true;
00436 unlock();
00437
00438
00439 invokeCallbacks(myStartPlaybackCBList);
00440
00441
00442 #ifdef DEBUG
00443 ArLog::log(ArLog::Normal, "Acting on item. type=%d", myLastItem.type);
00444 #endif
00445 myLastItem.play();
00446
00447
00448 debuglog("Finished acting on item. Invoking endPlayback callbacks...");
00449 invokeCallbacks(myEndPlaybackCBList);
00450
00451
00452
00453 ArUtil::sleep(200);
00454
00455 lock();
00456 myPlayingSomething = false;
00457 unlock();
00458
00459 if(myQueue.size() == 0)
00460 {
00461 debuglog("invoking queue-empty callbacks!");
00462 invokeCallbacks(myQueueEmptyCallbacks);
00463 }
00464 }
00465 else
00466 {
00467 unlock();
00468 ArUtil::sleep(20);
00469 }
00470 }
00471 return NULL;
00472 }
00473
00474
00475 void ArSoundsQueue::pause()
00476 {
00477 lock();
00478 myPauseRequestCount++;
00479 unlock();
00480 }
00481
00482 void ArSoundsQueue::resume()
00483 {
00484 ArLog::log(ArLog::Verbose, "ArSoundsQueue::resume: requested.");
00485 lock();
00486 if(--myPauseRequestCount <= 0)
00487 {
00488 myPauseRequestCount = 0;
00489 ArLog::log(ArLog::Verbose, "ArSoundsQueue::resume: unpausing.");
00490 unlock();
00491 myPausedCondition.signal();
00492 } else {
00493 unlock();
00494 }
00495 }
00496
00497 void ArSoundsQueue::stop()
00498 {
00499 stopRunning();
00500 }
00501
00502 bool ArSoundsQueue::isPaused()
00503 {
00504 return (myPauseRequestCount > 0);
00505 }
00506
00507 void ArSoundsQueue::interrupt()
00508 {
00509 lock();
00510
00511
00512
00513 if(myPlayingSomething)
00514 myLastItem.interrupt();
00515 myPlayingSomething = false;
00516 unlock();
00517 }
00518
00519 void ArSoundsQueue::clearQueue()
00520 {
00521 lock();
00522 myQueue.clear();
00523 unlock();
00524 invokeCallbacks(myQueueEmptyCallbacks);
00525 }
00526
00527 set<int> ArSoundsQueue::findPendingItems(const char* item)
00528 {
00529 lock();
00530 set<int> found;
00531 int pos = 0;
00532 for(list<Item>::const_iterator i = myQueue.begin(); i != myQueue.end(); i++)
00533 {
00534 if((*i).data == item)
00535 found.insert(pos);
00536 pos++;
00537 }
00538 unlock();
00539 return found;
00540 }
00541
00542 void ArSoundsQueue::removePendingItems(const char* item, ItemType type)
00543 {
00544 lock();
00545 myQueue.remove_if<ItemComparator_TypeAndData>(ItemComparator_TypeAndData(item, type));
00546 unlock();
00547 }
00548
00549
00550 void ArSoundsQueue::removePendingItems(const char* data)
00551 {
00552 lock();
00553 myQueue.remove_if<ItemComparator_OnlyData>(ItemComparator_OnlyData(data));
00554 unlock();
00555 }
00556
00557 void ArSoundsQueue::removePendingItems(int priority)
00558 {
00559 lock();
00560 myQueue.remove_if<ItemComparator_PriorityLessThan>(ItemComparator_PriorityLessThan(priority));
00561 unlock();
00562 }
00563
00564 void ArSoundsQueue::removePendingItems(int priority, ItemType type)
00565 {
00566 lock();
00567 myQueue.remove_if<ItemComparator_WithTypePriorityLessThan>(ItemComparator_WithTypePriorityLessThan(type, priority));
00568 unlock();
00569 }
00570
00571 void ArSoundsQueue::removePendingItems(ItemType type)
00572 {
00573 lock();
00574 myQueue.remove_if<ItemComparator_WithType>(ItemComparator_WithType(type));
00575 unlock();
00576 }
00577
00578 string ArSoundsQueue::nextItem(ItemType type)
00579 {
00580 lock();
00581 for(list<Item>::const_iterator i = myQueue.begin(); i != myQueue.end(); i++)
00582 {
00583 if(type == (*i).type) {
00584 string found = (*i).data;
00585 unlock();
00586 return found;
00587 }
00588 }
00589 unlock();
00590 return "";
00591 }
00592
00593 string ArSoundsQueue::nextItem(int priority)
00594 {
00595 lock();
00596 for(list<Item>::const_iterator i = myQueue.begin(); i != myQueue.end(); i++)
00597 {
00598 if((*i).priority >= priority) {
00599 string found = (*i).data;
00600 unlock();
00601 return found;
00602 }
00603 }
00604 unlock();
00605 return "";
00606 }
00607
00608 string ArSoundsQueue::nextItem(ItemType type, int priority)
00609 {
00610 lock();
00611 for(list<Item>::const_iterator i = myQueue.begin(); i != myQueue.end(); i++)
00612 {
00613 if(type == (*i).type && (*i).priority >= priority) {
00614 string found = (*i).data;
00615 unlock();
00616 return found;
00617 }
00618 }
00619 unlock();
00620 return "";
00621 }
00622
00623