Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * visca.cpp - Controller for Visca cams 00004 * 00005 * Created: Wed Jun 08 12:08:17 2005 (FireVision) 00006 * Copyright 2005-2009 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include "visca.h" 00025 00026 #include <core/exceptions/system.h> 00027 00028 #include <sys/ioctl.h> 00029 #include <termios.h> 00030 #include <fcntl.h> 00031 #include <unistd.h> 00032 #include <cerrno> 00033 #include <cstring> 00034 #include <cstdlib> 00035 00036 /** @class ViscaException "visca.h" 00037 * Visca exception. 00038 */ 00039 00040 /** Constructor. 00041 * @param msg message of exception. 00042 */ 00043 ViscaException::ViscaException(const char *msg) 00044 : Exception(msg) 00045 {} 00046 00047 00048 /** Constructor with errno. 00049 * @param msg message prefix 00050 * @param _errno errno for additional error information. 00051 */ 00052 ViscaException::ViscaException(const char *msg, const int _errno) 00053 : Exception(_errno, msg) 00054 {} 00055 00056 /** @class ViscaInquiryRunningException "visca.h" 00057 * Visca inquire running exception. 00058 */ 00059 00060 /** Constructor. */ 00061 ViscaInquiryRunningException::ViscaInquiryRunningException() 00062 : ViscaException("Inquiry already running") 00063 {} 00064 00065 00066 /** Automatic white balance. */ 00067 const unsigned int Visca::VISCA_WHITEBLANCE_AUTO = VISCA_WB_AUTO; 00068 /** Indoor white balance preset. */ 00069 const unsigned int Visca::VISCA_WHITEBALANCE_INDOOR = VISCA_WB_INDOOR; 00070 /** Outdoor white balance preset. */ 00071 const unsigned int Visca::VISCA_WHITEBALANCE_OUTDOOR = VISCA_WB_OUTDOOR; 00072 /** One push white balance preset. */ 00073 const unsigned int Visca::VISCA_WHITEBALANCE_ONE_PUSH = VISCA_WB_ONE_PUSH; 00074 /** ATW white balance preset. */ 00075 const unsigned int Visca::VISCA_WHITEBALANCE_ATW = VISCA_WB_ATW; 00076 /** Manual white balance. */ 00077 const unsigned int Visca::VISCA_WHITEBALANCE_MANUAL = VISCA_WB_MANUAL; 00078 00079 /** Non-blocking pan/tilt item. */ 00080 const unsigned int Visca::NONBLOCKING_PANTILT = 0; 00081 /** Non-blocking zoom item. */ 00082 const unsigned int Visca::NONBLOCKING_ZOOM = 1; 00083 /** Number of non-blocking items. */ 00084 const unsigned int Visca::NONBLOCKING_NUM = 2; 00085 00086 /** Number of non-blocking items. */ 00087 const unsigned int Visca::MAX_PAN_SPEED = 0x18; 00088 00089 /** Number of non-blocking items. */ 00090 const unsigned int Visca::MAX_TILT_SPEED = 0x14; 00091 00092 00093 /** @class Visca "visca.h" 00094 * Visca control protocol implementation over a serial line. 00095 * @author Tim Niemueller 00096 */ 00097 00098 00099 /** Constructor. 00100 * @param device_file serial device file (e.g. /dev/ttyUSB0) 00101 * @param def_timeout_ms default timeout for read operations applied if no explicit 00102 * timeout is given. 00103 * @param blocking if true, setting the pan/tilt values will only cause sending the 00104 * request, you need to call process() when there is time to process and handle 00105 * incoming messages. 00106 */ 00107 Visca::Visca(const char *device_file, unsigned int def_timeout_ms, bool blocking) 00108 { 00109 __inquire = VISCA_RUNINQ_NONE; 00110 __device_file = strdup(device_file); 00111 __blocking = blocking; 00112 __opened = false; 00113 __default_timeout_ms = def_timeout_ms; 00114 __pan_speed = MAX_PAN_SPEED; 00115 __tilt_speed = MAX_TILT_SPEED; 00116 00117 for (unsigned int i = 0; i < NONBLOCKING_NUM; ++i) { 00118 __nonblocking_sockets[i] = 0; 00119 __nonblocking_running[i] = false; 00120 } 00121 00122 open(); 00123 00124 set_address(); 00125 clear(); 00126 } 00127 00128 00129 /** Destructor. */ 00130 Visca::~Visca() 00131 { 00132 close(); 00133 free(__device_file); 00134 } 00135 00136 00137 /** Open serial port. */ 00138 void 00139 Visca::open() { 00140 00141 struct termios param; 00142 00143 __fd = ::open(__device_file, O_RDWR | O_NONBLOCK); 00144 if (! __fd) { 00145 throw ViscaException("Cannot open device", errno); 00146 } 00147 00148 if (tcgetattr(__fd, ¶m) == -1) { 00149 ViscaException ve("Getting the port parameters failed", errno); 00150 ::close(__fd); 00151 throw ve; 00152 } 00153 00154 cfsetospeed(¶m, B9600); 00155 cfsetispeed(¶m, B9600); 00156 00157 param.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 00158 param.c_cflag |= CREAD; 00159 param.c_cflag |= CLOCAL; 00160 //param.c_cflag |= CRTSCTS; 00161 00162 param.c_cc[VMIN] = 1; 00163 param.c_cc[VTIME] = 0; 00164 00165 param.c_iflag |= IGNBRK; 00166 param.c_iflag &= ~PARMRK; 00167 param.c_iflag &= ~ISTRIP; 00168 param.c_iflag &= ~INLCR; 00169 param.c_iflag &= ~IGNCR; 00170 param.c_iflag &= ~ICRNL; 00171 param.c_iflag &= ~IXON; 00172 param.c_iflag &= ~IXOFF; 00173 00174 param.c_lflag &= ~ECHO; 00175 00176 // hand shake 00177 param.c_lflag |= IEXTEN; 00178 param.c_oflag &= ~OPOST; //enable raw output 00179 00180 //tcflow (__fd, TCOON); 00181 //tcflow (__fd, TCION); 00182 00183 // number of data bits: 8 00184 param.c_cflag &= ~CS5 & ~CS6 & ~CS7 & ~CS8; 00185 00186 param.c_cflag |= CS8; 00187 00188 // parity: none 00189 param.c_cflag &=~(PARENB & PARODD); 00190 00191 // stop bits: 1 00192 param.c_cflag &= ~CSTOPB; 00193 00194 if (tcsetattr(__fd, TCSANOW, ¶m) != 0) { 00195 ViscaException ve("Setting the port parameters failed", errno); 00196 ::close(__fd); 00197 throw ve; 00198 } 00199 00200 __opened = true; 00201 // Choose first camera by default 00202 __sender = VISCA_BUS_0; 00203 __recipient = VISCA_BUS_1; 00204 00205 #ifdef TIMETRACKER_VISCA 00206 __tt = new TimeTracker(); 00207 __ttc_pantilt_get_send = __tt->addClass("getPanTilt: send"); 00208 __ttc_pantilt_get_read = __tt->addClass("getPanTilt: read"); 00209 __ttc_pantilt_get_handle = __tt->addClass("getPanTilt: handling responses"); 00210 __ttc_pantilt_get_interpret = __tt->addClass("getPanTilt: interpreting"); 00211 #endif 00212 } 00213 00214 00215 /** Close port. */ 00216 void 00217 Visca::close() 00218 { 00219 if (__opened) { 00220 __opened = false; 00221 ::close(__fd); 00222 } 00223 } 00224 00225 00226 /** Set addresses of cameras. */ 00227 void 00228 Visca::set_address() 00229 { 00230 unsigned char recp_backup = __recipient; 00231 __recipient = VISCA_BUS_BROADCAST; 00232 __obuffer[1] = 0x30; 00233 __obuffer[2] = 0x01; 00234 __obuffer_length = 2; 00235 00236 try { 00237 send(); 00238 recv(); 00239 } catch (ViscaException &e) { 00240 __recipient = recp_backup; 00241 throw; 00242 } 00243 00244 __recipient = recp_backup; 00245 } 00246 00247 00248 /** Clear command buffers. */ 00249 void 00250 Visca::clear() 00251 { 00252 if (!__opened) throw ViscaException("Serial port not open"); 00253 00254 __obuffer[1] = 0x01; 00255 __obuffer[2] = 0x00; 00256 __obuffer[3] = 0x01; 00257 __obuffer_length = 3; 00258 00259 try { 00260 send(); 00261 recv(); 00262 } catch (ViscaException &e) { 00263 e.append("clear() failed"); 00264 throw; 00265 } 00266 } 00267 00268 00269 /** Send outbound queue. */ 00270 void 00271 Visca::send() 00272 { 00273 if (!__opened) throw ViscaException("Serial port not open"); 00274 00275 // Set first bit to 1 00276 __obuffer[0] = 0x80; 00277 __obuffer[0] |= (__sender << 4); 00278 __obuffer[0] |= __recipient; 00279 00280 __obuffer[++__obuffer_length] = VISCA_TERMINATOR; 00281 ++__obuffer_length; 00282 00283 int written = write(__fd, __obuffer, __obuffer_length); 00284 //printf("Visca sent: "); 00285 //for (int i = 0; i < __obuffer_length; ++i) { 00286 // printf("%02X", __obuffer[i]); 00287 //} 00288 //printf("\n"); 00289 if (written < __obuffer_length) { 00290 throw ViscaException("Not all bytes send"); 00291 } 00292 } 00293 00294 00295 /** Check data availability. 00296 * @return true if data is available, false otherwise 00297 */ 00298 bool 00299 Visca::data_available() 00300 { 00301 int num_bytes = 0; 00302 ioctl(__fd, FIONREAD, &num_bytes); 00303 return (num_bytes > 0); 00304 } 00305 00306 00307 /** Receive data. 00308 * @param timeout_ms read timeout in miliseconds 00309 */ 00310 void 00311 Visca::recv(unsigned int timeout_ms) 00312 { 00313 if (timeout_ms == 0xFFFFFFFF) timeout_ms = __default_timeout_ms; 00314 try { 00315 recv_packet(timeout_ms); 00316 } catch (ViscaException &e) { 00317 e.append("Receiving failed, recv_packet() call failed"); 00318 throw; 00319 } 00320 00321 // Get type of message 00322 unsigned char type = __ibuffer[1] & 0xF0; 00323 while (type == VISCA_RESPONSE_ACK) { 00324 try { 00325 recv_packet(timeout_ms); 00326 } catch (ViscaException &e) { 00327 e.append("Receiving failed, recv_packet() call 2 failed"); 00328 throw; 00329 } 00330 type = __ibuffer[1] & 0xF0; 00331 } 00332 00333 switch (type) { 00334 case VISCA_RESPONSE_CLEAR: 00335 case VISCA_RESPONSE_ADDRESS: 00336 case VISCA_RESPONSE_COMPLETED: 00337 case VISCA_RESPONSE_ERROR: 00338 break; 00339 default: 00340 throw fawkes::Exception("Receiving failed, unexpected packet type %u received", 00341 type); 00342 } 00343 } 00344 00345 00346 /** Receive ACK packet. 00347 * @param socket contains the socket that the ACK was received on upon return 00348 */ 00349 void 00350 Visca::recv_ack(unsigned int *socket) 00351 { 00352 try { 00353 recv_packet(__default_timeout_ms); 00354 } catch (ViscaException &e) { 00355 throw ViscaException("recv_ack(): recv_packet() failed"); 00356 } 00357 00358 // Get type of message 00359 unsigned char type = __ibuffer[1] & 0xF0; 00360 while (type != VISCA_RESPONSE_ACK) { 00361 00362 try { 00363 handle_response(); 00364 recv_packet(__default_timeout_ms); 00365 } catch (ViscaException &e) { 00366 e.append("Handling message of type %u failed", type); 00367 throw; 00368 } 00369 type = __ibuffer[1] & 0xF0; 00370 } 00371 00372 // Got an ack now 00373 if (socket != NULL) { 00374 *socket = __ibuffer[1] & 0x0F; 00375 } 00376 00377 } 00378 00379 00380 /** Send non-blocking. 00381 * Does a non-blocking send. 00382 * @param socket the socket that was used to send the request. 00383 */ 00384 void 00385 Visca::send_nonblocking(unsigned int *socket) 00386 { 00387 try { 00388 send(); 00389 recv_ack(socket); 00390 } catch (ViscaException &e) { 00391 e.append("Non-blocking send failed!"); 00392 throw; 00393 } 00394 } 00395 00396 00397 /** Finish a non-blocking operation. 00398 * @param socket socket that the non-blocking operation was sent to 00399 */ 00400 void 00401 Visca::finish_nonblocking( unsigned int socket ) 00402 { 00403 for (unsigned int i = 0; i < NONBLOCKING_NUM; ++i) { 00404 if (__nonblocking_sockets[i] == socket) { 00405 __nonblocking_sockets[i] = 0; 00406 __nonblocking_running[i] = false; 00407 return; 00408 } 00409 } 00410 00411 throw ViscaException("finish_nonblocking() failed: socket not found"); 00412 } 00413 00414 00415 /** Check if a non-blocking operation has been finished. 00416 * @param item the non-blocking item to check 00417 * @return true if the non-blocking operation has been finished, false otherwise 00418 */ 00419 bool 00420 Visca::is_nonblocking_finished(unsigned int item) const 00421 { 00422 if (item >= NONBLOCKING_NUM) { 00423 throw ViscaException("Invalid item number"); 00424 } 00425 return ! __nonblocking_running[item]; 00426 } 00427 00428 00429 /** Send and wait for reply, blocking. 00430 */ 00431 void 00432 Visca::send_with_reply() 00433 { 00434 try { 00435 send(); 00436 recv(); 00437 } catch (ViscaException &e) { 00438 e.append("Sending with reply failed"); 00439 throw; 00440 } 00441 } 00442 00443 00444 /** Receive a packet. 00445 * @param timeout_ms read timeout in miliseconds 00446 */ 00447 void 00448 Visca::recv_packet(unsigned int timeout_ms) 00449 { 00450 // wait for message 00451 timeval timeout = {0, timeout_ms * 1000}; 00452 00453 fd_set read_fds; 00454 FD_ZERO(&read_fds); 00455 FD_SET(__fd, &read_fds); 00456 00457 int rv = 0; 00458 rv = select(__fd + 1, &read_fds, NULL, NULL, &timeout); 00459 00460 if ( rv == -1 ) { 00461 throw fawkes::Exception(errno, "Select on FD failed"); 00462 } else if ( rv == 0 ) { 00463 throw fawkes::TimeoutException("Timeout reached while waiting for incoming data"); 00464 } 00465 00466 // get octets one by one 00467 if (read(__fd, __ibuffer, 1) != 1) { 00468 throw fawkes::Exception(errno, "Visca reading packet byte failed"); 00469 } 00470 00471 int pos = 0; 00472 while (__ibuffer[pos] != VISCA_TERMINATOR) { 00473 if (read(__fd, &__ibuffer[++pos], 1) != 1) { 00474 throw fawkes::Exception(errno, "Visca reading packet byte failed"); 00475 } 00476 usleep(0); 00477 } 00478 __ibuffer_length = pos + 1; 00479 //printf("Visca read: "); 00480 //for (int i = 0; i < __ibuffer_length; ++i) { 00481 // printf("%02X", __ibuffer[i]); 00482 //} 00483 //printf("\n"); 00484 } 00485 00486 00487 00488 /** Handle incoming response. */ 00489 void 00490 Visca::handle_response() 00491 { 00492 unsigned int type = __ibuffer[1] & 0xF0; 00493 unsigned int socket = __ibuffer[1] & 0x0F; 00494 00495 if (socket == 0) { 00496 // This is an inquire response, do NOT handle! 00497 //throw ViscaException("handle_response(): Received an inquire response, can't handle"); 00498 return; 00499 } 00500 00501 if ( type == VISCA_RESPONSE_COMPLETED ) { 00502 // Command has been finished 00503 try { 00504 finish_nonblocking( __ibuffer[1] & 0x0F ); 00505 } catch (ViscaException &e) { 00506 // Ignore, happens sometimes without effect 00507 // e.append("handle_response() failed, could not finish non-blocking"); 00508 // throw; 00509 } 00510 } else if ( type == VISCA_RESPONSE_ERROR ) { 00511 finish_nonblocking( __ibuffer[1] & 0x0F ); 00512 //throw ViscaException("handle_response(): got an error message from camera"); 00513 } else { 00514 // ignore 00515 //ViscaException ve("Got unknown/unhandled response type"); 00516 //ve.append("Received message of type %u", type); 00517 //throw ve; 00518 } 00519 00520 } 00521 00522 00523 /** Cancel a running command. 00524 * @param socket socket that the command was send on 00525 */ 00526 void 00527 Visca::cancel_command( unsigned int socket ) 00528 { 00529 unsigned char cancel_socket = socket & 0x0000000F; 00530 00531 __obuffer[1] = VISCA_CANCEL | cancel_socket; 00532 __obuffer_length = 1; 00533 00534 try { 00535 send_with_reply(); 00536 } catch (ViscaException &e) { 00537 e.append("cancel_command() failed"); 00538 throw; 00539 } 00540 00541 if ( ((__ibuffer[1] & 0xF0) == VISCA_RESPONSE_ERROR) && 00542 ((__ibuffer[1] & 0x0F) == cancel_socket) && 00543 ((__ibuffer[2] == VISCA_ERROR_CANCELLED)) ) { 00544 return; 00545 } else { 00546 throw ViscaException("Command could not be cancelled"); 00547 } 00548 } 00549 00550 00551 /** Process incoming data. */ 00552 void 00553 Visca::process() 00554 { 00555 00556 __inquire = VISCA_RUNINQ_NONE; 00557 00558 while (data_available()) { 00559 try { 00560 recv(); 00561 handle_response(); 00562 } catch (ViscaException &e) { 00563 // Ignore this error 00564 return; 00565 } 00566 } 00567 } 00568 00569 00570 /** Set pan tilt. 00571 * @param pan pan 00572 * @param tilt tilt 00573 */ 00574 void 00575 Visca::set_pan_tilt(int pan, int tilt) 00576 { 00577 00578 // we do not to check for blocking, could not be called at 00579 // the same time if blocking... 00580 /* 00581 if ( __nonblocking_running[ NONBLOCKING_PANTILT] ) { 00582 cout << "Cancelling old setPanTilt" << endl; 00583 if (cancel_command( __nonblocking_sockets[ NONBLOCKING_PANTILT ] ) != VISCA_SUCCESS) { 00584 cout << "Visca: Could not cancel old non-blocking pan/tilt command. Not setting new pan/tilt." << endl; 00585 return VISCA_E_CANCEL; 00586 } 00587 __nonblocking_running[ NONBLOCKING_PANTILT ] = false; 00588 } 00589 */ 00590 00591 unsigned short int tilt_val = 0 + tilt; 00592 unsigned short int pan_val = 0 + pan; 00593 00594 __obuffer[1] = VISCA_COMMAND; 00595 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00596 __obuffer[3] = VISCA_PT_ABSOLUTE_POSITION; 00597 __obuffer[4] = __pan_speed; 00598 __obuffer[5] = __tilt_speed; 00599 00600 // pan 00601 __obuffer[6] = (pan_val & 0xf000) >> 12; 00602 __obuffer[7] = (pan_val & 0x0f00) >> 8; 00603 __obuffer[8] = (pan_val & 0x00f0) >> 4; 00604 __obuffer[9] = (pan_val & 0x000f); 00605 // tilt 00606 __obuffer[10] = (tilt_val & 0xf000) >> 12; 00607 __obuffer[11] = (tilt_val & 0x0f00) >> 8; 00608 __obuffer[12] = (tilt_val & 0x00f0) >> 4; 00609 __obuffer[13] = (tilt_val & 0x000f); 00610 00611 __obuffer_length = 13; 00612 00613 try { 00614 if (! __blocking) { 00615 __nonblocking_running[ NONBLOCKING_PANTILT ] = true; 00616 send_nonblocking( &(__nonblocking_sockets[ NONBLOCKING_PANTILT ]) ); 00617 } else { 00618 send_with_reply(); 00619 } 00620 } catch (ViscaException &e) { 00621 e.append("setPanTilt() failed"); 00622 throw; 00623 } 00624 } 00625 00626 00627 /** Set pan/tilt speed. 00628 * @param pan_speed a value between 0 and MAX_PAN_SPEED 00629 * @param tilt_speed a value between 0 and MAX_TILT_SPEED 00630 * @exception Exception thrown if desired pan or tilt speed is too high 00631 */ 00632 void 00633 Visca::set_pan_tilt_speed(unsigned char pan_speed, unsigned char tilt_speed) 00634 { 00635 if (pan_speed > MAX_PAN_SPEED) { 00636 throw fawkes::Exception("Pan speed too hight, max: %u des: %u", MAX_PAN_SPEED, pan_speed); 00637 } 00638 if (tilt_speed > MAX_TILT_SPEED) { 00639 throw fawkes::Exception("Tilt speed too hight, max: %u des: %u", MAX_TILT_SPEED, tilt_speed); 00640 } 00641 00642 __pan_speed = pan_speed; 00643 __tilt_speed = tilt_speed; 00644 } 00645 00646 00647 /** Get pan/tilt speed. 00648 * @param pan_speed upon return contains pan speed index 00649 * @param tilt_speed upon return contains tilt speed index 00650 */ 00651 void 00652 Visca::get_pan_tilt_speed(unsigned char &pan_speed, unsigned char &tilt_speed) 00653 { 00654 pan_speed = __pan_speed; 00655 tilt_speed = __tilt_speed; 00656 } 00657 00658 /** Initiate a pan/tilt request, but do not wait for the reply. */ 00659 void 00660 Visca::start_get_pan_tilt() 00661 { 00662 00663 if ( __inquire ) throw ViscaInquiryRunningException(); 00664 00665 __inquire = VISCA_RUNINQ_PANTILT; 00666 00667 __obuffer[1] = VISCA_INQUIRY; 00668 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00669 __obuffer[3] = VISCA_PT_POSITION_INQ; 00670 __obuffer_length = 3; 00671 00672 try { 00673 send(); 00674 } catch (ViscaException &e) { 00675 e.append("startGetPanTilt() failed"); 00676 throw; 00677 } 00678 } 00679 00680 00681 /** Get pan and tilt values. 00682 * If you used startGetPanTilt() to initiate the query the result is 00683 * received and returned, otherwise a request is sent and the method blocks 00684 * until the answer has been received. 00685 * @param pan contains pan upon return 00686 * @param tilt contains tilt upon return 00687 */ 00688 void 00689 Visca::get_pan_tilt(int &pan, int &tilt) 00690 { 00691 00692 if ( __inquire ) { 00693 if ( __inquire != VISCA_RUNINQ_PANTILT ) { 00694 throw ViscaException("Inquiry running, but it is not a pan/tilt inquiry"); 00695 } else { 00696 #ifdef TIMETRACKER_VISCA 00697 __tt->ping_start( __ttc_pantilt_get_read ); 00698 #endif 00699 try { 00700 recv(); 00701 } catch (ViscaException &e) { 00702 // Ignore 00703 } 00704 #ifdef TIMETRACKER_VISCA 00705 __tt->ping_end( __ttc_pantilt_get_read ); 00706 #endif 00707 } 00708 } else { 00709 00710 __obuffer[1] = VISCA_INQUIRY; 00711 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00712 __obuffer[3] = VISCA_PT_POSITION_INQ; 00713 __obuffer_length = 3; 00714 00715 try { 00716 #ifdef TIMETRACKER_VISCA 00717 __tt->ping_start( __ttc_pantilt_get_send ); 00718 send(); 00719 __tt->ping_end( __ttc_pantilt_get_send ); 00720 __tt->ping_start( __ttc_pantilt_get_read ); 00721 recv(); 00722 __tt->ping_end( __ttc_pantilt_get_read ); 00723 #else 00724 send_with_reply(); 00725 #endif 00726 } catch (ViscaException &e) { 00727 // Ignore 00728 } 00729 } 00730 00731 #ifdef TIMETRACKER_VISCA 00732 __tt->ping_start( __ttc_pantilt_get_handle ); 00733 #endif 00734 00735 while (__ibuffer[1] != VISCA_RESPONSE_COMPLETED) { 00736 // inquire return from socket 0, so this may occur if there 00737 // are other responses waiting, handle them... 00738 try { 00739 handle_response(); 00740 recv(); 00741 } catch (ViscaException &e) { 00742 // Ignore 00743 } 00744 } 00745 00746 #ifdef TIMETRACKER_VISCA 00747 __tt->ping_end( __ttc_pantilt_get_handle ); 00748 __tt->ping_start( __ttc_pantilt_get_interpret ); 00749 #endif 00750 00751 00752 // Extract information from __ibuffer 00753 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) { 00754 unsigned short int pan_val = 0; 00755 unsigned short int tilt_val = 0; 00756 00757 pan_val |= (__ibuffer[2] & 0x0F) << 12; 00758 pan_val |= (__ibuffer[3] & 0x0F) << 8; 00759 pan_val |= (__ibuffer[4] & 0x0F) << 4; 00760 pan_val |= (__ibuffer[5] & 0x0F); 00761 00762 tilt_val |= (__ibuffer[6] & 0x0F) << 12; 00763 tilt_val |= (__ibuffer[7] & 0x0F) << 8; 00764 tilt_val |= (__ibuffer[8] & 0x0F) << 4; 00765 tilt_val |= (__ibuffer[9] & 0x0F); 00766 00767 if (pan_val < 0x8000) { 00768 // The value must be positive 00769 pan = pan_val; 00770 } else { 00771 // negative value 00772 pan = pan_val - 0xFFFF; 00773 } 00774 00775 if (tilt_val < 0x8000) { 00776 // The value must be positive 00777 tilt = tilt_val; 00778 } else { 00779 // negative value 00780 tilt = tilt_val - 0xFFFF; 00781 } 00782 00783 } else { 00784 throw ViscaException("getPanTilt(): Wrong response received"); 00785 } 00786 #ifdef TIMETRACKER_VISCA 00787 __tt->ping_end( __ttc_pantilt_get_interpret ); 00788 __tt->print_to_stdout(); 00789 #endif 00790 00791 __inquire = VISCA_RUNINQ_NONE; 00792 } 00793 00794 00795 /** Reset pan/tilt limit. */ 00796 void 00797 Visca::reset_pan_tilt_limit() 00798 { 00799 __obuffer[1] = VISCA_COMMAND; 00800 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00801 __obuffer[3] = VISCA_PT_LIMITSET; 00802 __obuffer[3] = VISCA_PT_LIMITSET_CLEAR; 00803 __obuffer[4] = VISCA_PT_LIMITSET_SET_UR; 00804 __obuffer[5] = 0x07; 00805 __obuffer[6] = 0x0F; 00806 __obuffer[7] = 0x0F; 00807 __obuffer[8] = 0x0F; 00808 __obuffer[9] = 0x07; 00809 __obuffer[10] = 0x0F; 00810 __obuffer[11] = 0x0F; 00811 __obuffer[12] = 0x0F; 00812 __obuffer_length = 12; 00813 00814 try { 00815 send_with_reply(); 00816 00817 __obuffer[4] = VISCA_PT_LIMITSET_SET_DL; 00818 00819 send_with_reply(); 00820 } catch (ViscaException &e) { 00821 e.append("resetPanTiltLimit() failed"); 00822 throw; 00823 } 00824 } 00825 00826 00827 /** Set pan tilt limit. 00828 * @param pan_left most left pan value 00829 * @param pan_right most right pan value 00830 * @param tilt_up most up tilt value 00831 * @param tilt_down most down tilt value 00832 */ 00833 void 00834 Visca::set_pan_tilt_limit(int pan_left, int pan_right, int tilt_up, int tilt_down) 00835 { 00836 try { 00837 __obuffer[1] = VISCA_COMMAND; 00838 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00839 __obuffer[3] = VISCA_PT_LIMITSET; 00840 __obuffer[3] = VISCA_PT_LIMITSET_SET; 00841 __obuffer[4] = VISCA_PT_LIMITSET_SET_UR; 00842 // pan 00843 __obuffer[5] = (pan_right & 0xf000) >> 12; 00844 __obuffer[6] = (pan_right & 0x0f00) >> 8; 00845 __obuffer[7] = (pan_right & 0x00f0) >> 4; 00846 __obuffer[8] = (pan_right & 0x000f); 00847 // tilt 00848 __obuffer[9] = (tilt_up & 0xf000) >> 12; 00849 __obuffer[10] = (tilt_up & 0x0f00) >> 8; 00850 __obuffer[11] = (tilt_up & 0x00f0) >> 4; 00851 __obuffer[12] = (tilt_up & 0x000f); 00852 00853 __obuffer_length = 12; 00854 00855 send_with_reply(); 00856 00857 __obuffer[4] = VISCA_PT_LIMITSET_SET_DL; 00858 // pan 00859 __obuffer[5] = (pan_left & 0xf000) >> 12; 00860 __obuffer[6] = (pan_left & 0x0f00) >> 8; 00861 __obuffer[7] = (pan_left & 0x00f0) >> 4; 00862 __obuffer[8] = (pan_left & 0x000f); 00863 // tilt 00864 __obuffer[9] = (tilt_down & 0xf000) >> 12; 00865 __obuffer[10] = (tilt_down & 0x0f00) >> 8; 00866 __obuffer[11] = (tilt_down & 0x00f0) >> 4; 00867 __obuffer[12] = (tilt_down & 0x000f); 00868 00869 send_with_reply(); 00870 } catch (ViscaException &e) { 00871 e.append("setPanTiltLimit() failed"); 00872 throw; 00873 } 00874 } 00875 00876 00877 /** Reset pan/tilt. */ 00878 void 00879 Visca::reset_pan_tilt() 00880 { 00881 __obuffer[1] = VISCA_COMMAND; 00882 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00883 __obuffer[3] = VISCA_PT_HOME; 00884 __obuffer_length = 3; 00885 00886 try { 00887 send_with_reply(); 00888 } catch (ViscaException &e) { 00889 e.append("resetPanTilt() failed"); 00890 throw; 00891 } 00892 } 00893 00894 00895 /** Reset zoom. */ 00896 void 00897 Visca::reset_zoom() 00898 { 00899 __obuffer[1] = VISCA_COMMAND; 00900 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00901 __obuffer[3] = VISCA_ZOOM; 00902 __obuffer[4] = VISCA_ZOOM_STOP; 00903 __obuffer_length = 4; 00904 00905 try { 00906 send_with_reply(); 00907 } catch (ViscaException &e) { 00908 e.append("resetZoom() failed"); 00909 throw; 00910 } 00911 } 00912 00913 00914 /** Set zoom speed in tele. 00915 * @param speed speed 00916 */ 00917 void 00918 Visca::set_zoom_speed_tele(unsigned int speed) 00919 { 00920 __obuffer[1] = VISCA_COMMAND; 00921 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00922 __obuffer[3] = VISCA_ZOOM; 00923 __obuffer[4] = VISCA_ZOOM_TELE_SPEED; 00924 // zoom speed 00925 __obuffer[5] = (speed & 0x000f) | 0x0020; 00926 __obuffer_length = 5; 00927 00928 try { 00929 send_with_reply(); 00930 } catch (ViscaException &e) { 00931 e.append("setZoomSpeedTele() failed"); 00932 throw; 00933 } 00934 } 00935 00936 00937 /** Set zoom speed in wide angle. 00938 * @param speed speed 00939 */ 00940 void 00941 Visca::set_zoom_speed_wide(unsigned int speed) 00942 { 00943 __obuffer[1] = VISCA_COMMAND; 00944 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00945 __obuffer[3] = VISCA_ZOOM; 00946 __obuffer[4] = VISCA_ZOOM_WIDE_SPEED; 00947 // zoom speed 00948 __obuffer[5] = (speed & 0x000f) | 0x0020; 00949 __obuffer_length = 5; 00950 00951 try { 00952 send_with_reply(); 00953 } catch (ViscaException &e) { 00954 e.append("setZoomSpeedWide() failed"); 00955 throw; 00956 } 00957 } 00958 00959 00960 /** Set zoom. 00961 * @param zoom zoom value 00962 */ 00963 void 00964 Visca::set_zoom(unsigned int zoom) 00965 { 00966 __obuffer[1] = VISCA_COMMAND; 00967 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00968 __obuffer[3] = VISCA_ZOOM_VALUE; 00969 // zoom 00970 __obuffer[4] = (zoom & 0xf000) >> 12; 00971 __obuffer[5] = (zoom & 0x0f00) >> 8; 00972 __obuffer[6] = (zoom & 0x00f0) >> 4; 00973 __obuffer[7] = (zoom & 0x000f); 00974 00975 __obuffer_length = 7; 00976 00977 try { 00978 send_with_reply(); 00979 } catch (ViscaException &e) { 00980 e.append("setZoom() failed"); 00981 throw; 00982 } 00983 } 00984 00985 00986 /** Get zoom. 00987 * @param zoom contains zoom upon return. 00988 */ 00989 void 00990 Visca::get_zoom(unsigned int *zoom) 00991 { 00992 __obuffer[1] = VISCA_INQUIRY; 00993 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00994 __obuffer[3] = VISCA_ZOOM_VALUE; 00995 __obuffer_length = 3; 00996 00997 try { 00998 send_with_reply(); 00999 } catch (ViscaException &e) { 01000 e.append("getZoom() failed"); 01001 throw; 01002 } 01003 01004 // Extract information from __ibuffer 01005 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) { 01006 unsigned short int zoom_val = 0; 01007 01008 zoom_val |= (__ibuffer[2] & 0x0F) << 12; 01009 zoom_val |= (__ibuffer[3] & 0x0F) << 8; 01010 zoom_val |= (__ibuffer[4] & 0x0F) << 4; 01011 zoom_val |= (__ibuffer[5] & 0x0F); 01012 01013 *zoom = zoom_val; 01014 } else { 01015 throw ViscaException("getZoom(): zoom inquiry failed, response code not VISCA_RESPONSE_COMPLETED"); 01016 } 01017 01018 } 01019 01020 01021 /** Enable or disable digital zoome. 01022 * @param enabled true to enable digital zoom, false to disable 01023 */ 01024 void 01025 Visca::set_zoom_digital_enabled(bool enabled) 01026 { 01027 __obuffer[1] = VISCA_COMMAND; 01028 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 01029 __obuffer[3] = VISCA_DZOOM; 01030 if (enabled) { 01031 __obuffer[4] = VISCA_DZOOM_ON; 01032 } else { 01033 __obuffer[4] = VISCA_DZOOM_OFF; 01034 } 01035 __obuffer_length = 4; 01036 01037 try { 01038 send_with_reply(); 01039 } catch (ViscaException &e) { 01040 e.append("setZoomDigitalEnabled() failed"); 01041 throw; 01042 } 01043 } 01044 01045 01046 /** Apply effect. 01047 * @param filter filter 01048 */ 01049 void 01050 Visca::apply_effect(unsigned char filter) 01051 { 01052 __obuffer[1] = VISCA_COMMAND; 01053 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 01054 __obuffer[3] = VISCA_PICTURE_EFFECT; 01055 __obuffer[4] = filter; 01056 __obuffer_length = 4; 01057 01058 try { 01059 send_with_reply(); 01060 } catch (ViscaException &e) { 01061 e.append("applyEffect() failed"); 01062 throw; 01063 } 01064 } 01065 01066 01067 /** Reset effects. */ 01068 void 01069 Visca::reset_effect() 01070 { 01071 try { 01072 apply_effect(VISCA_PICTURE_EFFECT_OFF); 01073 } catch (ViscaException &e) { 01074 e.append("resetEffect() failed"); 01075 throw; 01076 } 01077 } 01078 01079 01080 /** Apply pastel effect. */ 01081 void 01082 Visca::apply_effect_pastel() 01083 { 01084 try { 01085 apply_effect(VISCA_PICTURE_EFFECT_PASTEL); 01086 } catch (ViscaException &e) { 01087 e.append("applyEffectPastel() failed"); 01088 throw; 01089 } 01090 } 01091 01092 01093 /** Apply negative art effect. */ 01094 void 01095 Visca::apply_effect_neg_art() 01096 { 01097 try { 01098 apply_effect(VISCA_PICTURE_EFFECT_NEGATIVE); 01099 } catch (ViscaException &e) { 01100 e.append("applyEffectNegArt() failed"); 01101 throw; 01102 } 01103 } 01104 01105 01106 /** Apply sepia effect. */ 01107 void 01108 Visca::apply_effect_sepia() 01109 { 01110 try { 01111 apply_effect(VISCA_PICTURE_EFFECT_SEPIA); 01112 } catch (ViscaException &e) { 01113 e.append("applyEffectSepia() failed"); 01114 throw; 01115 } 01116 } 01117 01118 01119 /**Apply B/W effect */ 01120 void 01121 Visca::apply_effect_bnw() 01122 { 01123 try { 01124 apply_effect(VISCA_PICTURE_EFFECT_BW); 01125 } catch (ViscaException &e) { 01126 e.append("applyEffectBnW() failed"); 01127 throw; 01128 } 01129 } 01130 01131 01132 /** Apply solarize effect. */ 01133 void 01134 Visca::apply_effect_solarize() 01135 { 01136 try { 01137 apply_effect(VISCA_PICTURE_EFFECT_SOLARIZE); 01138 } catch (ViscaException &e) { 01139 e.append("applyEffectSolarize() failed"); 01140 throw; 01141 } 01142 } 01143 01144 01145 /** Apply mosaic effect. */ 01146 void 01147 Visca::apply_effect_mosaic() 01148 { 01149 try { 01150 apply_effect(VISCA_PICTURE_EFFECT_MOSAIC); 01151 } catch (ViscaException &e) { 01152 e.append("applyEffectMosaic() failed"); 01153 throw; 01154 } 01155 } 01156 01157 01158 /** Apply slim effect. */ 01159 void 01160 Visca::apply_effect_slim() 01161 { 01162 try { 01163 apply_effect(VISCA_PICTURE_EFFECT_SLIM); 01164 } catch (ViscaException &e) { 01165 e.append("applyEffectSlim() failed"); 01166 throw; 01167 } 01168 } 01169 01170 01171 /** Apply stretch effect. */ 01172 void 01173 Visca::apply_effect_stretch() 01174 { 01175 try { 01176 apply_effect(VISCA_PICTURE_EFFECT_STRETCH); 01177 } catch (ViscaException &e) { 01178 e.append("applyEffectStretch() failed"); 01179 throw; 01180 } 01181 } 01182 01183 01184 /** Get white balance mode. 01185 * @return white balance mode 01186 */ 01187 unsigned int 01188 Visca::get_white_balance_mode() 01189 { 01190 __obuffer[1] = VISCA_INQUIRY; 01191 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 01192 __obuffer[3] = VISCA_WB; 01193 __obuffer_length = 3; 01194 01195 try { 01196 send_with_reply(); 01197 } catch (ViscaException &e) { 01198 e.append("getWhiteBalanceMode() failed"); 01199 throw; 01200 } 01201 01202 while (__ibuffer[1] != VISCA_RESPONSE_COMPLETED) { 01203 // inquire return from socket 0, so this may occur if there 01204 // are other responses waiting, handle them... 01205 try { 01206 handle_response(); 01207 recv(); 01208 } catch (ViscaException &e) { 01209 e.append("getWhiteBalanceMode() failed"); 01210 throw; 01211 } 01212 } 01213 01214 // Extract information from __ibuffer 01215 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) { 01216 return __ibuffer[2]; 01217 } else { 01218 throw ViscaException("Did not get 'request completed' response"); 01219 } 01220 01221 } 01222