Skip to content

Commit aea46e0

Browse files
committed
Add "time" to cancel()
1 parent 524e3e6 commit aea46e0

3 files changed

Lines changed: 39 additions & 27 deletions

File tree

src/rtmixer.c

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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)

src/rtmixer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct action
2222
PaUtilRingBuffer* const ringbuffer;
2323
struct action* action; // Used in CANCEL
2424
};
25-
const frame_t total_frames;
25+
frame_t total_frames;
2626
frame_t done_frames;
2727
// TODO: something to store the result of the action?
2828
// TODO: number of xruns during the runtime of the current action?

src/rtmixer.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def actions(self):
3535
self._drain_result_q()
3636
return self._actions
3737

38-
def cancel(self, action):
38+
def cancel(self, action, time=0, allow_belated=True):
3939
"""Initiate stopping a running action.
4040
4141
This creates another action that is sent to the callback in
@@ -47,6 +47,8 @@ def cancel(self, action):
4747
"""
4848
cancel_action = _ffi.new('struct action*', dict(
4949
type=_lib.CANCEL,
50+
allow_belated=allow_belated,
51+
requested_time=time,
5052
action=action,
5153
))
5254
self._enqueue(cancel_action)

0 commit comments

Comments
 (0)