source: roaraudio/plugins/universal/filter-slfi-map.c @ 6004:9178df7c3076

Last change on this file since 6004:9178df7c3076 was 6004:9178df7c3076, checked in by phi, 10 years ago

added filter map

File size: 6.6 KB
Line 
1//filter-slfi-map.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012-2014
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include <roaraudio.h>
27#include <libroarlight/libroarlight.h>
28
29#define MAX_EVENTS 8
30#define MAX_MAPS   16
31
32enum slfi_maptype {
33 // copy=start-end:dest
34 MT_COPY,
35 // swap=start:dest
36 MT_SWAP,
37 // inverse=start
38 MT_INVERSE
39};
40
41struct slfi_map {
42 enum slfi_maptype mt;
43 ssize_t src_start;
44 ssize_t src_end;
45 ssize_t dst_start;
46};
47
48struct slfi_mapinst {
49 uint8_t event[MAX_EVENTS][2];
50 size_t event_len;
51 struct slfi_map map[MAX_MAPS];
52 size_t map_len;
53};
54
55static struct slfi_map __parse_map(const char * type, const char * str) {
56 struct slfi_map map = {MT_COPY, -1, -1, -1};
57 char * buf = roar_mm_strdup(str);
58 char * value;
59 char * end;
60
61 if ( buf == NULL ) {
62  ROAR_ERR("__parse_map(*): Can not allocate memory. Bad.");
63  return map;
64 }
65
66 if ( !strcmp(type, "copy") || !strcmp(type, "move") || !strcmp(type, "mov") ) {
67  map.mt = MT_COPY;
68 } else if ( !strcmp(type, "swap") ) {
69  map.mt = MT_SWAP;
70 } else if ( !strcmp(type, "inverse") || !strcmp(type, "inv") ) {
71  map.mt = MT_INVERSE;
72 } else {
73  ROAR_ERR("__parse_map(*): Unknown map type: %s", type);
74  return map;
75 }
76
77 value = strstr(buf, ":");
78 if ( value != NULL ) {
79  *value = 0;
80  value++;
81  map.dst_start = atoi(value);
82  if ( map.dst_start < 0 )
83   map.dst_start = 0;
84 }
85
86 end = strstr(buf, "-");
87 if ( end != NULL ) {
88  *end = 0;
89  end++;
90 }
91
92 map.src_start = atoi(buf);
93 if ( map.src_start < 0 )
94  map.src_start = 0;
95
96 if ( end != NULL ) {
97  map.src_end = atoi(end);
98  if ( map.src_end < map.src_start )
99   map.src_end = map.src_start;
100 }
101
102 roar_mm_free(buf);
103
104 if ( map.mt == MT_COPY && map.src_end == -1 )
105  map.src_end = map.src_start;
106
107 if ( map.mt != MT_INVERSE && map.dst_start == -1 ) {
108  ROAR_ERR("__parse_map(*): Bad mapping: no destination channel(s) given.");
109  map.src_start = -1;
110  return map;
111 }
112
113 return map;
114}
115
116static int __init(struct roar_slfi_inst * inst, const struct roar_keyval * para, ssize_t paralen) {
117 struct slfi_mapinst * self = roar_mm_malloc(sizeof(struct slfi_mapinst));
118 const struct roar_keyval * kv;
119 ssize_t i;
120
121 if ( self == NULL )
122  return -1;
123
124 memset(self, 0, sizeof(*self));
125 inst->userdata = self;
126
127 for (i = 0; i < paralen; i++) {
128  kv = &(para[i]);
129  if ( kv->key == NULL || kv->value == NULL )
130   continue;
131
132  if ( !strcmp(kv->key, "event") ) {
133   ROAR_WARN("__init(*): Can not add event: Not Supported");
134/*
135   if ( self->event_len == MAX_EVENTS ) {
136    ROAR_WARN("__init(*): Can not add (list is full) event: %s", kv->value);
137    continue;
138   }
139   self->event[self->event_len++] = roar_roardmx_str2event(kv->value);
140*/
141  } else if ( !strcmp(kv->key, "copy") || !strcmp(kv->key, "move") || !strcmp(kv->key, "mov") ||
142              !strcmp(kv->key, "swap") ||
143              !strcmp(kv->key, "inverse") || !strcmp(kv->key, "inv") ) {
144   if ( self->map_len == MAX_MAPS ) {
145    ROAR_WARN("__init(*): Can not add (list is full) map: %s=%s", kv->key, kv->value);
146    continue;
147   }
148   self->map[self->map_len++] = __parse_map(kv->key, kv->value);
149  } else {
150   ROAR_WARN("__init(*): Unknown parameter: %s", kv->key);
151  }
152 }
153
154 return 0;
155}
156
157static int __update(struct roar_slfi_inst * inst, uint8_t * universe, ssize_t size_of_universe, int32_t usecspassed, const uint8_t * event, size_t eventlen) {
158 struct slfi_mapinst * self = inst->userdata;
159 const struct slfi_map * map;
160 size_t i;
161 ssize_t j;
162 uint8_t tmp;
163
164 (void)inst, (void)usecspassed, (void)event, (void)eventlen;
165
166 for (i = 0; i < self->event_len; i++) {
167  for (j = 0; j < (ssize_t)eventlen; j++) {
168   if ( self->event[i][0] == event[j] ) {
169    roar_slfi_event_add(inst, self->event[i][1]);
170   }
171  }
172 }
173
174 for (i = 0; i < self->map_len; i++) {
175  map = &(self->map[i]);
176
177  if ( map->src_start >= size_of_universe || map->src_end >= size_of_universe || map->dst_start >= size_of_universe ) {
178   ROAR_WARN("__update(*): Universe too small for filter.");
179   return 0;
180  }
181
182  if ( map->src_end != -1 && (map->dst_start + map->src_end - map->src_start) >= size_of_universe ) {
183   ROAR_WARN("__update(*): Universe too small for filter.");
184   return 0;
185  }
186
187  switch (map->mt) {
188   case MT_COPY:
189     memcpy(&(universe[map->dst_start]), &(universe[map->src_start]), map->src_end - map->src_start + 1);
190    break;
191   case MT_SWAP:
192     tmp = universe[map->src_start];
193     universe[map->src_start] = universe[map->dst_start];
194     universe[map->dst_start] = tmp;
195    break;
196   case MT_INVERSE:
197     for (j = map->dst_start; j <= map->src_end; j++)
198      universe[j] = 255 - universe[j];
199    break;
200  }
201 }
202
203 return 0;
204}
205
206static const struct roar_slfi_filter filter[1] = {
207 {
208  .name = "map",
209  .description = "Map SLFI filter",
210  .flags = ROAR_SLFI_FLAG_ON_UPDATE,
211  .init = __init,
212  .uninit = NULL,
213  .update = __update,
214  .ctl = NULL
215 }
216};
217
218ROAR_DL_PLUGIN_REG_SLFI(filter);
219
220// This is the plugin control block.
221ROAR_DL_PLUGIN_START(filter_slfi_map) {
222 // Here we set the name and vendor of our plugin.
223 // If you have no Vendor ID you need to use ROAR_DL_PLUGIN_META_PRODUCT_NV().
224 ROAR_DL_PLUGIN_META_PRODUCT_NIV("filter-slfi-map", ROAR_VID_ROARAUDIO, ROAR_VNAME_ROARAUDIO);
225
226 // This sets the version of your plugin.
227 ROAR_DL_PLUGIN_META_VERSION(ROAR_VERSION_STRING);
228
229 // This sets the license of your plugin.
230 // If there is no tag for the license you use you can just
231 // use ROAR_DL_PLUGIN_META_LICENSE().
232 ROAR_DL_PLUGIN_META_LICENSE_TAG(GPLv3_0);
233
234 // This sets the author and contact infos.
235 // There are several other macros to do this with other parameters.
236 // See ROAR_DL_PLUGIN_META_CONTACT*() in the header or documentation.
237 ROAR_DL_PLUGIN_META_CONTACT_FLNE("Philipp", "Schafft", "ph3-der-loewe", "lion@lion.leolix.org");
238
239 // This sets the description for your plugin.
240 ROAR_DL_PLUGIN_META_DESC("This plugin maps values between channels.");
241
242 // Load filters.
243 ROAR_DL_PLUGIN_REG_FNFUNC(ROAR_DL_FN_FILTER);
244
245// This is the end of the control block.
246} ROAR_DL_PLUGIN_END
247
248//ll
Note: See TracBrowser for help on using the repository browser.