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 frameOn) {
11 // Make sure the video thread can process events while the GBA thread is paused
12 MutexLock(&sync->videoFrameMutex);
13 if (frameOn != sync->videoFrameOn) {
14 sync->videoFrameOn = frameOn;
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 ConditionWake(&sync->videoFrameRequiredCond);
53 if (!sync->videoFrameOn && !sync->videoFramePending) {
54 return false;
55 }
56 if (sync->videoFrameOn) {
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 MutexUnlock(&sync->videoFrameMutex);
71}
72
73void mCoreSyncSetVideoSync(struct mCoreSync* sync, bool wait) {
74 if (!sync) {
75 return;
76 }
77
78 _changeVideoSync(sync, wait);
79}
80
81bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t* buf, size_t samples) {
82 if (!sync) {
83 return true;
84 }
85
86 size_t produced = blip_samples_avail(buf);
87 size_t producedNew = produced;
88 while (sync->audioWait && producedNew >= samples) {
89 ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex);
90 produced = producedNew;
91 producedNew = blip_samples_avail(buf);
92 }
93 MutexUnlock(&sync->audioBufferMutex);
94 return producedNew != produced;
95}
96
97void mCoreSyncLockAudio(struct mCoreSync* sync) {
98 if (!sync) {
99 return;
100 }
101
102 MutexLock(&sync->audioBufferMutex);
103}
104
105void mCoreSyncUnlockAudio(struct mCoreSync* sync) {
106 if (!sync) {
107 return;
108 }
109
110 MutexUnlock(&sync->audioBufferMutex);
111}
112
113void mCoreSyncConsumeAudio(struct mCoreSync* sync) {
114 if (!sync) {
115 return;
116 }
117
118 ConditionWake(&sync->audioRequiredCond);
119 MutexUnlock(&sync->audioBufferMutex);
120}