source: roaraudio/plugins/roard/dmx-waveform.c @ 5961:06e7fd9e4c25

Last change on this file since 5961:06e7fd9e4c25 was 5961:06e7fd9e4c25, checked in by phi, 10 years ago

Updates of copyright and license headers

File size: 5.5 KB
Line 
1//dmx-waveform.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011-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 <roard/include/roard.h>
27
28#define SAMPLES_PER_TICK 2
29
30struct state {
31 size_t startaddr;
32 size_t len;
33 int stream;
34 struct roar_stream_server * ss;
35};
36
37static struct state * g_state;
38static struct state   g_state_init = {
39 .startaddr =  0,
40 .len       =  4,
41 .stream    = -1,
42 .ss        = NULL
43};
44
45static int16_t __get_chanval(struct state * self, size_t c, int pos) {
46 int16_t ret = 0;
47
48 if ( pos ) {
49  ret = light_dmxchannel_get(self->startaddr + c);
50 } else {
51  if ( self->len & 1 ) {
52   ret = light_dmxchannel_get(self->startaddr + self->len - 1);
53  } else {
54   ret = light_dmxchannel_get(self->startaddr + self->len/2 + c);
55  }
56 }
57
58 if ( !pos )
59  ret *= -1;
60
61 ret *= 127;
62
63 ROAR_DBG("__get_chanval(self=%p, c=%lu, pos=%i) = %i", self, (long unsigned int)c, pos, (int)ret);
64 return ret;
65}
66
67static ssize_t _vio_read   (struct roar_vio_calls * vio, void *buf, size_t count) {
68 struct state * self = vio->inst;
69 ssize_t samplesize = roar_info2samplesize(&(ROAR_STREAM(self->ss)->info)) / 8;
70 ssize_t framesize = roar_info2framesize(&(ROAR_STREAM(self->ss)->info)) / 8;
71 size_t i, c;
72 int16_t * samp = buf;
73 size_t zeros = 0;
74
75 ROAR_DBG("_vio_read(vio=%p, buf=%p, count=%lu) = ?", vio, buf, (long unsigned int)count);
76
77 if ( count % framesize ) {
78  roar_err_set(ROAR_ERROR_RANGE);
79  return -1;
80 }
81
82 framesize *= 2;
83
84 if ( count % framesize ) {
85  zeros = count % framesize;
86  count -= zeros;
87  memset(buf+count, 0, zeros);
88 }
89
90 ROAR_DBG("_vio_read(vio=%p, buf=%p, count=%lu) = ?", vio, buf, (long unsigned int)count);
91
92 for (i = 0; i < count/samplesize;) {
93  for (c = 0; c < ROAR_STREAM(self->ss)->info.channels; c++, i++)
94   samp[i] = __get_chanval(self, c, 1);
95  for (c = 0; c < ROAR_STREAM(self->ss)->info.channels; c++, i++)
96   samp[i] = __get_chanval(self, c, 0);
97 }
98
99 ROAR_DBG("_vio_read(vio=%p, buf=%p, count=%lu) = %lu", vio, buf, (long unsigned int)count, (long unsigned int)count);
100
101 return count + zeros;
102}
103
104static int     _vio_ctl     (struct roar_vio_calls * vio, roar_vio_ctl_t cmd, void * data) {
105 (void)vio, (void)data;
106
107 if ( cmd == ROAR_VIO_CTL_NONBLOCK )
108  return 0;
109
110 roar_err_set(ROAR_ERROR_BADRQC);
111 return -1;
112}
113
114static int     _vio_close   (struct roar_vio_calls * vio) {
115 struct state * self = vio->inst;
116 self->stream = -1;
117 self->ss     = NULL;
118 return 0;
119}
120
121static int _init  (struct roar_dl_librarypara * para) {
122 struct roar_keyval * p;
123
124 p = roar_keyval_lookup(para->argv, "startaddr", para->argc, 1);
125 if ( p != NULL && p->value != NULL )
126  g_state->startaddr = atoi(p->value);
127
128 p = roar_keyval_lookup(para->argv, "len", para->argc, 1);
129 if ( p != NULL && p->value != NULL )
130  g_state->len = atoi(p->value);
131
132 if ((g_state->stream = streams_new()) == -1 )
133  return -1;
134
135 if ( streams_get(g_state->stream, &(g_state->ss)) == -1 ) {
136  streams_delete(g_state->stream);
137  return -1;
138 }
139
140 if ( streams_set_dir(g_state->stream, ROAR_DIR_PLAY, 1) == -1 ) {
141  streams_delete(g_state->stream);
142  return -1;
143 }
144
145 if ( streams_set_name(g_state->stream, "DMX to Waveform bridge") == -1 ) {
146  streams_delete(g_state->stream);
147  return -1;
148 }
149
150 ROAR_STREAM(g_state->ss)->info = *g_sa;
151 if ( g_state->len & 1 ) {
152  ROAR_STREAM(g_state->ss)->info.channels = g_state->len - 1;
153 } else {
154  ROAR_STREAM(g_state->ss)->info.channels = g_state->len / 2;
155 }
156 ROAR_STREAM(g_state->ss)->info.bits = 16;
157
158 roar_vio_clear_calls(&(g_state->ss->vio));
159 g_state->ss->vio.inst  = g_state;
160 g_state->ss->vio.read  = _vio_read;
161 g_state->ss->vio.ctl   = _vio_ctl;
162 g_state->ss->vio.close = _vio_close;
163
164 streams_set_fh(g_state->stream, -2);
165
166 client_stream_add(g_self_client, g_state->stream);
167
168 return 0;
169}
170
171static int _free  (struct roar_dl_librarypara * para) {
172 (void)para;
173
174 if ( g_state->stream == -1 )
175  return 0;
176
177 if ( streams_reset_flag(g_state->stream, ROAR_FLAG_IMMUTABLE) == -1 )
178  return -1;
179
180 if ( streams_delete(g_state->stream) == -1 )
181  return -1;
182
183 g_state->stream = -1;
184
185 return 0;
186}
187
188static struct roar_dl_appsched sched = {
189 .init   = _init,
190 .free   = _free,
191 .update = NULL,
192 .tick   = NULL,
193 .wait   = NULL
194};
195
196ROAR_DL_PLUGIN_START(dmx_waveform) {
197 ROARD_DL_CHECK_VERSIONS();
198
199 ROAR_DL_PLUGIN_META_PRODUCT_NIV("dmx-waveform", ROAR_VID_ROARAUDIO, ROAR_VNAME_ROARAUDIO);
200 ROAR_DL_PLUGIN_META_VERSION(ROAR_VERSION_STRING);
201 ROAR_DL_PLUGIN_META_LICENSE_TAG(GPLv3_0);
202 ROAR_DL_PLUGIN_META_CONTACT_FLNE("Philipp", "Schafft", "ph3-der-loewe", "lion@lion.leolix.org");
203 ROAR_DL_PLUGIN_META_DESC("This renders DMX channels as waveform signals. This is helpful to drive LEDs with cheap PWM based sound devices.");
204
205 ROAR_DL_PLUGIN_REG_GLOBAL_DATA(g_state, g_state_init);
206 ROAR_DL_PLUGIN_REG_APPSCHED(&sched);
207} ROAR_DL_PLUGIN_END
208
209//ll
Note: See TracBrowser for help on using the repository browser.