2 Copyright © 2015-2016, The AROS Development Team. All rights reserved.
9 #include <aros/debug.h>
11 #include <clib/alib_protos.h>
12 #include <proto/exec.h>
13 #include <proto/dos.h>
14 #include <proto/intuition.h>
15 #include <proto/utility.h>
16 #include <proto/realtime.h>
18 #include <intuition/gadgetclass.h>
19 #include <libraries/realtime.h>
20 #include <gadgets/tapedeck.h>
22 #include "animationclass.h"
24 void FreeBufferSignals(struct ProcessPrivate
*priv
)
26 D(bug("[animation.datatype/BUFFER]: %s()\n", __func__
);)
28 if (priv
->pp_BufferFill
!= -1)
29 FreeSignal(priv
->pp_BufferFill
);
30 if (priv
->pp_BufferPurge
!= -1)
31 FreeSignal(priv
->pp_BufferPurge
);
32 if (priv
->pp_BufferEnable
!= -1)
33 FreeSignal(priv
->pp_BufferEnable
);
34 if (priv
->pp_BufferDisable
!= -1)
35 FreeSignal(priv
->pp_BufferDisable
);
38 BOOL
AllocBufferSignals(struct ProcessPrivate
*priv
)
40 D(bug("[animation.datatype/BUFFER]: %s()\n", __func__
);)
42 if ((priv
->pp_BufferEnable
= AllocSignal(-1)) != -1)
44 D(bug("[animation.datatype/BUFFER]: %s: allocated enable signal (%x)\n", __func__
, priv
->pp_BufferEnable
);)
45 if ((priv
->pp_BufferDisable
= AllocSignal(-1)) != -1)
47 D(bug("[animation.datatype/BUFFER]: %s: allocated disable signal (%x)\n", __func__
, priv
->pp_BufferDisable
);)
48 if ((priv
->pp_BufferFill
= AllocSignal(-1)) != -1)
50 D(bug("[animation.datatype/BUFFER]: %s: allocated fill signal (%x)\n", __func__
, priv
->pp_BufferFill
);)
51 if ((priv
->pp_BufferPurge
= AllocSignal(-1)) != -1)
53 D(bug("[animation.datatype/BUFFER]: %s: allocated purge signal (%x)\n", __func__
, priv
->pp_BufferPurge
);)
55 priv
->pp_BufferSigMask
= (1 << priv
->pp_BufferEnable
) | (1 << priv
->pp_BufferDisable
) | (1 << priv
->pp_BufferFill
) | (1 << priv
->pp_BufferPurge
);
57 D(bug("[animation.datatype/BUFFER]: %s: signal mask (%x)\n", __func__
, priv
->pp_BufferSigMask
);)
67 struct AnimFrame
*NextToBuffer(struct ProcessPrivate
*priv
, struct AnimFrame
*newFrame
)
69 struct AnimFrame
*startFrame
, *prevFrame
;
72 DFRAMES("[animation.datatype/BUFFER]: %s()\n", __PRETTY_FUNCTION__
)
74 ObtainSemaphoreShared(&priv
->pp_Data
->ad_FrameData
.afd_AnimFramesLock
);
76 if ((startFrame
= priv
->pp_BufferFirst
) == NULL
)
77 prevFrame
= (struct AnimFrame
*)&priv
->pp_Data
->ad_FrameData
.afd_AnimFrames
;
79 prevFrame
= startFrame
;
82 while ((prevFrame
->af_Node
.ln_Succ
) && (prevFrame
->af_Node
.ln_Succ
->ln_Succ
) &&
83 ((prevFrame
== (struct AnimFrame
*)&priv
->pp_Data
->ad_FrameData
.afd_AnimFrames
) ||
84 (NODEID(prevFrame
->af_Node
.ln_Succ
) == (NODEID(prevFrame
) + 1))))
86 prevFrame
= (struct AnimFrame
*)prevFrame
->af_Node
.ln_Succ
;
89 if (NODEID(prevFrame
) == (priv
->pp_Data
->ad_FrameData
.afd_Frames
- 1))
91 prevFrame
= (struct AnimFrame
*)&priv
->pp_Data
->ad_FrameData
.afd_AnimFrames
;
99 if (prevFrame
!= (struct AnimFrame
*)&priv
->pp_Data
->ad_FrameData
.afd_AnimFrames
)
101 startFrame
= prevFrame
;
102 newFrame
->af_Frame
.alf_Frame
= NODEID(prevFrame
) + 1;
105 newFrame
->af_Frame
.alf_Frame
= 0;
107 NODEID(newFrame
) = (UWORD
) newFrame
->af_Frame
.alf_Frame
;
108 newFrame
->af_Frame
.alf_TimeStamp
= newFrame
->af_Frame
.alf_Frame
;
109 priv
->pp_BufferFirst
= startFrame
;
111 ReleaseSemaphore(&priv
->pp_Data
->ad_FrameData
.afd_AnimFramesLock
);
116 BOOL
DoFramePurge(struct Animation_Data
*animd
, struct AnimFrame
*purgeFrame
)
118 UWORD dispplayedframe
= animd
->ad_FrameData
.afd_FrameCurrent
;
120 if ((purgeFrame
->af_Frame
.alf_BitMap
!= animd
->ad_FrameBM
) &&
121 (purgeFrame
!= animd
->ad_ProcessData
->pp_PlaybackFrame
) &&
122 (purgeFrame
!= animd
->ad_ProcessData
->pp_BufferFirst
) &&
123 (NODEID(purgeFrame
) != dispplayedframe
) &&
124 (NODEID(purgeFrame
) != 0))
126 if ((NODEID(purgeFrame
) > (dispplayedframe
+ animd
->ad_ProcessData
->pp_BufferFrames
)) ||
127 (NODEID(purgeFrame
) < dispplayedframe
))
129 if ((dispplayedframe
> (animd
->ad_FrameData
.afd_Frames
- animd
->ad_ProcessData
->pp_BufferFrames
)) &&
130 (NODEID(purgeFrame
) < (animd
->ad_ProcessData
->pp_BufferFrames
- (animd
->ad_FrameData
.afd_Frames
- dispplayedframe
))))
141 Process to handle loading/discarding (buffering) of animation frames
142 realtime.library player & playback thread will signal us when needed.
145 AROS_UFH3(void, bufferProc
,
146 AROS_UFHA(STRPTR
, argPtr
, A0
),
147 AROS_UFHA(ULONG
, argSize
, D0
),
148 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
152 struct Task
*thisTask
= FindTask(NULL
);
153 struct ProcessPrivate
*priv
= thisTask
->tc_UserData
;
154 struct AnimFrame
*curFrame
= NULL
, *startFrame
;
155 ULONG signal
, bufferstep
;
157 D(bug("[animation.datatype/BUFFER]: %s()\n", __func__
);)
162 bug("[animation.datatype/BUFFER] %s: private data @ 0x%p\n", __func__
, priv
);
163 bug("[animation.datatype/BUFFER] %s: dt obj @ 0x%p, instance data @ 0x%p\n", __func__
, priv
->pp_Object
, priv
->pp_Data
);
166 priv
->pp_BufferFirst
= NULL
;
167 priv
->pp_BufferSpecific
= -1;
168 priv
->pp_BufferLevel
= 0;
169 priv
->pp_BufferFlags
|= PRIVPROCF_RUNNING
;
171 if (AllocBufferSignals(priv
))
173 D(bug("[animation.datatype/BUFFER]: %s: entering main loop ...\n", __func__
);)
175 bufferstep
= priv
->pp_Data
->ad_BufferStep
;
179 priv
->pp_BufferFlags
&= ~PRIVPROCF_ACTIVE
;
181 if ((priv
->pp_BufferFlags
& PRIVPROCF_ENABLED
) &&
182 ((bufferstep
>= 1) || (priv
->pp_BufferLevel
< priv
->pp_BufferFrames
)) &&
183 (priv
->pp_BufferLevel
< priv
->pp_Data
->ad_FrameData
.afd_Frames
))
185 D(bug("[animation.datatype/BUFFER]: %s: %d:%d\n", __func__
, priv
->pp_BufferLevel
, priv
->pp_BufferFrames
);)
186 signal
= (1 << priv
->pp_BufferFill
);
190 bufferstep
= priv
->pp_Data
->ad_BufferStep
;
191 D(bug("[animation.datatype/BUFFER]: %s: waiting ...\n", __func__
);)
192 signal
= Wait(priv
->pp_BufferSigMask
| SIGBREAKF_CTRL_C
);
195 D(bug("[animation.datatype/BUFFER]: %s: signalled (%08x)\n", __func__
, signal
);)
197 if (signal
& SIGBREAKF_CTRL_C
)
200 if (signal
& (1 << priv
->pp_BufferEnable
))
201 priv
->pp_BufferFlags
|= PRIVPROCF_ENABLED
;
202 else if (signal
& (1 << priv
->pp_BufferDisable
))
203 priv
->pp_BufferFlags
&= ~PRIVPROCF_ENABLED
;
205 if ((priv
->pp_BufferFlags
& PRIVPROCF_ENABLED
) &&
206 (signal
& (1 <<priv
->pp_BufferPurge
)) &&
207 (priv
->pp_BufferFrames
< priv
->pp_Data
->ad_FrameData
.afd_Frames
))
209 struct AnimFrame
*purgeFrame
= NULL
, *tmpFrame
= NULL
;
211 D(bug("[animation.datatype/BUFFER]: %s: Purging Frames...\n", __func__
);)
212 if (AttemptSemaphore(&priv
->pp_Data
->ad_FrameData
.afd_AnimFramesLock
))
214 D(bug("[animation.datatype/BUFFER]: %s: locked frame list...\n", __func__
);)
215 ForeachNodeSafe(&priv
->pp_Data
->ad_FrameData
.afd_AnimFrames
, purgeFrame
, tmpFrame
)
217 if (DoFramePurge(priv
->pp_Data
, (struct AnimFrame
*)purgeFrame
))
219 D(bug("[animation.datatype/BUFFER]: %s: unloading frame #%d\n", __func__
, NODEID(purgeFrame
));)
221 freeFrame(priv
->pp_Data
, purgeFrame
);
223 purgeFrame
->af_Frame
.MethodID
= ADTM_UNLOADFRAME
;
224 DoMethodA(priv
->pp_Object
, (Msg
)&purgeFrame
->af_Frame
);
226 D(bug("[animation.datatype/BUFFER]: %s: freeing frame @0x%p\n", __func__
, purgeFrame
);)
227 Remove(&purgeFrame
->af_Node
);
228 FreeMem(purgeFrame
, sizeof(struct AnimFrame
));
230 priv
->pp_BufferLevel
--;
233 ReleaseSemaphore(&priv
->pp_Data
->ad_FrameData
.afd_AnimFramesLock
);
237 if ((priv
->pp_BufferFlags
& PRIVPROCF_ENABLED
) &&
238 (signal
& (1 <<priv
->pp_BufferFill
)))
240 D(bug("[animation.datatype/BUFFER]: %s: Loading Frames...\n", __func__
);)
242 priv
->pp_BufferFlags
|= PRIVPROCF_ACTIVE
;
244 if ((priv
->pp_BufferFrames
> priv
->pp_BufferLevel
) &&
245 (priv
->pp_BufferLevel
< priv
->pp_Data
->ad_FrameData
.afd_Frames
))
248 ((curFrame
= AllocMem(sizeof(struct AnimFrame
), MEMF_ANY
|MEMF_CLEAR
)) != NULL
))
250 curFrame
->af_Frame
.MethodID
= ADTM_LOADFRAME
;
252 if (!(priv
->pp_BufferFirst
) && (priv
->pp_BufferSpecific
!= -1))
254 curFrame
->af_Frame
.alf_Frame
= priv
->pp_BufferSpecific
;
255 priv
->pp_BufferSpecific
= -1;
257 ObtainSemaphore(&priv
->pp_Data
->ad_FrameData
.afd_AnimFramesLock
);
258 startFrame
= (struct AnimFrame
*)&priv
->pp_Data
->ad_FrameData
.afd_AnimFrames
;
259 while ((startFrame
->af_Node
.ln_Succ
) &&
260 (startFrame
->af_Node
.ln_Succ
->ln_Succ
) &&
261 (NODEID(startFrame
->af_Node
.ln_Succ
) < priv
->pp_BufferSpecific
))
263 startFrame
= (struct AnimFrame
*)startFrame
->af_Node
.ln_Succ
;
266 if (startFrame
== (struct AnimFrame
*)&priv
->pp_Data
->ad_FrameData
.afd_AnimFrames
)
268 priv
->pp_BufferFirst
= startFrame
;
269 ReleaseSemaphore(&priv
->pp_Data
->ad_FrameData
.afd_AnimFramesLock
);
271 NODEID(curFrame
) = (UWORD
) curFrame
->af_Frame
.alf_Frame
;
272 curFrame
->af_Frame
.alf_TimeStamp
= curFrame
->af_Frame
.alf_Frame
;
276 startFrame
= NextToBuffer(priv
, curFrame
);
280 bug("[animation.datatype/BUFFER]: %s: Loading Frame #%d (AnimFrame @ 0x%p)\n", __func__
, curFrame
->af_Frame
.alf_Frame
, curFrame
);
281 bug("[animation.datatype/BUFFER]: %s: startFrame @ 0x%p\n", __func__
, startFrame
);
284 if (DoMethodA(priv
->pp_Object
, (Msg
)&curFrame
->af_Frame
))
286 priv
->pp_BufferLevel
++;
288 bug("[animation.datatype/BUFFER]: %s: Loaded! bitmap @ %p\n", __func__
, curFrame
->af_Frame
.alf_BitMap
);
289 bug("[animation.datatype/BUFFER]: %s: frame #%d. stamp %d\n", __func__
, curFrame
->af_Frame
.alf_Frame
, curFrame
->af_Frame
.alf_TimeStamp
);
290 bug("[animation.datatype/BUFFER]: %s: bitmap @ %p\n", __func__
, curFrame
->af_Frame
.alf_BitMap
);
293 ObtainSemaphore(&priv
->pp_Data
->ad_FrameData
.afd_AnimFramesLock
);
294 Insert(&priv
->pp_Data
->ad_FrameData
.afd_AnimFrames
, &curFrame
->af_Node
, &startFrame
->af_Node
);
295 if (startFrame
== priv
->pp_BufferFirst
)
297 if (NODEID(curFrame
) < (priv
->pp_Data
->ad_FrameData
.afd_Frames
- 1))
299 priv
->pp_BufferFirst
= curFrame
;
300 while ((priv
->pp_BufferFirst
->af_Node
.ln_Succ
) &&
301 (priv
->pp_BufferFirst
->af_Node
.ln_Succ
->ln_Succ
) &&
302 (NODEID(priv
->pp_BufferFirst
->af_Node
.ln_Succ
) == (NODEID(priv
->pp_BufferFirst
) + 1)))
304 priv
->pp_BufferFirst
= (struct AnimFrame
*)priv
->pp_BufferFirst
->af_Node
.ln_Succ
;
307 if ((priv
->pp_BufferFirst
) &&
308 (NODEID(priv
->pp_BufferFirst
) == (priv
->pp_Data
->ad_FrameData
.afd_Frames
- 1)))
309 priv
->pp_BufferFirst
= NULL
;
311 ReleaseSemaphore(&priv
->pp_Data
->ad_FrameData
.afd_AnimFramesLock
);
313 cacheFrame(priv
->pp_Data
, curFrame
);
319 curFrame
->af_Frame
.MethodID
= ADTM_UNLOADFRAME
;
320 DoMethodA(priv
->pp_Object
, (Msg
)&curFrame
->af_Frame
);
328 SetTaskPri((struct Task
*)priv
->pp_Data
->ad_PlayerProc
, 0);
331 FreeBufferSignals(priv
);
333 priv
->pp_BufferFlags
&= ~PRIVPROCF_RUNNING
;
334 priv
->pp_Data
->ad_BufferProc
= NULL
;
336 D(bug("[animation.datatype/BUFFER]: %s: exiting ...\n", __func__
);)