26 #include <core/exceptions/system.h> 28 #include <sys/ioctl.h> 106 Visca::Visca(
const char *device_file,
unsigned int def_timeout_ms,
bool blocking)
108 __inquire = VISCA_RUNINQ_NONE;
109 __device_file = strdup(device_file);
110 __blocking = blocking;
112 __default_timeout_ms = def_timeout_ms;
113 __pan_speed = MAX_PAN_SPEED;
114 __tilt_speed = MAX_TILT_SPEED;
116 for (
unsigned int i = 0; i < NONBLOCKING_NUM; ++i) {
117 __nonblocking_sockets[i] = 0;
118 __nonblocking_running[i] =
false;
140 struct termios param;
142 __fd = ::open(__device_file, O_RDWR);
147 if (tcgetattr(__fd, ¶m) == -1) {
153 cfsetospeed(¶m, B9600);
154 cfsetispeed(¶m, B9600);
156 param.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
157 param.c_cflag |= CREAD;
158 param.c_cflag |= CLOCAL;
161 param.c_cc[VMIN] = 1;
162 param.c_cc[VTIME] = 0;
164 param.c_iflag |= IGNBRK;
165 param.c_iflag &= ~PARMRK;
166 param.c_iflag &= ~ISTRIP;
167 param.c_iflag &= ~INLCR;
168 param.c_iflag &= ~IGNCR;
169 param.c_iflag &= ~ICRNL;
170 param.c_iflag &= ~IXON;
171 param.c_iflag &= ~IXOFF;
173 param.c_lflag &= ~ECHO;
176 param.c_lflag |= IEXTEN;
177 param.c_oflag &= ~OPOST;
183 param.c_cflag &= ~CS5 & ~CS6 & ~CS7 & ~CS8;
185 param.c_cflag |= CS8;
188 param.c_cflag &=~(PARENB & PARODD);
191 param.c_cflag &= ~CSTOPB;
193 if (tcsetattr(__fd, TCSANOW, ¶m) != 0) {
201 __sender = VISCA_BUS_0;
202 __recipient = VISCA_BUS_1;
204 #ifdef TIMETRACKER_VISCA 205 __tt =
new TimeTracker();
206 __ttc_pantilt_get_send = __tt->addClass(
"getPanTilt: send");
207 __ttc_pantilt_get_read = __tt->addClass(
"getPanTilt: read");
208 __ttc_pantilt_get_handle = __tt->addClass(
"getPanTilt: handling responses");
209 __ttc_pantilt_get_interpret = __tt->addClass(
"getPanTilt: interpreting");
229 unsigned char recp_backup = __recipient;
230 __recipient = VISCA_BUS_BROADCAST;
233 __obuffer_length = 2;
239 __recipient = recp_backup;
243 __recipient = recp_backup;
256 __obuffer_length = 3;
262 e.
append(
"clear() failed");
276 __obuffer[0] |= (__sender << 4);
277 __obuffer[0] |= __recipient;
279 __obuffer[++__obuffer_length] = VISCA_TERMINATOR;
282 int written = write(__fd, __obuffer, __obuffer_length);
288 if (written < __obuffer_length) {
301 ioctl(__fd, FIONREAD, &num_bytes);
302 return (num_bytes > 0);
312 if (timeout_ms == 0xFFFFFFFF) timeout_ms = __default_timeout_ms;
314 recv_packet(timeout_ms);
316 e.
append(
"Receiving failed, recv_packet() call failed");
321 unsigned char type = __ibuffer[1] & 0xF0;
322 while (type == VISCA_RESPONSE_ACK) {
324 recv_packet(timeout_ms);
326 e.
append(
"Receiving failed, recv_packet() call 2 failed");
329 type = __ibuffer[1] & 0xF0;
333 case VISCA_RESPONSE_CLEAR:
334 case VISCA_RESPONSE_ADDRESS:
335 case VISCA_RESPONSE_COMPLETED:
336 case VISCA_RESPONSE_ERROR:
352 recv_packet(__default_timeout_ms);
358 unsigned char type = __ibuffer[1] & 0xF0;
359 while (type != VISCA_RESPONSE_ACK) {
363 recv_packet(__default_timeout_ms);
365 e.
append(
"Handling message of type %u failed", type);
368 type = __ibuffer[1] & 0xF0;
372 if (socket != NULL) {
373 *socket = __ibuffer[1] & 0x0F;
390 e.
append(
"Non-blocking send failed!");
400 Visca::finish_nonblocking(
unsigned int socket )
402 for (
unsigned int i = 0; i < NONBLOCKING_NUM; ++i) {
403 if (__nonblocking_sockets[i] == socket) {
404 __nonblocking_sockets[i] = 0;
405 __nonblocking_running[i] =
false;
410 throw ViscaException(
"finish_nonblocking() failed: socket not found");
421 if (item >= NONBLOCKING_NUM) {
424 return ! __nonblocking_running[item];
435 if (__obuffer[1] == VISCA_COMMAND) {
451 e.
append(
"Sending with reply failed");
461 Visca::recv_packet(
unsigned int timeout_ms)
464 timeval timeout = {0, (suseconds_t)timeout_ms * 1000};
468 FD_SET(__fd, &read_fds);
471 rv = select(__fd + 1, &read_fds, NULL, NULL, &timeout);
475 }
else if ( rv == 0 ) {
480 if (read(__fd, __ibuffer, 1) != 1) {
485 while (__ibuffer[pos] != VISCA_TERMINATOR && (pos <
sizeof(__ibuffer)-1)) {
486 if (read(__fd, &__ibuffer[++pos], 1) != 1) {
493 __ibuffer_length = pos + 1;
505 Visca::handle_response()
507 unsigned int type = __ibuffer[1] & 0xF0;
508 unsigned int socket = __ibuffer[1] & 0x0F;
516 if ( type == VISCA_RESPONSE_COMPLETED ) {
519 finish_nonblocking( __ibuffer[1] & 0x0F );
525 }
else if ( type == VISCA_RESPONSE_ERROR ) {
526 finish_nonblocking( __ibuffer[1] & 0x0F );
544 unsigned char cancel_socket = socket & 0x0000000F;
546 __obuffer[1] = VISCA_CANCEL | cancel_socket;
547 __obuffer_length = 1;
552 e.
append(
"cancel_command() failed");
556 if ( ((__ibuffer[1] & 0xF0) == VISCA_RESPONSE_ERROR) &&
557 ((__ibuffer[1] & 0x0F) == cancel_socket) &&
558 ((__ibuffer[2] == VISCA_ERROR_CANCELLED)) ) {
571 __inquire = VISCA_RUNINQ_NONE;
573 while (data_available()) {
591 __obuffer[1] = VISCA_COMMAND;
592 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
593 __obuffer[3] = VISCA_POWER;
594 __obuffer[4] = powered ? VISCA_POWER_ON : VISCA_POWER_OFF;
595 __obuffer_length = 4;
600 e.
append(
"set_power() failed");
612 __obuffer[1] = VISCA_INQUIRY;
613 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
614 __obuffer[3] = VISCA_POWER;
615 __obuffer_length = 3;
620 e.
append(
"Failed to get power data");
625 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
626 return (__ibuffer[2] == VISCA_POWER_ON);
628 throw ViscaException(
"is_powered(): inquiry failed, response code not VISCA_RESPONSE_COMPLETED");
654 unsigned short int tilt_val = 0 + tilt;
655 unsigned short int pan_val = 0 + pan;
657 __obuffer[1] = VISCA_COMMAND;
658 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
659 __obuffer[3] = VISCA_PT_ABSOLUTE_POSITION;
660 __obuffer[4] = __pan_speed;
661 __obuffer[5] = __tilt_speed;
664 __obuffer[6] = (pan_val & 0xf000) >> 12;
665 __obuffer[7] = (pan_val & 0x0f00) >> 8;
666 __obuffer[8] = (pan_val & 0x00f0) >> 4;
667 __obuffer[9] = (pan_val & 0x000f);
669 __obuffer[10] = (tilt_val & 0xf000) >> 12;
670 __obuffer[11] = (tilt_val & 0x0f00) >> 8;
671 __obuffer[12] = (tilt_val & 0x00f0) >> 4;
672 __obuffer[13] = (tilt_val & 0x000f);
674 __obuffer_length = 13;
678 __nonblocking_running[ NONBLOCKING_PANTILT ] =
true;
679 send_nonblocking( &(__nonblocking_sockets[ NONBLOCKING_PANTILT ]) );
684 e.
append(
"setPanTilt() failed");
698 if (pan_speed > MAX_PAN_SPEED) {
699 throw fawkes::Exception(
"Pan speed too hight, max: %u des: %u", MAX_PAN_SPEED, pan_speed);
701 if (tilt_speed > MAX_TILT_SPEED) {
702 throw fawkes::Exception(
"Tilt speed too hight, max: %u des: %u", MAX_TILT_SPEED, tilt_speed);
705 __pan_speed = pan_speed;
706 __tilt_speed = tilt_speed;
717 pan_speed = __pan_speed;
718 tilt_speed = __tilt_speed;
728 __inquire = VISCA_RUNINQ_PANTILT;
730 __obuffer[1] = VISCA_INQUIRY;
731 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
732 __obuffer[3] = VISCA_PT_POSITION_INQ;
733 __obuffer_length = 3;
738 e.
append(
"startGetPanTilt() failed");
756 if ( __inquire != VISCA_RUNINQ_PANTILT ) {
757 throw ViscaException(
"Inquiry running, but it is not a pan/tilt inquiry");
759 #ifdef TIMETRACKER_VISCA 760 __tt->ping_start( __ttc_pantilt_get_read );
768 #ifdef TIMETRACKER_VISCA 769 __tt->ping_end( __ttc_pantilt_get_read );
774 __obuffer[1] = VISCA_INQUIRY;
775 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
776 __obuffer[3] = VISCA_PT_POSITION_INQ;
777 __obuffer_length = 3;
780 #ifdef TIMETRACKER_VISCA 781 __tt->ping_start( __ttc_pantilt_get_send );
783 __tt->ping_end( __ttc_pantilt_get_send );
784 __tt->ping_start( __ttc_pantilt_get_read );
786 __tt->ping_end( __ttc_pantilt_get_read );
795 #ifdef TIMETRACKER_VISCA 796 __tt->ping_start( __ttc_pantilt_get_handle );
799 while (__ibuffer[1] != VISCA_RESPONSE_COMPLETED) {
810 #ifdef TIMETRACKER_VISCA 811 __tt->ping_end( __ttc_pantilt_get_handle );
812 __tt->ping_start( __ttc_pantilt_get_interpret );
817 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
818 unsigned short int pan_val = 0;
819 unsigned short int tilt_val = 0;
821 pan_val |= (__ibuffer[2] & 0x0F) << 12;
822 pan_val |= (__ibuffer[3] & 0x0F) << 8;
823 pan_val |= (__ibuffer[4] & 0x0F) << 4;
824 pan_val |= (__ibuffer[5] & 0x0F);
826 tilt_val |= (__ibuffer[6] & 0x0F) << 12;
827 tilt_val |= (__ibuffer[7] & 0x0F) << 8;
828 tilt_val |= (__ibuffer[8] & 0x0F) << 4;
829 tilt_val |= (__ibuffer[9] & 0x0F);
831 if (pan_val < 0x8000) {
836 pan = pan_val - 0xFFFF;
839 if (tilt_val < 0x8000) {
844 tilt = tilt_val - 0xFFFF;
850 #ifdef TIMETRACKER_VISCA 851 __tt->ping_end( __ttc_pantilt_get_interpret );
852 __tt->print_to_stdout();
855 __inquire = VISCA_RUNINQ_NONE;
863 __obuffer[1] = VISCA_COMMAND;
864 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
865 __obuffer[3] = VISCA_PT_LIMITSET;
866 __obuffer[3] = VISCA_PT_LIMITSET_CLEAR;
867 __obuffer[4] = VISCA_PT_LIMITSET_SET_UR;
873 __obuffer[10] = 0x0F;
874 __obuffer[11] = 0x0F;
875 __obuffer[12] = 0x0F;
876 __obuffer_length = 12;
881 __obuffer[4] = VISCA_PT_LIMITSET_SET_DL;
885 e.
append(
"resetPanTiltLimit() failed");
901 __obuffer[1] = VISCA_COMMAND;
902 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
903 __obuffer[3] = VISCA_PT_LIMITSET;
904 __obuffer[3] = VISCA_PT_LIMITSET_SET;
905 __obuffer[4] = VISCA_PT_LIMITSET_SET_UR;
907 __obuffer[5] = (pan_right & 0xf000) >> 12;
908 __obuffer[6] = (pan_right & 0x0f00) >> 8;
909 __obuffer[7] = (pan_right & 0x00f0) >> 4;
910 __obuffer[8] = (pan_right & 0x000f);
912 __obuffer[9] = (tilt_up & 0xf000) >> 12;
913 __obuffer[10] = (tilt_up & 0x0f00) >> 8;
914 __obuffer[11] = (tilt_up & 0x00f0) >> 4;
915 __obuffer[12] = (tilt_up & 0x000f);
917 __obuffer_length = 12;
921 __obuffer[4] = VISCA_PT_LIMITSET_SET_DL;
923 __obuffer[5] = (pan_left & 0xf000) >> 12;
924 __obuffer[6] = (pan_left & 0x0f00) >> 8;
925 __obuffer[7] = (pan_left & 0x00f0) >> 4;
926 __obuffer[8] = (pan_left & 0x000f);
928 __obuffer[9] = (tilt_down & 0xf000) >> 12;
929 __obuffer[10] = (tilt_down & 0x0f00) >> 8;
930 __obuffer[11] = (tilt_down & 0x00f0) >> 4;
931 __obuffer[12] = (tilt_down & 0x000f);
935 e.
append(
"setPanTiltLimit() failed");
945 __obuffer[1] = VISCA_COMMAND;
946 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
947 __obuffer[3] = VISCA_PT_HOME;
948 __obuffer_length = 3;
953 e.
append(
"resetPanTilt() failed");
963 __obuffer[1] = VISCA_COMMAND;
964 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
965 __obuffer[3] = VISCA_ZOOM;
966 __obuffer[4] = VISCA_ZOOM_STOP;
967 __obuffer_length = 4;
972 e.
append(
"resetZoom() failed");
984 __obuffer[1] = VISCA_COMMAND;
985 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
986 __obuffer[3] = VISCA_ZOOM;
987 __obuffer[4] = VISCA_ZOOM_TELE_SPEED;
989 __obuffer[5] = (speed & 0x000f) | 0x0020;
990 __obuffer_length = 5;
995 e.
append(
"setZoomSpeedTele() failed");
1007 __obuffer[1] = VISCA_COMMAND;
1008 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1009 __obuffer[3] = VISCA_ZOOM;
1010 __obuffer[4] = VISCA_ZOOM_WIDE_SPEED;
1012 __obuffer[5] = (speed & 0x000f) | 0x0020;
1013 __obuffer_length = 5;
1018 e.
append(
"setZoomSpeedWide() failed");
1030 __obuffer[1] = VISCA_COMMAND;
1031 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1032 __obuffer[3] = VISCA_ZOOM_VALUE;
1034 __obuffer[4] = (zoom & 0xf000) >> 12;
1035 __obuffer[5] = (zoom & 0x0f00) >> 8;
1036 __obuffer[6] = (zoom & 0x00f0) >> 4;
1037 __obuffer[7] = (zoom & 0x000f);
1039 __obuffer_length = 7;
1043 __nonblocking_running[ NONBLOCKING_ZOOM ] =
true;
1044 send_nonblocking( &(__nonblocking_sockets[ NONBLOCKING_ZOOM ]) );
1049 e.
append(
"setZoom() failed");
1061 __obuffer[1] = VISCA_INQUIRY;
1062 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1063 __obuffer[3] = VISCA_ZOOM_VALUE;
1064 __obuffer_length = 3;
1069 e.
append(
"Failed to get zoom data");
1074 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
1075 unsigned short int zoom_val = 0;
1077 zoom_val |= (__ibuffer[2] & 0x0F) << 12;
1078 zoom_val |= (__ibuffer[3] & 0x0F) << 8;
1079 zoom_val |= (__ibuffer[4] & 0x0F) << 4;
1080 zoom_val |= (__ibuffer[5] & 0x0F);
1084 throw ViscaException(
"Failed to get zoom data failed, response code not VISCA_RESPONSE_COMPLETED");
1096 __obuffer[1] = VISCA_COMMAND;
1097 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1098 __obuffer[3] = VISCA_DZOOM;
1100 __obuffer[4] = VISCA_DZOOM_ON;
1102 __obuffer[4] = VISCA_DZOOM_OFF;
1104 __obuffer_length = 4;
1109 e.
append(
"setZoomDigitalEnabled() failed");
1121 __obuffer[1] = VISCA_COMMAND;
1122 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1123 __obuffer[3] = VISCA_PICTURE_EFFECT;
1124 __obuffer[4] = filter;
1125 __obuffer_length = 4;
1130 e.
append(
"applyEffect() failed");
1141 apply_effect(VISCA_PICTURE_EFFECT_OFF);
1143 e.
append(
"resetEffect() failed");
1154 apply_effect(VISCA_PICTURE_EFFECT_PASTEL);
1156 e.
append(
"applyEffectPastel() failed");
1167 apply_effect(VISCA_PICTURE_EFFECT_NEGATIVE);
1169 e.
append(
"applyEffectNegArt() failed");
1180 apply_effect(VISCA_PICTURE_EFFECT_SEPIA);
1182 e.
append(
"applyEffectSepia() failed");
1193 apply_effect(VISCA_PICTURE_EFFECT_BW);
1195 e.
append(
"applyEffectBnW() failed");
1206 apply_effect(VISCA_PICTURE_EFFECT_SOLARIZE);
1208 e.
append(
"applyEffectSolarize() failed");
1219 apply_effect(VISCA_PICTURE_EFFECT_MOSAIC);
1221 e.
append(
"applyEffectMosaic() failed");
1232 apply_effect(VISCA_PICTURE_EFFECT_SLIM);
1234 e.
append(
"applyEffectSlim() failed");
1245 apply_effect(VISCA_PICTURE_EFFECT_STRETCH);
1247 e.
append(
"applyEffectStretch() failed");
1259 __obuffer[1] = VISCA_INQUIRY;
1260 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1261 __obuffer[3] = VISCA_WB;
1262 __obuffer_length = 3;
1267 e.
append(
"getWhiteBalanceMode() failed");
1271 while (__ibuffer[1] != VISCA_RESPONSE_COMPLETED) {
1278 e.
append(
"getWhiteBalanceMode() failed");
1284 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
1285 return __ibuffer[2];
1287 throw ViscaException(
"Did not get 'request completed' response");
1299 __obuffer[1] = VISCA_COMMAND;
1300 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1301 __obuffer[3] = VISCA_MIRROR;
1302 __obuffer[4] = mirror ? VISCA_MIRROR_ON : VISCA_MIRROR_OFF;
1303 __obuffer_length = 4;
1308 e.
append(
"set_mirror() failed");
1319 __obuffer[1] = VISCA_INQUIRY;
1320 __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1321 __obuffer[3] = VISCA_MIRROR;
1322 __obuffer_length = 3;
1327 e.
append(
"Failed to get mirror data");
1332 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
1333 return (__ibuffer[2] != 0);
1335 throw ViscaException(
"Failed to get mirror data: zoom inquiry failed, " 1336 "response code not VISCA_RESPONSE_COMPLETED");
void apply_effect_slim()
Apply slim effect.
void apply_effect_mosaic()
Apply mosaic effect.
static const unsigned int VISCA_WHITEBALANCE_ATW
ATW white balance preset.
void set_pan_tilt_limit(int pan_left, int pan_right, int tilt_up, int tilt_down)
Set pan tilt limit.
static const unsigned int NONBLOCKING_PANTILT
Non-blocking pan/tilt item.
void set_pan_tilt(int pan, int tilt)
Set pan tilt.
void cancel_command(unsigned int socket)
Cancel a running command.
void apply_effect_solarize()
Apply solarize effect.
void set_address()
Set addresses of cameras.
static const unsigned int MAX_TILT_SPEED
Number of non-blocking items.
void start_get_pan_tilt()
Query for pan/tilt but do not wait until finished This will send an inquire to the camera that asks f...
static const unsigned int VISCA_WHITEBALANCE_MANUAL
Manual white balance.
void apply_effect_pastel()
Apply pastel effect.
void set_power(bool powered)
Set power state.
Exception()
Constructor for subclasses.
void clear()
Clear command buffers.
void set_pan_tilt_speed(unsigned char pan_speed, unsigned char tilt_speed)
Set pan/tilt speed.
The current system call has timed out before completion.
static const unsigned int NONBLOCKING_ZOOM
Non-blocking zoom item.
void set_zoom_speed_wide(unsigned int speed)
Set zoom speed in wide angle.
int _errno
Error number, should be used if the error was caused by a method that supplies errno.
bool is_powered()
Check if camera is powered.
void set_zoom_speed_tele(unsigned int speed)
Set zoom speed in tele.
void reset_effect()
Reset effects.
void send_with_reply()
Send and wait for reply, blocking.
static const unsigned int VISCA_WHITEBALANCE_INDOOR
Indoor white balance preset.
virtual ~Visca()
Destructor.
static const unsigned int NONBLOCKING_NUM
Number of non-blocking items.
void reset_pan_tilt_limit()
Reset pan/tilt limit.
ViscaInquiryRunningException()
Constructor.
static const unsigned int VISCA_WHITEBALANCE_OUTDOOR
Outdoor white balance preset.
void recv_ack(unsigned int *socket=NULL)
Receive ACK packet.
void open()
Open serial port.
void reset_zoom()
Reset zoom.
Base class for exceptions in Fawkes.
void set_zoom_digital_enabled(bool enabled)
Enable or disable digital zoome.
void apply_effect_stretch()
Apply stretch effect.
void get_pan_tilt(int &pan, int &tilt)
Get pan and tilt values.
void apply_effect(unsigned char effect)
Apply effect.
static const unsigned int VISCA_WHITEBLANCE_AUTO
Automatic white balance.
void reset_pan_tilt()
Reset pan/tilt.
bool data_available()
Check data availability.
bool is_nonblocking_finished(unsigned int item) const
Check if a non-blocking operation has been finished.
bool get_mirror()
Get mirror sate.
static const unsigned int MAX_PAN_SPEED
Number of non-blocking items.
void apply_effect_neg_art()
Apply negative art effect.
void apply_effect_sepia()
Apply sepia effect.
void recv(unsigned int timeout_ms=0xFFFFFFFF)
Receive data.
unsigned int get_white_balance_mode()
Get white balance mode.
ViscaException(const char *msg)
Constructor.
void get_pan_tilt_speed(unsigned char &pan_speed, unsigned char &tilt_speed)
Get pan/tilt speed.
void get_zoom(unsigned int &zoom)
Get zoom.
void set_zoom(unsigned int zoom)
Set zoom.
void apply_effect_bnw()
Apply B/W effect.
Visca(const char *device_file, unsigned int def_timeout_ms=10, bool blocking=true)
Constructor.
void send()
Send outbound queue.
void set_mirror(bool mirror)
Sett mirror sate.
static const unsigned int VISCA_WHITEBALANCE_ONE_PUSH
One push white balance preset.
void append(const char *format,...)
Append messages to the message list.
void send_nonblocking(unsigned int *socket=NULL)
Send non-blocking.
void process()
Process incoming data.