]>
code.delx.au - pulseaudio/blob - src/sink.c
951191dd48bf660949878adbf06f7402d44e4644
9 #define MAX_MIX_CHANNELS 32
11 struct sink
* sink_new(struct core
*core
, const char *name
, const struct sample_spec
*spec
) {
17 s
= malloc(sizeof(struct sink
));
20 s
->name
= name
? strdup(name
) : NULL
;
22 s
->sample_spec
= *spec
;
23 s
->inputs
= idxset_new(NULL
, NULL
);
26 n
= malloc(strlen(name
)+9);
27 sprintf(n
, "%s_monitor", name
);
30 s
->monitor_source
= source_new(core
, n
, spec
);
38 r
= idxset_put(core
->sinks
, s
, &s
->index
);
39 assert(s
->index
!= IDXSET_INVALID
&& r
>= 0);
41 fprintf(stderr
, "sink: created %u \"%s\".\n", s
->index
, s
->name
);
46 void sink_free(struct sink
*s
) {
47 struct sink_input
*i
, *j
= NULL
;
50 while ((i
= idxset_first(s
->inputs
, NULL
))) {
55 idxset_free(s
->inputs
, NULL
, NULL
);
57 source_free(s
->monitor_source
);
58 idxset_remove_by_data(s
->core
->sinks
, s
, NULL
);
60 fprintf(stderr
, "sink: freed %u \"%s\"\n", s
->index
, s
->name
);
66 void sink_notify(struct sink
*s
) {
73 static unsigned fill_mix_info(struct sink
*s
, struct mix_info
*info
, unsigned maxinfo
) {
74 uint32_t index
= IDXSET_INVALID
;
80 for (i
= idxset_first(s
->inputs
, &index
); maxinfo
> 0 && i
; i
= idxset_next(s
->inputs
, &index
)) {
82 if (i
->peek(i
, &info
->chunk
, &info
->volume
) < 0)
85 assert(info
->chunk
.memblock
&& info
->chunk
.memblock
->data
&& info
->chunk
.length
);
96 static void inputs_drop(struct sink
*s
, struct mix_info
*info
, unsigned maxinfo
, size_t length
) {
99 for (; maxinfo
> 0; maxinfo
--, info
++) {
100 struct sink_input
*i
= info
->userdata
;
101 assert(i
&& info
->chunk
.memblock
);
103 memblock_unref(info
->chunk
.memblock
);
109 int sink_render(struct sink
*s
, size_t length
, struct memchunk
*result
) {
110 struct mix_info info
[MAX_MIX_CHANNELS
];
113 assert(s
&& length
&& result
);
115 n
= fill_mix_info(s
, info
, MAX_MIX_CHANNELS
);
121 struct sink_info
*i
= info
[0].userdata
;
123 *result
= info
[0].chunk
;
124 memblock_ref(result
->memblock
);
126 if (result
->length
> length
)
127 result
->length
= length
;
131 result
->memblock
= memblock_new(length
);
132 assert(result
->memblock
);
134 result
->length
= l
= mix_chunks(info
, n
, result
->memblock
->data
, length
, &s
->sample_spec
, s
->volume
);
140 inputs_drop(s
, info
, n
, l
);
144 int sink_render_into(struct sink
*s
, struct memblock
*target
, struct memchunk
*result
) {
145 struct mix_info info
[MAX_MIX_CHANNELS
];
148 assert(s
&& target
&& target
->length
&& target
->data
&& result
);
150 n
= fill_mix_info(s
, info
, MAX_MIX_CHANNELS
);
156 struct sink_info
*i
= info
[0].userdata
;
160 if (l
> info
[0].chunk
.length
)
161 l
= info
[0].chunk
.length
;
163 result
->memblock
= target
;
164 memcpy(target
->data
, info
[0].chunk
.memblock
->data
+ info
[0].chunk
.index
, l
);
165 result
->length
= target
->length
= l
;
169 result
->memblock
= target
;
170 result
->length
= l
= mix_chunks(info
, n
, target
->data
, target
->length
, &s
->sample_spec
, s
->volume
);
175 inputs_drop(s
, info
, n
, l
);