| 1100 | } |
| 1101 | |
| 1102 | bool SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const al::span<const ALint> values) |
| 1103 | { |
| 1104 | ALCdevice *device{Context->mDevice.get()}; |
| 1105 | ALbuffer *buffer{nullptr}; |
| 1106 | ALfilter *filter{nullptr}; |
| 1107 | ALeffectslot *slot{nullptr}; |
| 1108 | ALbufferlistitem *oldlist{nullptr}; |
| 1109 | std::unique_lock<std::mutex> slotlock; |
| 1110 | std::unique_lock<std::mutex> filtlock; |
| 1111 | std::unique_lock<std::mutex> buflock; |
| 1112 | ALfloat fvals[6]; |
| 1113 | |
| 1114 | switch(prop) |
| 1115 | { |
| 1116 | case AL_SOURCE_STATE: |
| 1117 | case AL_SOURCE_TYPE: |
| 1118 | case AL_BUFFERS_QUEUED: |
| 1119 | case AL_BUFFERS_PROCESSED: |
| 1120 | /* Query only */ |
| 1121 | SETERR_RETURN(Context, AL_INVALID_OPERATION, false, |
| 1122 | "Setting read-only source property 0x%04x", prop); |
| 1123 | |
| 1124 | case AL_SOURCE_RELATIVE: |
| 1125 | CHECKSIZE(values, 1); |
| 1126 | CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); |
| 1127 | |
| 1128 | Source->HeadRelative = values[0] != AL_FALSE; |
| 1129 | return UpdateSourceProps(Source, Context); |
| 1130 | |
| 1131 | case AL_LOOPING: |
| 1132 | CHECKSIZE(values, 1); |
| 1133 | CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); |
| 1134 | |
| 1135 | Source->Looping = values[0] != AL_FALSE; |
| 1136 | if(IsPlayingOrPaused(Source)) |
| 1137 | { |
| 1138 | if(ALvoice *voice{GetSourceVoice(Source, Context)}) |
| 1139 | { |
| 1140 | if(Source->Looping) |
| 1141 | voice->mLoopBuffer.store(Source->queue, std::memory_order_release); |
| 1142 | else |
| 1143 | voice->mLoopBuffer.store(nullptr, std::memory_order_release); |
| 1144 | |
| 1145 | /* If the source is playing, wait for the current mix to finish |
| 1146 | * to ensure it isn't currently looping back or reaching the |
| 1147 | * end. |
| 1148 | */ |
| 1149 | while((device->MixCount.load(std::memory_order_acquire)&1)) |
| 1150 | std::this_thread::yield(); |
| 1151 | } |
| 1152 | } |
| 1153 | return true; |
| 1154 | |
| 1155 | case AL_BUFFER: |
| 1156 | CHECKSIZE(values, 1); |
| 1157 | buflock = std::unique_lock<std::mutex>{device->BufferLock}; |
| 1158 | if(values[0] && (buffer=LookupBuffer(device, static_cast<ALuint>(values[0]))) == nullptr) |
| 1159 | SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid buffer ID %u", |
no test coverage detected