event.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "config.h"
  2. #include "AL/alc.h"
  3. #include "AL/al.h"
  4. #include "AL/alext.h"
  5. #include "alMain.h"
  6. #include "alError.h"
  7. #include "alAuxEffectSlot.h"
  8. #include "ringbuffer.h"
  9. int EventThread(void *arg)
  10. {
  11. ALCcontext *context = arg;
  12. bool quitnow = false;
  13. while(!quitnow)
  14. {
  15. ALbitfieldSOFT enabledevts;
  16. AsyncEvent evt;
  17. if(ll_ringbuffer_read(context->AsyncEvents, (char*)&evt, 1) == 0)
  18. {
  19. alsem_wait(&context->EventSem);
  20. continue;
  21. }
  22. almtx_lock(&context->EventCbLock);
  23. do {
  24. quitnow = evt.EnumType == EventType_KillThread;
  25. if(quitnow) break;
  26. if(evt.EnumType == EventType_ReleaseEffectState)
  27. {
  28. ALeffectState_DecRef(evt.u.EffectState);
  29. continue;
  30. }
  31. enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_acquire);
  32. if(context->EventCb && (enabledevts&evt.EnumType) == evt.EnumType)
  33. context->EventCb(evt.u.user.type, evt.u.user.id, evt.u.user.param,
  34. (ALsizei)strlen(evt.u.user.msg), evt.u.user.msg, context->EventParam
  35. );
  36. } while(ll_ringbuffer_read(context->AsyncEvents, (char*)&evt, 1) != 0);
  37. almtx_unlock(&context->EventCbLock);
  38. }
  39. return 0;
  40. }
  41. AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable)
  42. {
  43. ALCcontext *context;
  44. ALbitfieldSOFT enabledevts;
  45. ALbitfieldSOFT flags = 0;
  46. ALsizei i;
  47. context = GetContextRef();
  48. if(!context) return;
  49. if(count < 0) SETERR_GOTO(context, AL_INVALID_VALUE, done, "Controlling %d events", count);
  50. if(count == 0) goto done;
  51. if(!types) SETERR_GOTO(context, AL_INVALID_VALUE, done, "NULL pointer");
  52. for(i = 0;i < count;i++)
  53. {
  54. if(types[i] == AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT)
  55. flags |= EventType_BufferCompleted;
  56. else if(types[i] == AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT)
  57. flags |= EventType_SourceStateChange;
  58. else if(types[i] == AL_EVENT_TYPE_ERROR_SOFT)
  59. flags |= EventType_Error;
  60. else if(types[i] == AL_EVENT_TYPE_PERFORMANCE_SOFT)
  61. flags |= EventType_Performance;
  62. else if(types[i] == AL_EVENT_TYPE_DEPRECATED_SOFT)
  63. flags |= EventType_Deprecated;
  64. else if(types[i] == AL_EVENT_TYPE_DISCONNECTED_SOFT)
  65. flags |= EventType_Disconnected;
  66. else
  67. SETERR_GOTO(context, AL_INVALID_ENUM, done, "Invalid event type 0x%04x", types[i]);
  68. }
  69. if(enable)
  70. {
  71. enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
  72. while(ATOMIC_COMPARE_EXCHANGE_WEAK(&context->EnabledEvts, &enabledevts, enabledevts|flags,
  73. almemory_order_acq_rel, almemory_order_acquire) == 0)
  74. {
  75. /* enabledevts is (re-)filled with the current value on failure, so
  76. * just try again.
  77. */
  78. }
  79. }
  80. else
  81. {
  82. enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
  83. while(ATOMIC_COMPARE_EXCHANGE_WEAK(&context->EnabledEvts, &enabledevts, enabledevts&~flags,
  84. almemory_order_acq_rel, almemory_order_acquire) == 0)
  85. {
  86. }
  87. /* Wait to ensure the event handler sees the changed flags before
  88. * returning.
  89. */
  90. almtx_lock(&context->EventCbLock);
  91. almtx_unlock(&context->EventCbLock);
  92. }
  93. done:
  94. ALCcontext_DecRef(context);
  95. }
  96. AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam)
  97. {
  98. ALCcontext *context;
  99. context = GetContextRef();
  100. if(!context) return;
  101. almtx_lock(&context->PropLock);
  102. almtx_lock(&context->EventCbLock);
  103. context->EventCb = callback;
  104. context->EventParam = userParam;
  105. almtx_unlock(&context->EventCbLock);
  106. almtx_unlock(&context->PropLock);
  107. ALCcontext_DecRef(context);
  108. }