blob: 24513994d5e9293971b4e8f31f2c99c0091800dd [file] [log] [blame]
Sylvain Munaut3c0a4fb2010-11-11 20:40:29 +01001/* Processing Queue Management */
2
3/*
4 * This file is part of gapk (GSM Audio Pocket Knife).
5 *
6 * gapk is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * gapk is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with gapk. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <errno.h>
21#include <stdint.h>
22#include <stdlib.h>
23
24#include <gapk/procqueue.h>
25
26
27#define MAX_PQ_ITEMS 8
28
29struct pq {
30 int n_items;
31 struct pq_item* items[MAX_PQ_ITEMS];
32 void * buffers[MAX_PQ_ITEMS+1];
33};
34
35
Harald Weltef3d2ad62017-05-27 16:42:14 +020036/* crate a new (empty) processing queue */
Sylvain Munaut3c0a4fb2010-11-11 20:40:29 +010037struct pq *
38pq_create(void)
39{
40 return (struct pq *) calloc(1, sizeof(struct pq));
41}
42
Harald Weltef3d2ad62017-05-27 16:42:14 +020043/*! destroy a processing queue, calls exit() callback of each item
44 * \param[in] pq Processing Queue to be destroyed */
Sylvain Munaut3c0a4fb2010-11-11 20:40:29 +010045void
46pq_destroy(struct pq *pq)
47{
48 int i;
49
50 if (!pq)
51 return;
52
53 for (i=0; i<pq->n_items; i++) {
54 if (!pq->items[i])
55 continue;
56 if (pq->items[i]->exit)
57 pq->items[i]->exit(pq->items[i]->state);
58 free(pq->items[i]);
59 }
60
61 for (i=0; i<pq->n_items-1; i++)
62 free(pq->buffers[i]); /* free is NULL safe */
63
64 free(pq);
65}
66
Harald Weltef3d2ad62017-05-27 16:42:14 +020067/*! allocate + add an item to a processing queue; return new item
68 * \param[in] pq Processing Queue to which item is added
69 * \returns new PQ item; NULL on error */
Sylvain Munaut3c0a4fb2010-11-11 20:40:29 +010070struct pq_item *
71pq_add_item(struct pq *pq)
72{
73 struct pq_item *item;
74
75 if (pq->n_items == MAX_PQ_ITEMS)
76 return NULL;
77
78 item = calloc(1, sizeof(struct pq_item));
79 if (!item)
80 return NULL;
81
82 pq->items[pq->n_items++] = item;
83
84 return item;
85}
86
Harald Weltef3d2ad62017-05-27 16:42:14 +020087/*! prepare a processing queue; allocates buffers; checks lengths
88 * \param[in] pq Processing Queue to be prepared
89 * \returns 0 on succcess; negative on error */
Sylvain Munaut3c0a4fb2010-11-11 20:40:29 +010090int
91pq_prepare(struct pq *pq)
92{
93 int i;
94 unsigned int len_prev;
95
96 len_prev = 0;
97
98 for (i=0; i<pq->n_items; i++) {
99 struct pq_item *item = pq->items[i];
100
101 if (item->len_in != len_prev)
102 return -EINVAL;
103
104 if (i < (pq->n_items-1)) {
105 pq->buffers[i] = malloc(item->len_out);
106 if (!pq->buffers[i])
107 return -ENOMEM;
108 } else{
109 if (item->len_out)
110 return -EINVAL;
111 }
112
113 len_prev = item->len_out;
114 }
115
116 return 0;
117}
118
Harald Weltef3d2ad62017-05-27 16:42:14 +0200119/*! execute a processing queue; iterate over processing elements
120 * \param[in] pq Processing Queue to be executed
121 * \returns 0 on success; negative on error (if any item returns negative) */
Sylvain Munaut3c0a4fb2010-11-11 20:40:29 +0100122int
123pq_execute(struct pq *pq)
124{
125 int i;
126 void *buf_prev, *buf;
127
128 buf_prev = NULL;
129
130 for (i=0; i<pq->n_items; i++) {
131 int rv;
132 struct pq_item *item = pq->items[i];
133
134 buf = i < (pq->n_items-1) ? pq->buffers[i] : NULL;
135
136 rv = item->proc(item->state, buf, buf_prev);
137 if (rv)
138 return rv;
139
140 buf_prev = buf;
141 }
142
143 return 0;
144}