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 read(__fd, __ibuffer, 1); 00468 int pos = 0; 00469 while (__ibuffer[pos] != VISCA_TERMINATOR) { 00470 read(__fd, &__ibuffer[++pos], 1); 00471 usleep(0); 00472 } 00473 __ibuffer_length = pos + 1; 00474 //printf("Visca read: "); 00475 //for (int i = 0; i < __ibuffer_length; ++i) { 00476 // printf("%02X", __ibuffer[i]); 00477 //} 00478 //printf("\n"); 00479 } 00480 00481 00482 00483 /** Handle incoming response. */ 00484 void 00485 Visca::handle_response() 00486 { 00487 unsigned int type = __ibuffer[1] & 0xF0; 00488 unsigned int socket = __ibuffer[1] & 0x0F; 00489 00490 if (socket == 0) { 00491 // This is an inquire response, do NOT handle! 00492 //throw ViscaException("handle_response(): Received an inquire response, can't handle"); 00493 return; 00494 } 00495 00496 if ( type == VISCA_RESPONSE_COMPLETED ) { 00497 // Command has been finished 00498 try { 00499 finish_nonblocking( __ibuffer[1] & 0x0F ); 00500 } catch (ViscaException &e) { 00501 // Ignore, happens sometimes without effect 00502 // e.append("handle_response() failed, could not finish non-blocking"); 00503 // throw; 00504 } 00505 } else if ( type == VISCA_RESPONSE_ERROR ) { 00506 finish_nonblocking( __ibuffer[1] & 0x0F ); 00507 //throw ViscaException("handle_response(): got an error message from camera"); 00508 } else { 00509 // ignore 00510 //ViscaException ve("Got unknown/unhandled response type"); 00511 //ve.append("Received message of type %u", type); 00512 //throw ve; 00513 } 00514 00515 } 00516 00517 00518 /** Cancel a running command. 00519 * @param socket socket that the command was send on 00520 */ 00521 void 00522 Visca::cancel_command( unsigned int socket ) 00523 { 00524 unsigned char cancel_socket = socket & 0x0000000F; 00525 00526 __obuffer[1] = VISCA_CANCEL | cancel_socket; 00527 __obuffer_length = 1; 00528 00529 try { 00530 send_with_reply(); 00531 } catch (ViscaException &e) { 00532 e.append("cancel_command() failed"); 00533 throw; 00534 } 00535 00536 if ( ((__ibuffer[1] & 0xF0) == VISCA_RESPONSE_ERROR) && 00537 ((__ibuffer[1] & 0x0F) == cancel_socket) && 00538 ((__ibuffer[2] == VISCA_ERROR_CANCELLED)) ) { 00539 return; 00540 } else { 00541 throw ViscaException("Command could not be cancelled"); 00542 } 00543 } 00544 00545 00546 /** Process incoming data. */ 00547 void 00548 Visca::process() 00549 { 00550 00551 __inquire = VISCA_RUNINQ_NONE; 00552 00553 while (data_available()) { 00554 try { 00555 recv(); 00556 handle_response(); 00557 } catch (ViscaException &e) { 00558 // Ignore this error 00559 return; 00560 } 00561 } 00562 } 00563 00564 00565 /** Set pan tilt. 00566 * @param pan pan 00567 * @param tilt tilt 00568 */ 00569 void 00570 Visca::set_pan_tilt(int pan, int tilt) 00571 { 00572 00573 // we do not to check for blocking, could not be called at 00574 // the same time if blocking... 00575 /* 00576 if ( __nonblocking_running[ NONBLOCKING_PANTILT] ) { 00577 cout << "Cancelling old setPanTilt" << endl; 00578 if (cancel_command( __nonblocking_sockets[ NONBLOCKING_PANTILT ] ) != VISCA_SUCCESS) { 00579 cout << "Visca: Could not cancel old non-blocking pan/tilt command. Not setting new pan/tilt." << endl; 00580 return VISCA_E_CANCEL; 00581 } 00582 __nonblocking_running[ NONBLOCKING_PANTILT ] = false; 00583 } 00584 */ 00585 00586 unsigned short int tilt_val = 0 + tilt; 00587 unsigned short int pan_val = 0 + pan; 00588 00589 __obuffer[1] = VISCA_COMMAND; 00590 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00591 __obuffer[3] = VISCA_PT_ABSOLUTE_POSITION; 00592 __obuffer[4] = __pan_speed; 00593 __obuffer[5] = __tilt_speed; 00594 00595 // pan 00596 __obuffer[6] = (pan_val & 0xf000) >> 12; 00597 __obuffer[7] = (pan_val & 0x0f00) >> 8; 00598 __obuffer[8] = (pan_val & 0x00f0) >> 4; 00599 __obuffer[9] = (pan_val & 0x000f); 00600 // tilt 00601 __obuffer[10] = (tilt_val & 0xf000) >> 12; 00602 __obuffer[11] = (tilt_val & 0x0f00) >> 8; 00603 __obuffer[12] = (tilt_val & 0x00f0) >> 4; 00604 __obuffer[13] = (tilt_val & 0x000f); 00605 00606 __obuffer_length = 13; 00607 00608 try { 00609 if (! __blocking) { 00610 __nonblocking_running[ NONBLOCKING_PANTILT ] = true; 00611 send_nonblocking( &(__nonblocking_sockets[ NONBLOCKING_PANTILT ]) ); 00612 } else { 00613 send_with_reply(); 00614 } 00615 } catch (ViscaException &e) { 00616 e.append("setPanTilt() failed"); 00617 throw; 00618 } 00619 } 00620 00621 00622 /** Set pan/tilt speed. 00623 * @param pan_speed a value between 0 and MAX_PAN_SPEED 00624 * @param tilt_speed a value between 0 and MAX_TILT_SPEED 00625 * @exception Exception thrown if desired pan or tilt speed is too high 00626 */ 00627 void 00628 Visca::set_pan_tilt_speed(unsigned char pan_speed, unsigned char tilt_speed) 00629 { 00630 if (pan_speed > MAX_PAN_SPEED) { 00631 throw fawkes::Exception("Pan speed too hight, max: %u des: %u", MAX_PAN_SPEED, pan_speed); 00632 } 00633 if (tilt_speed > MAX_TILT_SPEED) { 00634 throw fawkes::Exception("Tilt speed too hight, max: %u des: %u", MAX_TILT_SPEED, tilt_speed); 00635 } 00636 00637 __pan_speed = pan_speed; 00638 __tilt_speed = tilt_speed; 00639 } 00640 00641 00642 /** Get pan/tilt speed. 00643 * @param pan_speed upon return contains pan speed index 00644 * @param tilt_speed upon return contains tilt speed index 00645 */ 00646 void 00647 Visca::get_pan_tilt_speed(unsigned char &pan_speed, unsigned char &tilt_speed) 00648 { 00649 pan_speed = __pan_speed; 00650 tilt_speed = __tilt_speed; 00651 } 00652 00653 /** Initiate a pan/tilt request, but do not wait for the reply. */ 00654 void 00655 Visca::start_get_pan_tilt() 00656 { 00657 00658 if ( __inquire ) throw ViscaInquiryRunningException(); 00659 00660 __inquire = VISCA_RUNINQ_PANTILT; 00661 00662 __obuffer[1] = VISCA_INQUIRY; 00663 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00664 __obuffer[3] = VISCA_PT_POSITION_INQ; 00665 __obuffer_length = 3; 00666 00667 try { 00668 send(); 00669 } catch (ViscaException &e) { 00670 e.append("startGetPanTilt() failed"); 00671 throw; 00672 } 00673 } 00674 00675 00676 /** Get pan and tilt values. 00677 * If you used startGetPanTilt() to initiate the query the result is 00678 * received and returned, otherwise a request is sent and the method blocks 00679 * until the answer has been received. 00680 * @param pan contains pan upon return 00681 * @param tilt contains tilt upon return 00682 */ 00683 void 00684 Visca::get_pan_tilt(int &pan, int &tilt) 00685 { 00686 00687 if ( __inquire ) { 00688 if ( __inquire != VISCA_RUNINQ_PANTILT ) { 00689 throw ViscaException("Inquiry running, but it is not a pan/tilt inquiry"); 00690 } else { 00691 #ifdef TIMETRACKER_VISCA 00692 __tt->ping_start( __ttc_pantilt_get_read ); 00693 #endif 00694 try { 00695 recv(); 00696 } catch (ViscaException &e) { 00697 // Ignore 00698 } 00699 #ifdef TIMETRACKER_VISCA 00700 __tt->ping_end( __ttc_pantilt_get_read ); 00701 #endif 00702 } 00703 } else { 00704 00705 __obuffer[1] = VISCA_INQUIRY; 00706 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00707 __obuffer[3] = VISCA_PT_POSITION_INQ; 00708 __obuffer_length = 3; 00709 00710 try { 00711 #ifdef TIMETRACKER_VISCA 00712 __tt->ping_start( __ttc_pantilt_get_send ); 00713 send(); 00714 __tt->ping_end( __ttc_pantilt_get_send ); 00715 __tt->ping_start( __ttc_pantilt_get_read ); 00716 recv(); 00717 __tt->ping_end( __ttc_pantilt_get_read ); 00718 #else 00719 send_with_reply(); 00720 #endif 00721 } catch (ViscaException &e) { 00722 // Ignore 00723 } 00724 } 00725 00726 #ifdef TIMETRACKER_VISCA 00727 __tt->ping_start( __ttc_pantilt_get_handle ); 00728 #endif 00729 00730 while (__ibuffer[1] != VISCA_RESPONSE_COMPLETED) { 00731 // inquire return from socket 0, so this may occur if there 00732 // are other responses waiting, handle them... 00733 try { 00734 handle_response(); 00735 recv(); 00736 } catch (ViscaException &e) { 00737 // Ignore 00738 } 00739 } 00740 00741 #ifdef TIMETRACKER_VISCA 00742 __tt->ping_end( __ttc_pantilt_get_handle ); 00743 __tt->ping_start( __ttc_pantilt_get_interpret ); 00744 #endif 00745 00746 00747 // Extract information from __ibuffer 00748 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) { 00749 unsigned short int pan_val = 0; 00750 unsigned short int tilt_val = 0; 00751 00752 pan_val |= (__ibuffer[2] & 0x0F) << 12; 00753 pan_val |= (__ibuffer[3] & 0x0F) << 8; 00754 pan_val |= (__ibuffer[4] & 0x0F) << 4; 00755 pan_val |= (__ibuffer[5] & 0x0F); 00756 00757 tilt_val |= (__ibuffer[6] & 0x0F) << 12; 00758 tilt_val |= (__ibuffer[7] & 0x0F) << 8; 00759 tilt_val |= (__ibuffer[8] & 0x0F) << 4; 00760 tilt_val |= (__ibuffer[9] & 0x0F); 00761 00762 if (pan_val < 0x8000) { 00763 // The value must be positive 00764 pan = pan_val; 00765 } else { 00766 // negative value 00767 pan = pan_val - 0xFFFF; 00768 } 00769 00770 if (tilt_val < 0x8000) { 00771 // The value must be positive 00772 tilt = tilt_val; 00773 } else { 00774 // negative value 00775 tilt = tilt_val - 0xFFFF; 00776 } 00777 00778 } else { 00779 throw ViscaException("getPanTilt(): Wrong response received"); 00780 } 00781 #ifdef TIMETRACKER_VISCA 00782 __tt->ping_end( __ttc_pantilt_get_interpret ); 00783 __tt->print_to_stdout(); 00784 #endif 00785 00786 __inquire = VISCA_RUNINQ_NONE; 00787 } 00788 00789 00790 /** Reset pan/tilt limit. */ 00791 void 00792 Visca::reset_pan_tilt_limit() 00793 { 00794 __obuffer[1] = VISCA_COMMAND; 00795 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00796 __obuffer[3] = VISCA_PT_LIMITSET; 00797 __obuffer[3] = VISCA_PT_LIMITSET_CLEAR; 00798 __obuffer[4] = VISCA_PT_LIMITSET_SET_UR; 00799 __obuffer[5] = 0x07; 00800 __obuffer[6] = 0x0F; 00801 __obuffer[7] = 0x0F; 00802 __obuffer[8] = 0x0F; 00803 __obuffer[9] = 0x07; 00804 __obuffer[10] = 0x0F; 00805 __obuffer[11] = 0x0F; 00806 __obuffer[12] = 0x0F; 00807 __obuffer_length = 12; 00808 00809 try { 00810 send_with_reply(); 00811 00812 __obuffer[4] = VISCA_PT_LIMITSET_SET_DL; 00813 00814 send_with_reply(); 00815 } catch (ViscaException &e) { 00816 e.append("resetPanTiltLimit() failed"); 00817 throw; 00818 } 00819 } 00820 00821 00822 /** Set pan tilt limit. 00823 * @param pan_left most left pan value 00824 * @param pan_right most right pan value 00825 * @param tilt_up most up tilt value 00826 * @param tilt_down most down tilt value 00827 */ 00828 void 00829 Visca::set_pan_tilt_limit(int pan_left, int pan_right, int tilt_up, int tilt_down) 00830 { 00831 try { 00832 __obuffer[1] = VISCA_COMMAND; 00833 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00834 __obuffer[3] = VISCA_PT_LIMITSET; 00835 __obuffer[3] = VISCA_PT_LIMITSET_SET; 00836 __obuffer[4] = VISCA_PT_LIMITSET_SET_UR; 00837 // pan 00838 __obuffer[5] = (pan_right & 0xf000) >> 12; 00839 __obuffer[6] = (pan_right & 0x0f00) >> 8; 00840 __obuffer[7] = (pan_right & 0x00f0) >> 4; 00841 __obuffer[8] = (pan_right & 0x000f); 00842 // tilt 00843 __obuffer[9] = (tilt_up & 0xf000) >> 12; 00844 __obuffer[10] = (tilt_up & 0x0f00) >> 8; 00845 __obuffer[11] = (tilt_up & 0x00f0) >> 4; 00846 __obuffer[12] = (tilt_up & 0x000f); 00847 00848 __obuffer_length = 12; 00849 00850 send_with_reply(); 00851 00852 __obuffer[4] = VISCA_PT_LIMITSET_SET_DL; 00853 // pan 00854 __obuffer[5] = (pan_left & 0xf000) >> 12; 00855 __obuffer[6] = (pan_left & 0x0f00) >> 8; 00856 __obuffer[7] = (pan_left & 0x00f0) >> 4; 00857 __obuffer[8] = (pan_left & 0x000f); 00858 // tilt 00859 __obuffer[9] = (tilt_down & 0xf000) >> 12; 00860 __obuffer[10] = (tilt_down & 0x0f00) >> 8; 00861 __obuffer[11] = (tilt_down & 0x00f0) >> 4; 00862 __obuffer[12] = (tilt_down & 0x000f); 00863 00864 send_with_reply(); 00865 } catch (ViscaException &e) { 00866 e.append("setPanTiltLimit() failed"); 00867 throw; 00868 } 00869 } 00870 00871 00872 /** Reset pan/tilt. */ 00873 void 00874 Visca::reset_pan_tilt() 00875 { 00876 __obuffer[1] = VISCA_COMMAND; 00877 __obuffer[2] = VISCA_CATEGORY_PAN_TILTER; 00878 __obuffer[3] = VISCA_PT_HOME; 00879 __obuffer_length = 3; 00880 00881 try { 00882 send_with_reply(); 00883 } catch (ViscaException &e) { 00884 e.append("resetPanTilt() failed"); 00885 throw; 00886 } 00887 } 00888 00889 00890 /** Reset zoom. */ 00891 void 00892 Visca::reset_zoom() 00893 { 00894 __obuffer[1] = VISCA_COMMAND; 00895 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00896 __obuffer[3] = VISCA_ZOOM; 00897 __obuffer[4] = VISCA_ZOOM_STOP; 00898 __obuffer_length = 4; 00899 00900 try { 00901 send_with_reply(); 00902 } catch (ViscaException &e) { 00903 e.append("resetZoom() failed"); 00904 throw; 00905 } 00906 } 00907 00908 00909 /** Set zoom speed in tele. 00910 * @param speed speed 00911 */ 00912 void 00913 Visca::set_zoom_speed_tele(unsigned int speed) 00914 { 00915 __obuffer[1] = VISCA_COMMAND; 00916 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00917 __obuffer[3] = VISCA_ZOOM; 00918 __obuffer[4] = VISCA_ZOOM_TELE_SPEED; 00919 // zoom speed 00920 __obuffer[5] = (speed & 0x000f) | 0x0020; 00921 __obuffer_length = 5; 00922 00923 try { 00924 send_with_reply(); 00925 } catch (ViscaException &e) { 00926 e.append("setZoomSpeedTele() failed"); 00927 throw; 00928 } 00929 } 00930 00931 00932 /** Set zoom speed in wide angle. 00933 * @param speed speed 00934 */ 00935 void 00936 Visca::set_zoom_speed_wide(unsigned int speed) 00937 { 00938 __obuffer[1] = VISCA_COMMAND; 00939 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00940 __obuffer[3] = VISCA_ZOOM; 00941 __obuffer[4] = VISCA_ZOOM_WIDE_SPEED; 00942 // zoom speed 00943 __obuffer[5] = (speed & 0x000f) | 0x0020; 00944 __obuffer_length = 5; 00945 00946 try { 00947 send_with_reply(); 00948 } catch (ViscaException &e) { 00949 e.append("setZoomSpeedWide() failed"); 00950 throw; 00951 } 00952 } 00953 00954 00955 /** Set zoom. 00956 * @param zoom zoom value 00957 */ 00958 void 00959 Visca::set_zoom(unsigned int zoom) 00960 { 00961 __obuffer[1] = VISCA_COMMAND; 00962 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00963 __obuffer[3] = VISCA_ZOOM_VALUE; 00964 // zoom 00965 __obuffer[4] = (zoom & 0xf000) >> 12; 00966 __obuffer[5] = (zoom & 0x0f00) >> 8; 00967 __obuffer[6] = (zoom & 0x00f0) >> 4; 00968 __obuffer[7] = (zoom & 0x000f); 00969 00970 __obuffer_length = 7; 00971 00972 try { 00973 send_with_reply(); 00974 } catch (ViscaException &e) { 00975 e.append("setZoom() failed"); 00976 throw; 00977 } 00978 } 00979 00980 00981 /** Get zoom. 00982 * @param zoom contains zoom upon return. 00983 */ 00984 void 00985 Visca::get_zoom(unsigned int *zoom) 00986 { 00987 __obuffer[1] = VISCA_INQUIRY; 00988 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 00989 __obuffer[3] = VISCA_ZOOM_VALUE; 00990 __obuffer_length = 3; 00991 00992 try { 00993 send_with_reply(); 00994 } catch (ViscaException &e) { 00995 e.append("getZoom() failed"); 00996 throw; 00997 } 00998 00999 // Extract information from __ibuffer 01000 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) { 01001 unsigned short int zoom_val = 0; 01002 01003 zoom_val |= (__ibuffer[2] & 0x0F) << 12; 01004 zoom_val |= (__ibuffer[3] & 0x0F) << 8; 01005 zoom_val |= (__ibuffer[4] & 0x0F) << 4; 01006 zoom_val |= (__ibuffer[5] & 0x0F); 01007 01008 *zoom = zoom_val; 01009 } else { 01010 throw ViscaException("getZoom(): zoom inquiry failed, response code not VISCA_RESPONSE_COMPLETED"); 01011 } 01012 01013 } 01014 01015 01016 /** Enable or disable digital zoome. 01017 * @param enabled true to enable digital zoom, false to disable 01018 */ 01019 void 01020 Visca::set_zoom_digital_enabled(bool enabled) 01021 { 01022 __obuffer[1] = VISCA_COMMAND; 01023 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 01024 __obuffer[3] = VISCA_DZOOM; 01025 if (enabled) { 01026 __obuffer[4] = VISCA_DZOOM_ON; 01027 } else { 01028 __obuffer[4] = VISCA_DZOOM_OFF; 01029 } 01030 __obuffer_length = 4; 01031 01032 try { 01033 send_with_reply(); 01034 } catch (ViscaException &e) { 01035 e.append("setZoomDigitalEnabled() failed"); 01036 throw; 01037 } 01038 } 01039 01040 01041 /** Apply effect. 01042 * @param filter filter 01043 */ 01044 void 01045 Visca::apply_effect(unsigned char filter) 01046 { 01047 __obuffer[1] = VISCA_COMMAND; 01048 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 01049 __obuffer[3] = VISCA_PICTURE_EFFECT; 01050 __obuffer[4] = filter; 01051 __obuffer_length = 4; 01052 01053 try { 01054 send_with_reply(); 01055 } catch (ViscaException &e) { 01056 e.append("applyEffect() failed"); 01057 throw; 01058 } 01059 } 01060 01061 01062 /** Reset effects. */ 01063 void 01064 Visca::reset_effect() 01065 { 01066 try { 01067 apply_effect(VISCA_PICTURE_EFFECT_OFF); 01068 } catch (ViscaException &e) { 01069 e.append("resetEffect() failed"); 01070 throw; 01071 } 01072 } 01073 01074 01075 /** Apply pastel effect. */ 01076 void 01077 Visca::apply_effect_pastel() 01078 { 01079 try { 01080 apply_effect(VISCA_PICTURE_EFFECT_PASTEL); 01081 } catch (ViscaException &e) { 01082 e.append("applyEffectPastel() failed"); 01083 throw; 01084 } 01085 } 01086 01087 01088 /** Apply negative art effect. */ 01089 void 01090 Visca::apply_effect_neg_art() 01091 { 01092 try { 01093 apply_effect(VISCA_PICTURE_EFFECT_NEGATIVE); 01094 } catch (ViscaException &e) { 01095 e.append("applyEffectNegArt() failed"); 01096 throw; 01097 } 01098 } 01099 01100 01101 /** Apply sepia effect. */ 01102 void 01103 Visca::apply_effect_sepia() 01104 { 01105 try { 01106 apply_effect(VISCA_PICTURE_EFFECT_SEPIA); 01107 } catch (ViscaException &e) { 01108 e.append("applyEffectSepia() failed"); 01109 throw; 01110 } 01111 } 01112 01113 01114 /**Apply B/W effect */ 01115 void 01116 Visca::apply_effect_bnw() 01117 { 01118 try { 01119 apply_effect(VISCA_PICTURE_EFFECT_BW); 01120 } catch (ViscaException &e) { 01121 e.append("applyEffectBnW() failed"); 01122 throw; 01123 } 01124 } 01125 01126 01127 /** Apply solarize effect. */ 01128 void 01129 Visca::apply_effect_solarize() 01130 { 01131 try { 01132 apply_effect(VISCA_PICTURE_EFFECT_SOLARIZE); 01133 } catch (ViscaException &e) { 01134 e.append("applyEffectSolarize() failed"); 01135 throw; 01136 } 01137 } 01138 01139 01140 /** Apply mosaic effect. */ 01141 void 01142 Visca::apply_effect_mosaic() 01143 { 01144 try { 01145 apply_effect(VISCA_PICTURE_EFFECT_MOSAIC); 01146 } catch (ViscaException &e) { 01147 e.append("applyEffectMosaic() failed"); 01148 throw; 01149 } 01150 } 01151 01152 01153 /** Apply slim effect. */ 01154 void 01155 Visca::apply_effect_slim() 01156 { 01157 try { 01158 apply_effect(VISCA_PICTURE_EFFECT_SLIM); 01159 } catch (ViscaException &e) { 01160 e.append("applyEffectSlim() failed"); 01161 throw; 01162 } 01163 } 01164 01165 01166 /** Apply stretch effect. */ 01167 void 01168 Visca::apply_effect_stretch() 01169 { 01170 try { 01171 apply_effect(VISCA_PICTURE_EFFECT_STRETCH); 01172 } catch (ViscaException &e) { 01173 e.append("applyEffectStretch() failed"); 01174 throw; 01175 } 01176 } 01177 01178 01179 /** Get white balance mode. 01180 * @return white balance mode 01181 */ 01182 unsigned int 01183 Visca::get_white_balance_mode() 01184 { 01185 __obuffer[1] = VISCA_INQUIRY; 01186 __obuffer[2] = VISCA_CATEGORY_CAMERA1; 01187 __obuffer[3] = VISCA_WB; 01188 __obuffer_length = 3; 01189 01190 try { 01191 send_with_reply(); 01192 } catch (ViscaException &e) { 01193 e.append("getWhiteBalanceMode() failed"); 01194 throw; 01195 } 01196 01197 while (__ibuffer[1] != VISCA_RESPONSE_COMPLETED) { 01198 // inquire return from socket 0, so this may occur if there 01199 // are other responses waiting, handle them... 01200 try { 01201 handle_response(); 01202 recv(); 01203 } catch (ViscaException &e) { 01204 e.append("getWhiteBalanceMode() failed"); 01205 throw; 01206 } 01207 } 01208 01209 // Extract information from __ibuffer 01210 if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) { 01211 return __ibuffer[2]; 01212 } else { 01213 throw ViscaException("Did not get 'request completed' response"); 01214 } 01215 01216 } 01217