Fawkes API Fawkes Development Version

visca.cpp

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