@@ -55,29 +55,8 @@ int callback(const void* input, void* output, frame_t frameCount
5555 ; PaUtil_ReadRingBuffer (state -> action_q , & action , 1 )
5656 ;)
5757 {
58- // TODO: CANCEL with requested_time?
59-
60- if (action -> type == CANCEL )
61- {
62- CALLBACK_ASSERT (action -> action );
63-
64- struct action * * actionaddr = & (state -> actions );
65- while (* actionaddr )
66- {
67- if (* actionaddr == action -> action )
68- {
69- remove_action (actionaddr , state );
70- break ;
71- }
72- actionaddr = & ((* actionaddr )-> next );
73- }
74- // If the action wasn't in the list, we don't care
75-
76- remove_action (& action , state ); // Remove the CANCEL action itself
77- continue ;
78- }
79-
80- // Actions are added at the beginning of the list, because it's easier:
58+ // Actions are added at the beginning of the list, because CANCEL actions
59+ // must come before the action they are cancelling. Also, it's easier.
8160 action -> next = state -> actions ;
8261 state -> actions = action ;
8362 }
@@ -87,8 +66,13 @@ int callback(const void* input, void* output, frame_t frameCount
8766 {
8867 struct action * const action = * actionaddr ;
8968
90- const bool playing = action -> type == PLAY_BUFFER
91- || action -> type == PLAY_RINGBUFFER ;
69+ enum actiontype type = action -> type ;
70+ if (type == CANCEL )
71+ {
72+ CALLBACK_ASSERT (action -> action );
73+ type = action -> action -> type ;
74+ }
75+ const bool playing = type == PLAY_BUFFER || type == PLAY_RINGBUFFER ;
9276
9377 PaTime io_time = playing ? timeInfo -> outputBufferDacTime
9478 : timeInfo -> inputBufferAdcTime ;
@@ -126,6 +110,32 @@ int callback(const void* input, void* output, frame_t frameCount
126110 }
127111 }
128112
113+ if (action -> type == CANCEL )
114+ {
115+ for (struct action * * i = & (action -> next ); * i ; i = & ((* i )-> next ))
116+ {
117+ if (* i == action -> action )
118+ {
119+ struct action * delinquent = * i ;
120+
121+ if (delinquent -> done_frames + offset > delinquent -> total_frames )
122+ {
123+ // TODO: stops on its own ... set some error state?
124+ }
125+ else
126+ {
127+ delinquent -> total_frames = delinquent -> done_frames + offset ;
128+ }
129+ // TODO: save some informations to action->...?
130+ break ;
131+ }
132+ }
133+ // TODO: what if the action to cancel wasn't found? set actual_time = 0.0?
134+
135+ remove_action (actionaddr , state ); // Remove the CANCEL action itself
136+ continue ;
137+ }
138+
129139 frame_t frames = action -> total_frames - action -> done_frames ;
130140
131141 if (frameCount < frames )
0 commit comments