BlinkenArea - GitList
Repositories
Blog
Wiki
libflexipix
Code
Commits
Branches
Tags
Search
Tree:
aa3270a
Branches
Tags
master
v1.0.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5
v1.0.6
v1.0.7
v1.0.8
libflexipix
src
display.c
removed version information from file headers (manged via git now)
Stefan Schuermans
commited
aa3270a
at 2011-09-11 17:30:15
display.c
Blame
History
Raw
/* * FlexiPix library * * Copyright 2010-2011 Stefan Schuermans <stefan schuermans info> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <errno.h> #include <stdlib.h> #include <string.h> #include <flexipix/display.h> #include <flexipix/msg.h> #include <flexipix/types.h> #include <intern/config.h> #include <intern/constants.h> #include <intern/net.h> #include <intern/types.h> /** * \brief create a new FlexiPix display * * \param[in] sz_config_file name of config file to read * \param[in] p_msg_func message callback function or NULL * \param[in] p_msg_ctx user context for message callback * \return pointer to new FlexiPix display on success * or NULL on error */ flp_display_t *flp_display_create(const char *sz_config_file, flp_msg_func_p_t p_msg_func, void *p_msg_ctx) { flp_display_t *p_display; /* basic display setup */ /* create display structure */ p_display = (flp_display_t *)calloc(1, sizeof (flp_display_t)); if (!p_display) { if (p_msg_func) p_msg_func(p_msg_ctx, flp_msg_type_err, "out of memory\n"); return NULL; } /* set default bind address */ p_display->bind_addr.sin_family = AF_INET; p_display->bind_addr.sin_port = htons(FLP_BIND_PORT); p_display->bind_addr.sin_addr.s_addr = htonl(FLP_BIND_IP); /* no socket yet */ p_display->sock = -1; /* config file */ /* read config file */ if(flp_config_proc_file(p_display, sz_config_file, p_msg_func, p_msg_ctx)) { flp_display_free(p_display); /* cleanup everything that config file processing might heave created already */ p_msg_func(p_msg_ctx, flp_msg_type_err, "reading config file failed\n"); return NULL; } /* set up UDP socket */ /* create socket */ p_display->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (!flp_sock_is_valid(p_display->sock)) { flp_display_free(p_display); if (p_msg_func) { char errmsg[256]; flp_sock_get_last_error(errmsg, sizeof(errmsg)); p_msg_func(p_msg_ctx, flp_msg_type_err, "could not create UDP socket: %s\n", errmsg); } return NULL; } /* bind socket */ if (bind(p_display->sock, (struct sockaddr *)&p_display->bind_addr, sizeof (p_display->bind_addr))) { flp_display_free(p_display); if (p_msg_func) { char errmsg[256]; flp_sock_get_last_error(errmsg, sizeof(errmsg)); p_msg_func(p_msg_ctx, flp_msg_type_err, "could not bind UDP socket to \"%s:%u\": %s\n", inet_ntoa(p_display->bind_addr.sin_addr), (unsigned int)ntohs(p_display->bind_addr.sin_port), errmsg); } return NULL; } /* clear display */ flp_display_data_clear(p_display); return p_display; } /** * \brief free a FlexiPix display * * \param[in] p_display pointer to FlexiPix display */ void flp_display_free(flp_display_t *p_display) { int i; if (p_display) { /* free distributors */ for (i = 0; i < FLP_DISTRI_MAX_CNT; i++) { if (p_display->distri_ptrs[i]) { flp_distri_t *p_distri = p_display->distri_ptrs[i]; free(p_distri->p_pixels); free(p_distri->p_msg_buf); free(p_distri); } } /* close network connection */ if (flp_sock_is_valid(p_display->sock)) closesocket(p_display->sock); /* free display structutre */ free(p_display); } /* if (p_display) */ } /** * \brief get size of display * * \param[in] p_display pointer to FlexiPix display * \param[out] p_width width of display * \param[out] p_height height of display */ void flp_display_get_size(flp_display_t *p_display, unsigned int *p_width, unsigned int *p_height) { *p_width = (unsigned int)p_display->size.x; *p_height = (unsigned int)p_display->size.y; } /** * \brief clear image data to output on FlexiPix display * * clears the stored image data, * stored image data can later be sent to the distributors using * flp_display_send() * * \param[in] p_display pointer to FlexiPix display */ void flp_display_data_clear(flp_display_t *p_display) { flp_u8_t black[3] = { 0, 0, 0 }; flp_display_data(p_display, black, 0, 0, 0, 0, p_display->size.x, p_display->size.y); } /** * \brief set image data to output on FlexiPix display * * updates (part of) the stored image data, * stored image data can later be sent to the distributors using * flp_display_send() * * \param[in] p_display pointer to FlexiPix display * \param[in] p_data pointer to rectangular section of image data, * pixels need to be in R8G8B8 format * \param[in] stride_x stride between two pixels in X direction * \param[in] stride_y stride between two pixels in Y direction * \param[in] x X coordinate of left side of rectangular area * \param[in] y Y coordinate of top side of rectangular area * \param[in] width with of rectangular area * \param[in] height height of rectangular area */ void flp_display_data(flp_display_t *p_display, flp_u8_t *p_data, int stride_x, int stride_y, unsigned int x, unsigned int y, unsigned int width, unsigned int height) { unsigned int distri, out, pix, i, c; flp_distri_t *p_distri; flp_u8_t *dest, *src; flp_pixel_t *p_pixel; int rx, ry; /* set data for all distributors */ for (distri = 0; distri < FLP_DISTRI_MAX_CNT; distri++) { p_distri = p_display->distri_ptrs[distri]; if (p_distri) { /* set pointer to start of RGB data for pixels in message buffer (header is already set up and stays the same) */ dest = p_distri->p_msg_buf + FLP_MCUF_HDR_LEN; /* get RGB data of pixels for every output */ for (out = 0, i = 0; out < p_distri->output_cnt; out++) { for (pix = 0; pix < p_distri->pixel_cnt; pix++, i++) { p_pixel = &p_distri->p_pixels[i]; /* get pixel coordinates relative to rectangular area of image */ rx = p_pixel->x - (int)x; ry = p_pixel->y - (int)y; /* check if pixel is within rectangular area of image */ if (rx >= 0 && (unsigned int)rx < width && ry >= 0 && (unsigned int)ry < height) { /* get pixel data and map it */ src = (p_data + rx * stride_x + ry * stride_y); for (c = 0; c < 3; c++) dest[c] = p_distri->mapping[c].table[src[c]]; } dest += 3; } /* for (pix ...) */ } /* for (out ...) */ } /* if (p_distri) */ } /* for (distri ...) */ } /** * \brief send image data to distributors * * sends the currently stored image data to all configured distributors * * \param[in] p_display pointer to FlexiPix display */ void flp_display_send(flp_display_t *p_display) { unsigned int distri; flp_distri_t *p_distri; struct sockaddr_in dest_addr; /* send data to all distributors */ for (distri = 0; distri < FLP_DISTRI_MAX_CNT; distri++) { p_distri = p_display->distri_ptrs[distri]; if (p_distri) { /* assemble destination address of distributor */ dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(FLP_DEST_PORT); dest_addr.sin_addr.s_addr = htonl(FLP_DEST_IP_BASE + p_distri->distri * FLP_DEST_IP_STEP); /* send message as UDP packet */ sendto(p_display->sock, (char *)p_distri->p_msg_buf, p_distri->msg_len, 0, (struct sockaddr *)&dest_addr, sizeof (dest_addr)); } /* if (p_distri) */ } /* for (distri ...) */ }