v1.0.0
Stefan Schuermans authored 13 years ago
|
1) /*
2) * FlexiPix library
|
v1.0.6
Stefan Schuermans authored 13 years ago
|
3) * !version: 1.0.6! !date: 2010-12-30!
|
v1.0.0
Stefan Schuermans authored 13 years ago
|
4) *
5) * Copyright 2010 Stefan Schuermans <stefan schuermans info>
6) *
7) * This program is free software: you can redistribute it and/or modify
8) * it under the terms of the GNU General Public License as published by
9) * the Free Software Foundation, version 3 of the License.
10) *
11) *
12) * This program is distributed in the hope that it will be useful,
13) * but WITHOUT ANY WARRANTY; without even the implied warranty of
14) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15) * GNU General Public License for more details.
16) *
17) * You should have received a copy of the GNU Lesser General Public License
18) * along with this program. If not, see <http://www.gnu.org/licenses/>.
19) */
20)
21) #include <errno.h>
22) #include <stdlib.h>
23) #include <string.h>
24)
25) #include <flexipix/display.h>
26) #include <flexipix/msg.h>
27) #include <flexipix/types.h>
28) #include <intern/config.h>
29) #include <intern/constants.h>
30) #include <intern/net.h>
31) #include <intern/types.h>
32)
33) /**
34) * \brief create a new FlexiPix display
35) *
36) * \param[in] sz_config_file name of config file to read
37) * \param[in] p_msg_func message callback function or NULL
38) * \param[in] p_msg_ctx user context for message callback
39) * \return pointer to new FlexiPix display on success
40) * or NULL on error
41) */
42) flp_display_t *flp_display_create(const char *sz_config_file,
43) flp_msg_func_p_t p_msg_func,
44) void *p_msg_ctx)
45) {
46) flp_display_t *p_display;
47)
48) /* basic display setup */
49)
50) /* create display structure */
51) p_display = (flp_display_t *)calloc(1, sizeof (flp_display_t));
52) if (!p_display) {
53) if (p_msg_func)
54) p_msg_func(p_msg_ctx, flp_msg_type_err,
55) "out of memory\n");
56) return NULL;
57) }
58)
59) /* set default bind address */
60) p_display->bind_addr.sin_family = AF_INET;
61) p_display->bind_addr.sin_port = htons(FLP_BIND_PORT);
62) p_display->bind_addr.sin_addr.s_addr = htonl(FLP_BIND_IP);
63)
64) /* no socket yet */
65) p_display->sock = -1;
66)
67) /* config file */
68)
69) /* read config file */
70) if(flp_config_proc_file(p_display, sz_config_file,
71) p_msg_func, p_msg_ctx)) {
72) flp_display_free(p_display); /* cleanup everything that config file
73) processing might heave created already */
74) p_msg_func(p_msg_ctx, flp_msg_type_err, "reading config file failed\n");
75) return NULL;
76) }
77)
78) /* set up UDP socket */
79)
80) /* create socket */
81) p_display->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
v1.0.6
Stefan Schuermans authored 13 years ago
|
82) if (!flp_sock_is_valid(p_display->sock)) {
|
v1.0.0
Stefan Schuermans authored 13 years ago
|
83) flp_display_free(p_display);
|
v1.0.2
Stefan Schuermans authored 13 years ago
|
84) if (p_msg_func) {
85) char errmsg[256];
|
v1.0.6
Stefan Schuermans authored 13 years ago
|
86) flp_sock_get_last_error(errmsg, sizeof(errmsg));
|
v1.0.0
Stefan Schuermans authored 13 years ago
|
87) p_msg_func(p_msg_ctx, flp_msg_type_err,
|
v1.0.2
Stefan Schuermans authored 13 years ago
|
88) "could not create UDP socket: %s\n", errmsg);
89) }
|
v1.0.0
Stefan Schuermans authored 13 years ago
|
90) return NULL;
91) }
92)
93) /* bind socket */
94) if (bind(p_display->sock, (struct sockaddr *)&p_display->bind_addr,
95) sizeof (p_display->bind_addr))) {
96) flp_display_free(p_display);
|
v1.0.2
Stefan Schuermans authored 13 years ago
|
97) if (p_msg_func) {
98) char errmsg[256];
|
v1.0.6
Stefan Schuermans authored 13 years ago
|
99) flp_sock_get_last_error(errmsg, sizeof(errmsg));
|
v1.0.0
Stefan Schuermans authored 13 years ago
|
100) p_msg_func(p_msg_ctx, flp_msg_type_err,
101) "could not bind UDP socket to \"%s:%u\": %s\n",
102) inet_ntoa(p_display->bind_addr.sin_addr),
|
v1.0.2
Stefan Schuermans authored 13 years ago
|
103) (unsigned int)ntohs(p_display->bind_addr.sin_port), errmsg);
104) }
|
v1.0.0
Stefan Schuermans authored 13 years ago
|
105) return NULL;
106) }
107)
108) /* clear display */
109)
110) flp_display_data_clear(p_display);
111)
112) return p_display;
113) }
114)
115) /**
116) * \brief free a FlexiPix display
117) *
118) * \param[in] p_display pointer to FlexiPix display
119) */
120) void flp_display_free(flp_display_t *p_display)
121) {
122) int i;
123)
124) if (p_display) {
125)
126) /* free distributors */
127) for (i = 0; i < FLP_DISTRI_MAX_CNT; i++) {
128) if (p_display->distri_ptrs[i]) {
129) flp_distri_t *p_distri = p_display->distri_ptrs[i];
130) free(p_distri->p_pixels);
131) free(p_distri->p_msg_buf);
132) free(p_distri);
133) }
134) }
135)
136) /* close network connection */
|
v1.0.6
Stefan Schuermans authored 13 years ago
|
137) if (flp_sock_is_valid(p_display->sock))
|
v1.0.0
Stefan Schuermans authored 13 years ago
|
138) closesocket(p_display->sock);
139)
140) /* free display structutre */
141) free(p_display);
142)
143) } /* if (p_display) */
144) }
145)
146) /**
147) * \brief get size of display
148) *
149) * \param[in] p_display pointer to FlexiPix display
150) * \param[out] p_width width of display
151) * \param[out] p_height height of display
152) */
153) void flp_display_get_size(flp_display_t *p_display,
154) unsigned int *p_width, unsigned int *p_height)
155) {
156) *p_width = (unsigned int)p_display->size.x;
157) *p_height = (unsigned int)p_display->size.y;
158) }
159)
160) /**
161) * \brief clear image data to output on FlexiPix display
162) *
163) * clears the stored image data,
164) * stored image data can later be sent to the distributors using
165) * flp_display_send()
166) *
167) * \param[in] p_display pointer to FlexiPix display
168) */
169) void flp_display_data_clear(flp_display_t *p_display)
170) {
171) flp_u8_t black[3] = { 0, 0, 0 };
172) flp_display_data(p_display, black, 0, 0,
173) 0, 0, p_display->size.x, p_display->size.y);
174) }
175)
176) /**
177) * \brief set image data to output on FlexiPix display
178) *
179) * updates (part of) the stored image data,
180) * stored image data can later be sent to the distributors using
181) * flp_display_send()
182) *
183) * \param[in] p_display pointer to FlexiPix display
184) * \param[in] p_data pointer to rectangular section of image data,
185) * pixels need to be in R8G8B8 format
186) * \param[in] stride_x stride between two pixels in X direction
187) * \param[in] stride_y stride between two pixels in Y direction
188) * \param[in] x X coordinate of left side of rectangular area
189) * \param[in] y Y coordinate of top side of rectangular area
190) * \param[in] width with of rectangular area
191) * \param[in] height height of rectangular area
192) */
193) void flp_display_data(flp_display_t *p_display, flp_u8_t *p_data,
194) int stride_x, int stride_y,
195) unsigned int x, unsigned int y,
196) unsigned int width, unsigned int height)
197) {
198) unsigned int distri, out, pix, i, c;
199) flp_distri_t *p_distri;
200) flp_u8_t *dest, *src;
201) flp_pixel_t *p_pixel;
202) int rx, ry;
203)
204) /* set data for all distributors */
205) for (distri = 0; distri < FLP_DISTRI_MAX_CNT; distri++) {
206) p_distri = p_display->distri_ptrs[distri];
207) if (p_distri) {
208)
209) /* set pointer to start of RGB data for pixels in message buffer
210) (header is already set up and stays the same) */
211) dest = p_distri->p_msg_buf + FLP_MCUF_HDR_LEN;
212)
213) /* get RGB data of pixels for every output */
214) for (out = 0, i = 0; out < p_distri->output_cnt; out++) {
215) for (pix = 0; pix < p_distri->pixel_cnt; pix++, i++) {
216) p_pixel = &p_distri->p_pixels[i];
217)
218) /* get pixel coordinates relative to rectangular area of image */
219) rx = p_pixel->x - (int)x;
220) ry = p_pixel->y - (int)y;
221) /* check if pixel is within rectangular area of image */
222) if (rx >= 0 && (unsigned int)rx < width
223) && ry >= 0 && (unsigned int)ry < height) {
224) /* get pixel data and map it */
225) src = (p_data + rx * stride_x + ry * stride_y);
226) for (c = 0; c < 3; c++)
227) dest[c] = p_distri->mapping[c].table[src[c]];
228) }
229)
230) dest += 3;
231) } /* for (pix ...) */
232) } /* for (out ...) */
233)
234) } /* if (p_distri) */
235) } /* for (distri ...) */
236) }
237)
238) /**
239) * \brief send image data to distributors
240) *
241) * sends the currently stored image data to all configured distributors
242) *
243) * \param[in] p_display pointer to FlexiPix display
244) */
245) void flp_display_send(flp_display_t *p_display)
246) {
247) unsigned int distri;
248) flp_distri_t *p_distri;
249) struct sockaddr_in dest_addr;
250)
251) /* send data to all distributors */
252) for (distri = 0; distri < FLP_DISTRI_MAX_CNT; distri++) {
253) p_distri = p_display->distri_ptrs[distri];
254) if (p_distri) {
255)
256) /* assemble destination address of distributor */
257) dest_addr.sin_family = AF_INET;
258) dest_addr.sin_port = htons(FLP_DEST_PORT);
259) dest_addr.sin_addr.s_addr =
260) htonl(FLP_DEST_IP_BASE + p_distri->distri * FLP_DEST_IP_STEP);
261)
262) /* send message as UDP packet */
|
v1.0.6
Stefan Schuermans authored 13 years ago
|
263) sendto(p_display->sock, (char *)p_distri->p_msg_buf, p_distri->msg_len,
264) 0, (struct sockaddr *)&dest_addr, sizeof (dest_addr));
|