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