locale.library: correctly return the position of remaining datastream
[AROS.git] / workbench / libs / realtime / setconductorstate.c
blob481eb6db2909d072b09690ff186e844e4d56fcd8
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #include <proto/exec.h>
10 #include <proto/alib.h>
11 #include <proto/utility.h>
12 #include <proto/realtime.h>
13 #include <exec/lists.h>
14 #include "realtime_intern.h"
16 /*****************************************************************************
18 NAME */
19 #include <libraries/realtime.h>
21 AROS_LH3(LONG, SetConductorState,
23 /* SYNOPSIS */
25 AROS_LHA(struct Player *, player, A0),
26 AROS_LHA(ULONG , state , D0),
27 AROS_LHA(LONG , time , D1),
29 /* LOCATION */
31 struct Library *, RealTimeBase, 10, RealTime)
33 /* FUNCTION
35 Changes the state of the conductor connected to a specified player.
36 The possible states are
38 CONDSTATE_STOPPED
39 CONDSTATE_PAUSED
40 CONDSTATE_LOCATE
41 CONDSTATE_RUNNING
43 other possible "states" are
45 CONDSTATE_METRIC -- Ask the highest priority conducted node to do a
46 CONDSTATE_LOCATE
47 CONDSTATE_SHUTTLE -- Inform the players that the clock value is
48 changing without the clock running
51 INPUTS
53 player -- The player in question
54 state -- The new state of the conductor
55 time -- Start time offset in realtime.library units
57 RESULT
59 0 if OK, otherwise an error code. For now, these are RTE_PLAYING and
60 RTE_NOCONDUCTOR.
62 NOTES
64 Going from CONDSTATE_PAUSED to CONDSTATE_RUNNING does not reset the
65 cdt_ClockTime of the conductor.
67 EXAMPLE
69 BUGS
71 SEE ALSO
73 INTERNALS
75 HISTORY
77 27.7.1999 SDuvan implemented parts
78 27.1.2001 SDuvan implemented the rest
80 ******************************************************************************/
83 AROS_LIBFUNC_INIT
85 struct pmState stateMsg = { PM_STATE, 0 };
86 struct pmTime timeMsg = { 0 , time };
87 struct Player *pl; /* For use in ForeachNode() */
88 struct Conductor *conductor = player->pl_Source;
90 if (conductor == NULL)
92 return RTE_NOCONDUCTOR;
95 stateMsg.pms_OldState = conductor->cdt_State;
97 /* Don't report phony states */
98 if (state >= 0)
100 ForeachNode(&conductor->cdt_Players, pl)
102 /* Filter out QUIET players? */
103 if (pl->pl_Hook != NULL)
105 CallHookA(pl->pl_Hook, player, &stateMsg);
110 switch (state)
112 case CONDSTATE_PAUSED:
114 /* Pause the clock */
115 conductor->cdt_State = CONDSTATE_PAUSED;
116 conductor->cdt_Flags &= ~CONDUCTF_GOTTICK;
118 break;
120 case CONDSTATE_STOPPED:
122 /* Stop the clock */
123 conductor->cdt_State = CONDSTATE_STOPPED;
124 conductor->cdt_Flags &= ~CONDUCTF_GOTTICK;
126 break;
128 case CONDSTATE_LOCATE:
130 ULONG oldSignals;
132 conductor->cdt_State = CONDSTATE_LOCATE;
134 ObtainSemaphore(&conductor->cdt_Lock);
135 oldSignals = SetSignal(0, SIGF_SINGLE);
136 conductor->cdt_Barrier = FindTask(NULL);
137 ReleaseSemaphore(&conductor->cdt_Lock);
139 ForeachNode(&conductor->cdt_Players, pl)
141 BOOL isReady = FALSE;
143 /* Barrier synchronization */
144 while (!isReady)
146 struct TagItem tags[] = { { PLAYER_Ready, (IPTR)&isReady },
147 { TAG_DONE , (IPTR)NULL } };
149 GetPlayerAttrsA(pl, tags);
151 if (!isReady)
153 /* We are signalled by SetPlayerAttrs() if the tags
154 contain PLAYER_Ready '=' TRUE) */
155 Wait(SIGF_SINGLE);
160 ObtainSemaphore(&conductor->cdt_Lock);
161 conductor->cdt_Barrier = NULL;
162 SetSignal(oldSignals, SIGF_SINGLE);
163 ReleaseSemaphore(&conductor->cdt_Lock);
166 /* Send PM_STATE message with CONDSTATE_LOCATE_SET here? */
168 /* Fall through */
170 case CONDSTATE_RUNNING:
171 /* Start clock */
172 conductor->cdt_ClockTime = time;
173 conductor->cdt_State = CONDSTATE_RUNNING;
175 break;
177 case CONDSTATE_METRIC:
179 /* Get the highest priority musically aware player and let him
180 take care of the time location process. He will later call
181 SetConductorState() with state CONDSTATE_LOCATE to set the
182 time in realtime units calculated from his internal awareness
183 of time. */
184 struct Player *maestro = NULL;
186 ForeachNode(&conductor->cdt_Players,pl)
188 if (pl->pl_Flags & PLAYERF_CONDUCTED)
190 maestro = pl;
191 break;
195 if (maestro == NULL)
197 /* There is no defined error to return in this situation */
199 else
201 timeMsg.pmt_Method = PM_POSITION;
202 CallHookA(maestro->pl_Hook, player, &timeMsg);
205 break;
208 case CONDSTATE_SHUTTLE:
209 /* Shuttling not allowed when playing */
210 if (conductor->cdt_State == CONDSTATE_RUNNING)
212 return RTE_PLAYING;
215 conductor->cdt_StartTime = time;
217 timeMsg.pmt_Method = PM_SHUTTLE;
219 ForeachNode(&conductor->cdt_Players, pl)
221 if (pl->pl_Hook != NULL)
223 CallHookA(pl->pl_Hook, player, &timeMsg);
227 break;
230 return 0; /* Success */
232 AROS_LIBFUNC_EXIT
233 } /* SetConductorState */