aa3270aa371083e5c3c065a58b1551bfea58b4db
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

1) /*
2)  * FlexiPix library
3)  *
Stefan Schuermans removed version information...

Stefan Schuermans authored 13 years ago

4)  * Copyright 2010-2011 Stefan Schuermans <stefan schuermans info>
Stefan Schuermans 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);
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

81)   if (!flp_sock_is_valid(p_display->sock)) {
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

82)     flp_display_free(p_display);
Stefan Schuermans v1.0.2

Stefan Schuermans authored 13 years ago

83)     if (p_msg_func) {
84)       char errmsg[256];
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

85)       flp_sock_get_last_error(errmsg, sizeof(errmsg));
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

86)       p_msg_func(p_msg_ctx, flp_msg_type_err,
Stefan Schuermans v1.0.2

Stefan Schuermans authored 13 years ago

87)                  "could not create UDP socket: %s\n", errmsg);
88)     }
Stefan Schuermans 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);
Stefan Schuermans v1.0.2

Stefan Schuermans authored 13 years ago

96)     if (p_msg_func) {
97)       char errmsg[256];
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

98)       flp_sock_get_last_error(errmsg, sizeof(errmsg));
Stefan Schuermans 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),
Stefan Schuermans v1.0.2

Stefan Schuermans authored 13 years ago

102)                  (unsigned int)ntohs(p_display->bind_addr.sin_port), errmsg);
103)     }
Stefan Schuermans 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 */
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

136)     if (flp_sock_is_valid(p_display->sock))
Stefan Schuermans 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++)
Stefan Schuermans removed version information...

Stefan Schuermans authored 13 years ago

226)               dest[c] = p_distri->mapping[c].table[src[c]];
Stefan Schuermans 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 */
Stefan Schuermans 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));