src/core/sync.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba/core/sync.h>
7
8#include <mgba/core/blip_buf.h>
9
10static void _changeVideoSync(struct mCoreSync* sync, bool wait) {
11 // Make sure the video thread can process events while the GBA thread is paused
12 MutexLock(&sync->videoFrameMutex);
13 if (wait != sync->videoFrameWait) {
14 sync->videoFrameWait = wait;
15 ConditionWake(&sync->videoFrameAvailableCond);
16 }
17 MutexUnlock(&sync->videoFrameMutex);
18}
19
20void mCoreSyncPostFrame(struct mCoreSync* sync) {
21 if (!sync) {
22 return;
23 }
24
25 MutexLock(&sync->videoFrameMutex);
26 ++sync->videoFramePending;
27 do {
28 ConditionWake(&sync->videoFrameAvailableCond);
29 if (sync->videoFrameWait) {
30 ConditionWait(&sync->videoFrameRequiredCond, &sync->videoFrameMutex);
31 }
32 } while (sync->videoFrameWait && sync->videoFramePending);
33 MutexUnlock(&sync->videoFrameMutex);
34}
35
36void mCoreSyncForceFrame(struct mCoreSync* sync) {
37 if (!sync) {
38 return;
39 }
40
41 MutexLock(&sync->videoFrameMutex);
42 ConditionWake(&sync->videoFrameAvailableCond);
43 MutexUnlock(&sync->videoFrameMutex);
44}
45
46bool mCoreSyncWaitFrameStart(struct mCoreSync* sync) {
47 if (!sync) {
48 return true;
49 }
50
51 MutexLock(&sync->videoFrameMutex);
52 if (!sync->videoFrameWait && !sync->videoFramePending) {
53 return false;
54 }
55 if (sync->videoFrameWait) {
56 ConditionWake(&sync->videoFrameRequiredCond);
57 if (ConditionWaitTimed(&sync->videoFrameAvailableCond, &sync->videoFrameMutex, 50)) {
58 return false;
59 }
60 }
61 sync->videoFramePending = 0;
62 return true;
63}
64
65void mCoreSyncWaitFrameEnd(struct mCoreSync* sync) {
66 if (!sync) {
67 return;
68 }
69
70 ConditionWake(&sync->videoFrameRequiredCond);
71 MutexUnlock(&sync->videoFrameMutex);
72}
73
74void mCoreSyncSetVideoSync(struct mCoreSync* sync, bool wait) {
75 if (!sync) {
76 return;
77 }
78
79 _changeVideoSync(sync, wait);
80}
81
82bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t* buf, size_t samples) {
83 if (!sync) {
84 return true;
85 }
86
87 size_t produced = blip_samples_avail(buf);
88 size_t producedNew = produced;
89 while (sync->audioWait && producedNew >= samples) {
90 ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex);
91 produced = producedNew;
92 producedNew = blip_samples_avail(buf);
93 }
94 MutexUnlock(&sync->audioBufferMutex);
95 return producedNew != produced;
96}
97
98void mCoreSyncLockAudio(struct mCoreSync* sync) {
99 if (!sync) {
100 return;
101 }
102
103 MutexLock(&sync->audioBufferMutex);
104}
105
106void mCoreSyncUnlockAudio(struct mCoreSync* sync) {
107 if (!sync) {
108 return;
109 }
110
111 MutexUnlock(&sync->audioBufferMutex);
112}
113
114void mCoreSyncConsumeAudio(struct mCoreSync* sync) {
115 if (!sync) {
116 return;
117 }
118
119 ConditionWake(&sync->audioRequiredCond);
120 MutexUnlock(&sync->audioBufferMutex);
121}