visca.cpp

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, &param) == -1) {
00149     ViscaException ve("Getting the port parameters failed", errno);
00150     ::close(__fd);
00151     throw ve;
00152   }
00153 
00154   cfsetospeed(&param, B9600);
00155   cfsetispeed(&param, 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, &param) != 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 

Generated on Tue Feb 22 13:31:15 2011 for Fawkes API by  doxygen 1.4.7