| 31 | } |
| 32 | |
| 33 | static void waitForPlaybackToEnd(Macro *macro, obs_source_t *source, |
| 34 | int64_t maxMs = 0) |
| 35 | { |
| 36 | using namespace std::chrono_literals; |
| 37 | |
| 38 | std::unique_lock<std::mutex> lock(*GetMutex()); |
| 39 | SetMacroAbortWait(false); |
| 40 | |
| 41 | // The media source needs time to open and decode before reaching |
| 42 | // PLAYING state. Poll until it starts (or the macro is stopped). |
| 43 | while (!MacroWaitShouldAbort() && !MacroIsStopped(macro)) { |
| 44 | if (obs_source_media_get_state(source) == |
| 45 | OBS_MEDIA_STATE_PLAYING) { |
| 46 | break; |
| 47 | } |
| 48 | GetMacroWaitCV().wait_for(lock, 10ms); |
| 49 | } |
| 50 | |
| 51 | // Now wait for playback to end. Require two consecutive non-playing |
| 52 | // samples to avoid false positives on brief state transitions. |
| 53 | // If maxMs > 0, also stop once that many milliseconds have elapsed. |
| 54 | const auto playbackStart = std::chrono::steady_clock::now(); |
| 55 | static const int kStopThreshold = 2; |
| 56 | int stoppedCount = 0; |
| 57 | while (!MacroWaitShouldAbort() && !MacroIsStopped(macro)) { |
| 58 | if (maxMs > 0) { |
| 59 | const auto elapsed = |
| 60 | std::chrono::duration_cast< |
| 61 | std::chrono::milliseconds>( |
| 62 | std::chrono::steady_clock::now() - |
| 63 | playbackStart) |
| 64 | .count(); |
| 65 | if (elapsed >= maxMs) { |
| 66 | obs_source_media_stop(source); |
| 67 | break; |
| 68 | } |
| 69 | } |
| 70 | if (obs_source_media_get_state(source) != |
| 71 | OBS_MEDIA_STATE_PLAYING) { |
| 72 | if (++stoppedCount >= kStopThreshold) { |
| 73 | break; |
| 74 | } |
| 75 | } else { |
| 76 | stoppedCount = 0; |
| 77 | } |
| 78 | GetMacroWaitCV().wait_for(lock, 10ms); |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | bool MacroActionPlayAudio::PerformAction() |
| 83 | { |
no test coverage detected