Fawkes API  Fawkes Development Version
visca.cpp
1 
2 /***************************************************************************
3  * visca.cpp - Controller for Visca cams
4  *
5  * Created: Wed Jun 08 12:08:17 2005 (FireVision)
6  * Copyright 2005-2009 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include "visca.h"
25 
26 #include <core/exceptions/system.h>
27 
28 #include <sys/ioctl.h>
29 #include <termios.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <cerrno>
33 #include <cstring>
34 #include <cstdlib>
35 
36 /** @class ViscaException "visca.h"
37  * Visca exception.
38  */
39 
40 /** Constructor.
41  * @param msg message of exception.
42  */
44  : Exception(msg)
45 {}
46 
47 
48 /** Constructor with errno.
49  * @param msg message prefix
50  * @param _errno errno for additional error information.
51  */
52 ViscaException::ViscaException(const char *msg, const int _errno)
53  : Exception(_errno, msg)
54 {}
55 
56 /** @class ViscaInquiryRunningException "visca.h"
57  * Visca inquire running exception.
58  */
59 
60 /** Constructor. */
62  : ViscaException("Inquiry already running")
63 {}
64 
65 
66 /** Automatic white balance. */
67 const unsigned int Visca::VISCA_WHITEBLANCE_AUTO = VISCA_WB_AUTO;
68 /** Indoor white balance preset. */
69 const unsigned int Visca::VISCA_WHITEBALANCE_INDOOR = VISCA_WB_INDOOR;
70 /** Outdoor white balance preset. */
71 const unsigned int Visca::VISCA_WHITEBALANCE_OUTDOOR = VISCA_WB_OUTDOOR;
72 /** One push white balance preset. */
73 const unsigned int Visca::VISCA_WHITEBALANCE_ONE_PUSH = VISCA_WB_ONE_PUSH;
74 /** ATW white balance preset. */
75 const unsigned int Visca::VISCA_WHITEBALANCE_ATW = VISCA_WB_ATW;
76 /** Manual white balance. */
77 const unsigned int Visca::VISCA_WHITEBALANCE_MANUAL = VISCA_WB_MANUAL;
78 
79 /** Non-blocking pan/tilt item. */
80 const unsigned int Visca::NONBLOCKING_PANTILT = 0;
81 /** Non-blocking zoom item. */
82 const unsigned int Visca::NONBLOCKING_ZOOM = 1;
83 /** Number of non-blocking items. */
84 const unsigned int Visca::NONBLOCKING_NUM = 2;
85 
86 /** Number of non-blocking items. */
87 const unsigned int Visca::MAX_PAN_SPEED = 0x18;
88 
89 /** Number of non-blocking items. */
90 const unsigned int Visca::MAX_TILT_SPEED = 0x14;
91 
92 
93 /** @class Visca "visca.h"
94  * Visca control protocol implementation over a serial line.
95  * @author Tim Niemueller
96  */
97 
98 /** Constructor.
99  * @param device_file serial device file (e.g. /dev/ttyUSB0)
100  * @param def_timeout_ms default timeout for read operations applied if no explicit
101  * timeout is given.
102  * @param blocking if true, setting the pan/tilt values will only cause sending the
103  * request, you need to call process() when there is time to process and handle
104  * incoming messages.
105  */
106 Visca::Visca(const char *device_file, unsigned int def_timeout_ms, bool blocking)
107 {
108  __inquire = VISCA_RUNINQ_NONE;
109  __device_file = strdup(device_file);
110  __blocking = blocking;
111  __opened = false;
112  __default_timeout_ms = def_timeout_ms;
113  __pan_speed = MAX_PAN_SPEED;
114  __tilt_speed = MAX_TILT_SPEED;
115 
116  for (unsigned int i = 0; i < NONBLOCKING_NUM; ++i) {
117  __nonblocking_sockets[i] = 0;
118  __nonblocking_running[i] = false;
119  }
120 
121  open();
122 
123  set_address();
124  clear();
125 }
126 
127 
128 /** Destructor. */
130 {
131  close();
132  free(__device_file);
133 }
134 
135 
136 /** Open serial port. */
137 void
139 
140  struct termios param;
141 
142  __fd = ::open(__device_file, O_RDWR);
143  if (! __fd) {
144  throw ViscaException("Cannot open device", errno);
145  }
146 
147  if (tcgetattr(__fd, &param) == -1) {
148  ViscaException ve("Getting the port parameters failed", errno);
149  ::close(__fd);
150  throw ve;
151  }
152 
153  cfsetospeed(&param, B9600);
154  cfsetispeed(&param, B9600);
155 
156  param.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
157  param.c_cflag |= CREAD;
158  param.c_cflag |= CLOCAL;
159  //param.c_cflag |= CRTSCTS;
160 
161  param.c_cc[VMIN] = 1;
162  param.c_cc[VTIME] = 0;
163 
164  param.c_iflag |= IGNBRK;
165  param.c_iflag &= ~PARMRK;
166  param.c_iflag &= ~ISTRIP;
167  param.c_iflag &= ~INLCR;
168  param.c_iflag &= ~IGNCR;
169  param.c_iflag &= ~ICRNL;
170  param.c_iflag &= ~IXON;
171  param.c_iflag &= ~IXOFF;
172 
173  param.c_lflag &= ~ECHO;
174 
175  // hand shake
176  param.c_lflag |= IEXTEN;
177  param.c_oflag &= ~OPOST; //enable raw output
178 
179  //tcflow (__fd, TCOON);
180  //tcflow (__fd, TCION);
181 
182  // number of data bits: 8
183  param.c_cflag &= ~CS5 & ~CS6 & ~CS7 & ~CS8;
184 
185  param.c_cflag |= CS8;
186 
187  // parity: none
188  param.c_cflag &=~(PARENB & PARODD);
189 
190  // stop bits: 1
191  param.c_cflag &= ~CSTOPB;
192 
193  if (tcsetattr(__fd, TCSANOW, &param) != 0) {
194  ViscaException ve("Setting the port parameters failed", errno);
195  ::close(__fd);
196  throw ve;
197  }
198 
199  __opened = true;
200  // Choose first camera by default
201  __sender = VISCA_BUS_0;
202  __recipient = VISCA_BUS_1;
203 
204 #ifdef TIMETRACKER_VISCA
205  __tt = new TimeTracker();
206  __ttc_pantilt_get_send = __tt->addClass("getPanTilt: send");
207  __ttc_pantilt_get_read = __tt->addClass("getPanTilt: read");
208  __ttc_pantilt_get_handle = __tt->addClass("getPanTilt: handling responses");
209  __ttc_pantilt_get_interpret = __tt->addClass("getPanTilt: interpreting");
210 #endif
211 }
212 
213 
214 /** Close port. */
215 void
217 {
218  if (__opened) {
219  __opened = false;
220  ::close(__fd);
221  }
222 }
223 
224 
225 /** Set addresses of cameras. */
226 void
228 {
229  unsigned char recp_backup = __recipient;
230  __recipient = VISCA_BUS_BROADCAST;
231  __obuffer[1] = 0x30;
232  __obuffer[2] = 0x01;
233  __obuffer_length = 2;
234 
235  try {
236  send();
237  recv();
238  } catch (ViscaException &e) {
239  __recipient = recp_backup;
240  throw;
241  }
242 
243  __recipient = recp_backup;
244 }
245 
246 
247 /** Clear command buffers. */
248 void
250 {
251  if (!__opened) throw ViscaException("Serial port not open");
252 
253  __obuffer[1] = 0x01;
254  __obuffer[2] = 0x00;
255  __obuffer[3] = 0x01;
256  __obuffer_length = 3;
257 
258  try {
259  send();
260  recv();
261  } catch (ViscaException &e) {
262  e.append("clear() failed");
263  throw;
264  }
265 }
266 
267 
268 /** Send outbound queue. */
269 void
271 {
272  if (!__opened) throw ViscaException("Serial port not open");
273 
274  // Set first bit to 1
275  __obuffer[0] = 0x80;
276  __obuffer[0] |= (__sender << 4);
277  __obuffer[0] |= __recipient;
278 
279  __obuffer[++__obuffer_length] = VISCA_TERMINATOR;
280  ++__obuffer_length;
281 
282  int written = write(__fd, __obuffer, __obuffer_length);
283  //printf("Visca sent: ");
284  //for (int i = 0; i < __obuffer_length; ++i) {
285  // printf("%02X", __obuffer[i]);
286  //}
287  //printf("\n");
288  if (written < __obuffer_length) {
289  throw ViscaException("Not all bytes send");
290  }
291 }
292 
293 
294 /** Check data availability.
295  * @return true if data is available, false otherwise
296  */
297 bool
299 {
300  int num_bytes = 0;
301  ioctl(__fd, FIONREAD, &num_bytes);
302  return (num_bytes > 0);
303 }
304 
305 
306 /** Receive data.
307  * @param timeout_ms read timeout in miliseconds
308  */
309 void
310 Visca::recv(unsigned int timeout_ms)
311 {
312  if (timeout_ms == 0xFFFFFFFF) timeout_ms = __default_timeout_ms;
313  try {
314  recv_packet(timeout_ms);
315  } catch (ViscaException &e) {
316  e.append("Receiving failed, recv_packet() call failed");
317  throw;
318  }
319 
320  // Get type of message
321  unsigned char type = __ibuffer[1] & 0xF0;
322  while (type == VISCA_RESPONSE_ACK) {
323  try {
324  recv_packet(timeout_ms);
325  } catch (ViscaException &e) {
326  e.append("Receiving failed, recv_packet() call 2 failed");
327  throw;
328  }
329  type = __ibuffer[1] & 0xF0;
330  }
331 
332  switch (type) {
333  case VISCA_RESPONSE_CLEAR:
334  case VISCA_RESPONSE_ADDRESS:
335  case VISCA_RESPONSE_COMPLETED:
336  case VISCA_RESPONSE_ERROR:
337  break;
338  default:
339  throw fawkes::Exception("Receiving failed, unexpected packet type %u received",
340  type);
341  }
342 }
343 
344 
345 /** Receive ACK packet.
346  * @param socket contains the socket that the ACK was received on upon return
347  */
348 void
349 Visca::recv_ack(unsigned int *socket)
350 {
351  try {
352  recv_packet(__default_timeout_ms);
353  } catch (ViscaException &e) {
354  throw ViscaException("recv_ack(): recv_packet() failed");
355  }
356 
357  // Get type of message
358  unsigned char type = __ibuffer[1] & 0xF0;
359  while (type != VISCA_RESPONSE_ACK) {
360 
361  try {
362  handle_response();
363  recv_packet(__default_timeout_ms);
364  } catch (ViscaException &e) {
365  e.append("Handling message of type %u failed", type);
366  throw;
367  }
368  type = __ibuffer[1] & 0xF0;
369  }
370 
371  // Got an ack now
372  if (socket != NULL) {
373  *socket = __ibuffer[1] & 0x0F;
374  }
375 
376 }
377 
378 
379 /** Send non-blocking.
380  * Does a non-blocking send.
381  * @param socket the socket that was used to send the request.
382  */
383 void
384 Visca::send_nonblocking(unsigned int *socket)
385 {
386  try {
387  send();
388  recv_ack(socket);
389  } catch (ViscaException &e) {
390  e.append("Non-blocking send failed!");
391  throw;
392  }
393 }
394 
395 
396 /** Finish a non-blocking operation.
397  * @param socket socket that the non-blocking operation was sent to
398  */
399 void
400 Visca::finish_nonblocking( unsigned int socket )
401 {
402  for (unsigned int i = 0; i < NONBLOCKING_NUM; ++i) {
403  if (__nonblocking_sockets[i] == socket) {
404  __nonblocking_sockets[i] = 0;
405  __nonblocking_running[i] = false;
406  return;
407  }
408  }
409 
410  throw ViscaException("finish_nonblocking() failed: socket not found");
411 }
412 
413 
414 /** Check if a non-blocking operation has been finished.
415  * @param item the non-blocking item to check
416  * @return true if the non-blocking operation has been finished, false otherwise
417  */
418 bool
419 Visca::is_nonblocking_finished(unsigned int item) const
420 {
421  if (item >= NONBLOCKING_NUM) {
422  throw ViscaException("Invalid item number");
423  }
424  return ! __nonblocking_running[item];
425 }
426 
427 
428 /** Send and wait for reply, blocking. */
429 void
431 {
432  try {
433  send();
434 
435  if (__obuffer[1] == VISCA_COMMAND) {
436  // do not catch timeouts here, we expect them to be on time
437  recv_ack();
438  bool rcvd = false;
439 
440  while (! rcvd) {
441  try {
442  recv();
443  rcvd = true;
444  } catch (fawkes::TimeoutException &e) {} // ignored
445  }
446  } else {
447  // timeout applies to inquiries
448  recv();
449  }
450  } catch (ViscaException &e) {
451  e.append("Sending with reply failed");
452  throw;
453  }
454 }
455 
456 
457 /** Receive a packet.
458  * @param timeout_ms read timeout in miliseconds
459  */
460 void
461 Visca::recv_packet(unsigned int timeout_ms)
462 {
463  // wait for message
464  timeval timeout = {0, (suseconds_t)timeout_ms * 1000};
465 
466  fd_set read_fds;
467  FD_ZERO(&read_fds);
468  FD_SET(__fd, &read_fds);
469 
470  int rv = 0;
471  rv = select(__fd + 1, &read_fds, NULL, NULL, &timeout);
472 
473  if ( rv == -1 ) {
474  throw fawkes::Exception(errno, "Select on FD failed");
475  } else if ( rv == 0 ) {
476  throw fawkes::TimeoutException("Timeout reached while waiting for incoming data");
477  }
478 
479  // get octets one by one
480  if (read(__fd, __ibuffer, 1) != 1) {
481  throw fawkes::Exception(errno, "Visca reading packet byte failed (1)");
482  }
483 
484  size_t pos = 0;
485  while (__ibuffer[pos] != VISCA_TERMINATOR && (pos < sizeof(__ibuffer)-1)) {
486  if (read(__fd, &__ibuffer[++pos], 1) != 1) {
487 
488 
489  throw fawkes::Exception(errno, "Visca reading packet byte failed (2)");
490  }
491  usleep(0);
492  }
493  __ibuffer_length = pos + 1;
494  //printf("Visca read: ");
495  //for (int i = 0; i < __ibuffer_length; ++i) {
496  // printf("%02X", __ibuffer[i]);
497  //}
498  //printf("\n");
499 }
500 
501 
502 
503 /** Handle incoming response. */
504 void
505 Visca::handle_response()
506 {
507  unsigned int type = __ibuffer[1] & 0xF0;
508  unsigned int socket = __ibuffer[1] & 0x0F;
509 
510  if (socket == 0) {
511  // This is an inquire response, do NOT handle!
512  //throw ViscaException("handle_response(): Received an inquire response, can't handle");
513  return;
514  }
515 
516  if ( type == VISCA_RESPONSE_COMPLETED ) {
517  // Command has been finished
518  try {
519  finish_nonblocking( __ibuffer[1] & 0x0F );
520  } catch (ViscaException &e) {
521  // Ignore, happens sometimes without effect
522  // e.append("handle_response() failed, could not finish non-blocking");
523  // throw;
524  }
525  } else if ( type == VISCA_RESPONSE_ERROR ) {
526  finish_nonblocking( __ibuffer[1] & 0x0F );
527  //throw ViscaException("handle_response(): got an error message from camera");
528  } else {
529  // ignore
530  //ViscaException ve("Got unknown/unhandled response type");
531  //ve.append("Received message of type %u", type);
532  //throw ve;
533  }
534 
535 }
536 
537 
538 /** Cancel a running command.
539  * @param socket socket that the command was send on
540  */
541 void
542 Visca::cancel_command( unsigned int socket )
543 {
544  unsigned char cancel_socket = socket & 0x0000000F;
545 
546  __obuffer[1] = VISCA_CANCEL | cancel_socket;
547  __obuffer_length = 1;
548 
549  try {
550  send_with_reply();
551  } catch (ViscaException &e) {
552  e.append("cancel_command() failed");
553  throw;
554  }
555 
556  if ( ((__ibuffer[1] & 0xF0) == VISCA_RESPONSE_ERROR) &&
557  ((__ibuffer[1] & 0x0F) == cancel_socket) &&
558  ((__ibuffer[2] == VISCA_ERROR_CANCELLED)) ) {
559  return;
560  } else {
561  throw ViscaException("Command could not be cancelled");
562  }
563 }
564 
565 
566 /** Process incoming data. */
567 void
569 {
570 
571  __inquire = VISCA_RUNINQ_NONE;
572 
573  while (data_available()) {
574  try {
575  recv();
576  handle_response();
577  } catch (ViscaException &e) {
578  // Ignore this error
579  return;
580  }
581  }
582 }
583 
584 
585 /** Set power state.
586  * @param powered true to power on, false to power off
587  */
588 void
589 Visca::set_power(bool powered)
590 {
591  __obuffer[1] = VISCA_COMMAND;
592  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
593  __obuffer[3] = VISCA_POWER;
594  __obuffer[4] = powered ? VISCA_POWER_ON : VISCA_POWER_OFF;
595  __obuffer_length = 4;
596 
597  try {
598  send_with_reply();
599  } catch (ViscaException &e) {
600  e.append("set_power() failed");
601  throw;
602  }
603 }
604 
605 
606 /** Check if camera is powered
607  * @return true if camera is powered, false otherwise
608  */
609 bool
611 {
612  __obuffer[1] = VISCA_INQUIRY;
613  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
614  __obuffer[3] = VISCA_POWER;
615  __obuffer_length = 3;
616 
617  try {
618  send_with_reply();
619  } catch (ViscaException &e) {
620  e.append("Failed to get power data");
621  throw;
622  }
623 
624  // Extract information from __ibuffer
625  if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
626  return (__ibuffer[2] == VISCA_POWER_ON);
627  } else {
628  throw ViscaException("is_powered(): inquiry failed, response code not VISCA_RESPONSE_COMPLETED");
629  }
630 }
631 
632 
633 /** Set pan tilt.
634  * @param pan pan
635  * @param tilt tilt
636  */
637 void
638 Visca::set_pan_tilt(int pan, int tilt)
639 {
640 
641  // we do not to check for blocking, could not be called at
642  // the same time if blocking...
643  /*
644  if ( __nonblocking_running[ NONBLOCKING_PANTILT] ) {
645  cout << "Cancelling old setPanTilt" << endl;
646  if (cancel_command( __nonblocking_sockets[ NONBLOCKING_PANTILT ] ) != VISCA_SUCCESS) {
647  cout << "Visca: Could not cancel old non-blocking pan/tilt command. Not setting new pan/tilt." << endl;
648  return VISCA_E_CANCEL;
649  }
650  __nonblocking_running[ NONBLOCKING_PANTILT ] = false;
651  }
652  */
653 
654  unsigned short int tilt_val = 0 + tilt;
655  unsigned short int pan_val = 0 + pan;
656 
657  __obuffer[1] = VISCA_COMMAND;
658  __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
659  __obuffer[3] = VISCA_PT_ABSOLUTE_POSITION;
660  __obuffer[4] = __pan_speed;
661  __obuffer[5] = __tilt_speed;
662 
663  // pan
664  __obuffer[6] = (pan_val & 0xf000) >> 12;
665  __obuffer[7] = (pan_val & 0x0f00) >> 8;
666  __obuffer[8] = (pan_val & 0x00f0) >> 4;
667  __obuffer[9] = (pan_val & 0x000f);
668  // tilt
669  __obuffer[10] = (tilt_val & 0xf000) >> 12;
670  __obuffer[11] = (tilt_val & 0x0f00) >> 8;
671  __obuffer[12] = (tilt_val & 0x00f0) >> 4;
672  __obuffer[13] = (tilt_val & 0x000f);
673 
674  __obuffer_length = 13;
675 
676  try {
677  if (! __blocking) {
678  __nonblocking_running[ NONBLOCKING_PANTILT ] = true;
679  send_nonblocking( &(__nonblocking_sockets[ NONBLOCKING_PANTILT ]) );
680  } else {
681  send_with_reply();
682  }
683  } catch (ViscaException &e) {
684  e.append("setPanTilt() failed");
685  throw;
686  }
687 }
688 
689 
690 /** Set pan/tilt speed.
691  * @param pan_speed a value between 0 and MAX_PAN_SPEED
692  * @param tilt_speed a value between 0 and MAX_TILT_SPEED
693  * @exception Exception thrown if desired pan or tilt speed is too high
694  */
695 void
696 Visca::set_pan_tilt_speed(unsigned char pan_speed, unsigned char tilt_speed)
697 {
698  if (pan_speed > MAX_PAN_SPEED) {
699  throw fawkes::Exception("Pan speed too hight, max: %u des: %u", MAX_PAN_SPEED, pan_speed);
700  }
701  if (tilt_speed > MAX_TILT_SPEED) {
702  throw fawkes::Exception("Tilt speed too hight, max: %u des: %u", MAX_TILT_SPEED, tilt_speed);
703  }
704 
705  __pan_speed = pan_speed;
706  __tilt_speed = tilt_speed;
707 }
708 
709 
710 /** Get pan/tilt speed.
711  * @param pan_speed upon return contains pan speed index
712  * @param tilt_speed upon return contains tilt speed index
713  */
714 void
715 Visca::get_pan_tilt_speed(unsigned char &pan_speed, unsigned char &tilt_speed)
716 {
717  pan_speed = __pan_speed;
718  tilt_speed = __tilt_speed;
719 }
720 
721 /** Initiate a pan/tilt request, but do not wait for the reply. */
722 void
724 {
725 
726  if ( __inquire ) throw ViscaInquiryRunningException();
727 
728  __inquire = VISCA_RUNINQ_PANTILT;
729 
730  __obuffer[1] = VISCA_INQUIRY;
731  __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
732  __obuffer[3] = VISCA_PT_POSITION_INQ;
733  __obuffer_length = 3;
734 
735  try {
736  send();
737  } catch (ViscaException &e) {
738  e.append("startGetPanTilt() failed");
739  throw;
740  }
741 }
742 
743 
744 /** Get pan and tilt values.
745  * If you used startGetPanTilt() to initiate the query the result is
746  * received and returned, otherwise a request is sent and the method blocks
747  * until the answer has been received.
748  * @param pan contains pan upon return
749  * @param tilt contains tilt upon return
750  */
751 void
752 Visca::get_pan_tilt(int &pan, int &tilt)
753 {
754 
755  if ( __inquire ) {
756  if ( __inquire != VISCA_RUNINQ_PANTILT ) {
757  throw ViscaException("Inquiry running, but it is not a pan/tilt inquiry");
758  } else {
759 #ifdef TIMETRACKER_VISCA
760  __tt->ping_start( __ttc_pantilt_get_read );
761 #endif
762  try {
763  recv();
764  } catch (ViscaException &e) {
765  } catch (fawkes::TimeoutException &e) {
766  // Ignore
767  }
768 #ifdef TIMETRACKER_VISCA
769  __tt->ping_end( __ttc_pantilt_get_read );
770 #endif
771  }
772  } else {
773 
774  __obuffer[1] = VISCA_INQUIRY;
775  __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
776  __obuffer[3] = VISCA_PT_POSITION_INQ;
777  __obuffer_length = 3;
778 
779  try {
780 #ifdef TIMETRACKER_VISCA
781  __tt->ping_start( __ttc_pantilt_get_send );
782  send();
783  __tt->ping_end( __ttc_pantilt_get_send );
784  __tt->ping_start( __ttc_pantilt_get_read );
785  recv();
786  __tt->ping_end( __ttc_pantilt_get_read );
787 #else
788  send_with_reply();
789 #endif
790  } catch (ViscaException &e) {
791  // Ignore
792  }
793  }
794 
795 #ifdef TIMETRACKER_VISCA
796  __tt->ping_start( __ttc_pantilt_get_handle );
797 #endif
798 
799  while (__ibuffer[1] != VISCA_RESPONSE_COMPLETED) {
800  // inquire return from socket 0, so this may occur if there
801  // are other responses waiting, handle them...
802  try {
803  handle_response();
804  recv();
805  } catch (ViscaException &e) {
806  // Ignore
807  }
808  }
809 
810 #ifdef TIMETRACKER_VISCA
811  __tt->ping_end( __ttc_pantilt_get_handle );
812  __tt->ping_start( __ttc_pantilt_get_interpret );
813 #endif
814 
815 
816  // Extract information from __ibuffer
817  if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
818  unsigned short int pan_val = 0;
819  unsigned short int tilt_val = 0;
820 
821  pan_val |= (__ibuffer[2] & 0x0F) << 12;
822  pan_val |= (__ibuffer[3] & 0x0F) << 8;
823  pan_val |= (__ibuffer[4] & 0x0F) << 4;
824  pan_val |= (__ibuffer[5] & 0x0F);
825 
826  tilt_val |= (__ibuffer[6] & 0x0F) << 12;
827  tilt_val |= (__ibuffer[7] & 0x0F) << 8;
828  tilt_val |= (__ibuffer[8] & 0x0F) << 4;
829  tilt_val |= (__ibuffer[9] & 0x0F);
830 
831  if (pan_val < 0x8000) {
832  // The value must be positive
833  pan = pan_val;
834  } else {
835  // negative value
836  pan = pan_val - 0xFFFF;
837  }
838 
839  if (tilt_val < 0x8000) {
840  // The value must be positive
841  tilt = tilt_val;
842  } else {
843  // negative value
844  tilt = tilt_val - 0xFFFF;
845  }
846 
847  } else {
848  throw ViscaException("getPanTilt(): Wrong response received");
849  }
850 #ifdef TIMETRACKER_VISCA
851  __tt->ping_end( __ttc_pantilt_get_interpret );
852  __tt->print_to_stdout();
853 #endif
854 
855  __inquire = VISCA_RUNINQ_NONE;
856 }
857 
858 
859 /** Reset pan/tilt limit. */
860 void
862 {
863  __obuffer[1] = VISCA_COMMAND;
864  __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
865  __obuffer[3] = VISCA_PT_LIMITSET;
866  __obuffer[3] = VISCA_PT_LIMITSET_CLEAR;
867  __obuffer[4] = VISCA_PT_LIMITSET_SET_UR;
868  __obuffer[5] = 0x07;
869  __obuffer[6] = 0x0F;
870  __obuffer[7] = 0x0F;
871  __obuffer[8] = 0x0F;
872  __obuffer[9] = 0x07;
873  __obuffer[10] = 0x0F;
874  __obuffer[11] = 0x0F;
875  __obuffer[12] = 0x0F;
876  __obuffer_length = 12;
877 
878  try {
879  send_with_reply();
880 
881  __obuffer[4] = VISCA_PT_LIMITSET_SET_DL;
882 
883  send_with_reply();
884  } catch (ViscaException &e) {
885  e.append("resetPanTiltLimit() failed");
886  throw;
887  }
888 }
889 
890 
891 /** Set pan tilt limit.
892  * @param pan_left most left pan value
893  * @param pan_right most right pan value
894  * @param tilt_up most up tilt value
895  * @param tilt_down most down tilt value
896  */
897 void
898 Visca::set_pan_tilt_limit(int pan_left, int pan_right, int tilt_up, int tilt_down)
899 {
900  try {
901  __obuffer[1] = VISCA_COMMAND;
902  __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
903  __obuffer[3] = VISCA_PT_LIMITSET;
904  __obuffer[3] = VISCA_PT_LIMITSET_SET;
905  __obuffer[4] = VISCA_PT_LIMITSET_SET_UR;
906  // pan
907  __obuffer[5] = (pan_right & 0xf000) >> 12;
908  __obuffer[6] = (pan_right & 0x0f00) >> 8;
909  __obuffer[7] = (pan_right & 0x00f0) >> 4;
910  __obuffer[8] = (pan_right & 0x000f);
911  // tilt
912  __obuffer[9] = (tilt_up & 0xf000) >> 12;
913  __obuffer[10] = (tilt_up & 0x0f00) >> 8;
914  __obuffer[11] = (tilt_up & 0x00f0) >> 4;
915  __obuffer[12] = (tilt_up & 0x000f);
916 
917  __obuffer_length = 12;
918 
919  send_with_reply();
920 
921  __obuffer[4] = VISCA_PT_LIMITSET_SET_DL;
922  // pan
923  __obuffer[5] = (pan_left & 0xf000) >> 12;
924  __obuffer[6] = (pan_left & 0x0f00) >> 8;
925  __obuffer[7] = (pan_left & 0x00f0) >> 4;
926  __obuffer[8] = (pan_left & 0x000f);
927  // tilt
928  __obuffer[9] = (tilt_down & 0xf000) >> 12;
929  __obuffer[10] = (tilt_down & 0x0f00) >> 8;
930  __obuffer[11] = (tilt_down & 0x00f0) >> 4;
931  __obuffer[12] = (tilt_down & 0x000f);
932 
933  send_with_reply();
934  } catch (ViscaException &e) {
935  e.append("setPanTiltLimit() failed");
936  throw;
937  }
938 }
939 
940 
941 /** Reset pan/tilt. */
942 void
944 {
945  __obuffer[1] = VISCA_COMMAND;
946  __obuffer[2] = VISCA_CATEGORY_PAN_TILTER;
947  __obuffer[3] = VISCA_PT_HOME;
948  __obuffer_length = 3;
949 
950  try {
951  send_with_reply();
952  } catch (ViscaException &e) {
953  e.append("resetPanTilt() failed");
954  throw;
955  }
956 }
957 
958 
959 /** Reset zoom. */
960 void
962 {
963  __obuffer[1] = VISCA_COMMAND;
964  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
965  __obuffer[3] = VISCA_ZOOM;
966  __obuffer[4] = VISCA_ZOOM_STOP;
967  __obuffer_length = 4;
968 
969  try {
970  send_with_reply();
971  } catch (ViscaException &e) {
972  e.append("resetZoom() failed");
973  throw;
974  }
975 }
976 
977 
978 /** Set zoom speed in tele.
979  * @param speed speed
980  */
981 void
982 Visca::set_zoom_speed_tele(unsigned int speed)
983 {
984  __obuffer[1] = VISCA_COMMAND;
985  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
986  __obuffer[3] = VISCA_ZOOM;
987  __obuffer[4] = VISCA_ZOOM_TELE_SPEED;
988  // zoom speed
989  __obuffer[5] = (speed & 0x000f) | 0x0020;
990  __obuffer_length = 5;
991 
992  try {
993  send_with_reply();
994  } catch (ViscaException &e) {
995  e.append("setZoomSpeedTele() failed");
996  throw;
997  }
998 }
999 
1000 
1001 /** Set zoom speed in wide angle.
1002  * @param speed speed
1003  */
1004 void
1005 Visca::set_zoom_speed_wide(unsigned int speed)
1006 {
1007  __obuffer[1] = VISCA_COMMAND;
1008  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1009  __obuffer[3] = VISCA_ZOOM;
1010  __obuffer[4] = VISCA_ZOOM_WIDE_SPEED;
1011  // zoom speed
1012  __obuffer[5] = (speed & 0x000f) | 0x0020;
1013  __obuffer_length = 5;
1014 
1015  try {
1016  send_with_reply();
1017  } catch (ViscaException &e) {
1018  e.append("setZoomSpeedWide() failed");
1019  throw;
1020  }
1021 }
1022 
1023 
1024 /** Set zoom.
1025  * @param zoom zoom value
1026  */
1027 void
1028 Visca::set_zoom(unsigned int zoom)
1029 {
1030  __obuffer[1] = VISCA_COMMAND;
1031  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1032  __obuffer[3] = VISCA_ZOOM_VALUE;
1033  // zoom
1034  __obuffer[4] = (zoom & 0xf000) >> 12;
1035  __obuffer[5] = (zoom & 0x0f00) >> 8;
1036  __obuffer[6] = (zoom & 0x00f0) >> 4;
1037  __obuffer[7] = (zoom & 0x000f);
1038 
1039  __obuffer_length = 7;
1040 
1041  try {
1042  if (! __blocking) {
1043  __nonblocking_running[ NONBLOCKING_ZOOM ] = true;
1044  send_nonblocking( &(__nonblocking_sockets[ NONBLOCKING_ZOOM ]) );
1045  } else {
1046  send_with_reply();
1047  }
1048  } catch (ViscaException &e) {
1049  e.append("setZoom() failed");
1050  throw;
1051  }
1052 }
1053 
1054 
1055 /** Get zoom.
1056  * @param zoom contains zoom upon return.
1057  */
1058 void
1059 Visca::get_zoom(unsigned int &zoom)
1060 {
1061  __obuffer[1] = VISCA_INQUIRY;
1062  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1063  __obuffer[3] = VISCA_ZOOM_VALUE;
1064  __obuffer_length = 3;
1065 
1066  try {
1067  send_with_reply();
1068  } catch (ViscaException &e) {
1069  e.append("Failed to get zoom data");
1070  throw;
1071  }
1072 
1073  // Extract information from __ibuffer
1074  if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
1075  unsigned short int zoom_val = 0;
1076 
1077  zoom_val |= (__ibuffer[2] & 0x0F) << 12;
1078  zoom_val |= (__ibuffer[3] & 0x0F) << 8;
1079  zoom_val |= (__ibuffer[4] & 0x0F) << 4;
1080  zoom_val |= (__ibuffer[5] & 0x0F);
1081 
1082  zoom = zoom_val;
1083  } else {
1084  throw ViscaException("Failed to get zoom data failed, response code not VISCA_RESPONSE_COMPLETED");
1085  }
1086 
1087 }
1088 
1089 
1090 /** Enable or disable digital zoome.
1091  * @param enabled true to enable digital zoom, false to disable
1092  */
1093 void
1095 {
1096  __obuffer[1] = VISCA_COMMAND;
1097  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1098  __obuffer[3] = VISCA_DZOOM;
1099  if (enabled) {
1100  __obuffer[4] = VISCA_DZOOM_ON;
1101  } else {
1102  __obuffer[4] = VISCA_DZOOM_OFF;
1103  }
1104  __obuffer_length = 4;
1105 
1106  try {
1107  send_with_reply();
1108  } catch (ViscaException &e) {
1109  e.append("setZoomDigitalEnabled() failed");
1110  throw;
1111  }
1112 }
1113 
1114 
1115 /** Apply effect.
1116  * @param filter filter
1117  */
1118 void
1119 Visca::apply_effect(unsigned char filter)
1120 {
1121  __obuffer[1] = VISCA_COMMAND;
1122  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1123  __obuffer[3] = VISCA_PICTURE_EFFECT;
1124  __obuffer[4] = filter;
1125  __obuffer_length = 4;
1126 
1127  try {
1128  send_with_reply();
1129  } catch (ViscaException &e) {
1130  e.append("applyEffect() failed");
1131  throw;
1132  }
1133 }
1134 
1135 
1136 /** Reset effects. */
1137 void
1139 {
1140  try {
1141  apply_effect(VISCA_PICTURE_EFFECT_OFF);
1142  } catch (ViscaException &e) {
1143  e.append("resetEffect() failed");
1144  throw;
1145  }
1146 }
1147 
1148 
1149 /** Apply pastel effect. */
1150 void
1152 {
1153  try {
1154  apply_effect(VISCA_PICTURE_EFFECT_PASTEL);
1155  } catch (ViscaException &e) {
1156  e.append("applyEffectPastel() failed");
1157  throw;
1158  }
1159 }
1160 
1161 
1162 /** Apply negative art effect. */
1163 void
1165 {
1166  try {
1167  apply_effect(VISCA_PICTURE_EFFECT_NEGATIVE);
1168  } catch (ViscaException &e) {
1169  e.append("applyEffectNegArt() failed");
1170  throw;
1171  }
1172 }
1173 
1174 
1175 /** Apply sepia effect. */
1176 void
1178 {
1179  try {
1180  apply_effect(VISCA_PICTURE_EFFECT_SEPIA);
1181  } catch (ViscaException &e) {
1182  e.append("applyEffectSepia() failed");
1183  throw;
1184  }
1185 }
1186 
1187 
1188 /**Apply B/W effect */
1189 void
1191 {
1192  try {
1193  apply_effect(VISCA_PICTURE_EFFECT_BW);
1194  } catch (ViscaException &e) {
1195  e.append("applyEffectBnW() failed");
1196  throw;
1197  }
1198 }
1199 
1200 
1201 /** Apply solarize effect. */
1202 void
1204 {
1205  try {
1206  apply_effect(VISCA_PICTURE_EFFECT_SOLARIZE);
1207  } catch (ViscaException &e) {
1208  e.append("applyEffectSolarize() failed");
1209  throw;
1210  }
1211 }
1212 
1213 
1214 /** Apply mosaic effect. */
1215 void
1217 {
1218  try {
1219  apply_effect(VISCA_PICTURE_EFFECT_MOSAIC);
1220  } catch (ViscaException &e) {
1221  e.append("applyEffectMosaic() failed");
1222  throw;
1223  }
1224 }
1225 
1226 
1227 /** Apply slim effect. */
1228 void
1230 {
1231  try {
1232  apply_effect(VISCA_PICTURE_EFFECT_SLIM);
1233  } catch (ViscaException &e) {
1234  e.append("applyEffectSlim() failed");
1235  throw;
1236  }
1237 }
1238 
1239 
1240 /** Apply stretch effect. */
1241 void
1243 {
1244  try {
1245  apply_effect(VISCA_PICTURE_EFFECT_STRETCH);
1246  } catch (ViscaException &e) {
1247  e.append("applyEffectStretch() failed");
1248  throw;
1249  }
1250 }
1251 
1252 
1253 /** Get white balance mode.
1254  * @return white balance mode
1255  */
1256 unsigned int
1258 {
1259  __obuffer[1] = VISCA_INQUIRY;
1260  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1261  __obuffer[3] = VISCA_WB;
1262  __obuffer_length = 3;
1263 
1264  try {
1265  send_with_reply();
1266  } catch (ViscaException &e) {
1267  e.append("getWhiteBalanceMode() failed");
1268  throw;
1269  }
1270 
1271  while (__ibuffer[1] != VISCA_RESPONSE_COMPLETED) {
1272  // inquire return from socket 0, so this may occur if there
1273  // are other responses waiting, handle them...
1274  try {
1275  handle_response();
1276  recv();
1277  } catch (ViscaException &e) {
1278  e.append("getWhiteBalanceMode() failed");
1279  throw;
1280  }
1281  }
1282 
1283  // Extract information from __ibuffer
1284  if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
1285  return __ibuffer[2];
1286  } else {
1287  throw ViscaException("Did not get 'request completed' response");
1288  }
1289 
1290 }
1291 
1292 
1293 /** Sett mirror sate
1294  * @param mirror true to enable mirroring, false to disable
1295  */
1296 void
1297 Visca::set_mirror(bool mirror)
1298 {
1299  __obuffer[1] = VISCA_COMMAND;
1300  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1301  __obuffer[3] = VISCA_MIRROR;
1302  __obuffer[4] = mirror ? VISCA_MIRROR_ON : VISCA_MIRROR_OFF;
1303  __obuffer_length = 4;
1304 
1305  try {
1306  send_with_reply();
1307  } catch (ViscaException &e) {
1308  e.append("set_mirror() failed");
1309  throw;
1310  }
1311 }
1312 
1313 /** Get mirror sate.
1314  * @return true if image is mirrored, false otherwise
1315  */
1316 bool
1318 {
1319  __obuffer[1] = VISCA_INQUIRY;
1320  __obuffer[2] = VISCA_CATEGORY_CAMERA1;
1321  __obuffer[3] = VISCA_MIRROR;
1322  __obuffer_length = 3;
1323 
1324  try {
1325  send_with_reply();
1326  } catch (ViscaException &e) {
1327  e.append("Failed to get mirror data");
1328  throw;
1329  }
1330 
1331  // Extract information from __ibuffer
1332  if ( __ibuffer[1] == VISCA_RESPONSE_COMPLETED ) {
1333  return (__ibuffer[2] != 0);
1334  } else {
1335  throw ViscaException("Failed to get mirror data: zoom inquiry failed, "
1336  "response code not VISCA_RESPONSE_COMPLETED");
1337  }
1338 }
void apply_effect_slim()
Apply slim effect.
Definition: visca.cpp:1229
void apply_effect_mosaic()
Apply mosaic effect.
Definition: visca.cpp:1216
static const unsigned int VISCA_WHITEBALANCE_ATW
ATW white balance preset.
Definition: visca.h:57
void set_pan_tilt_limit(int pan_left, int pan_right, int tilt_up, int tilt_down)
Set pan tilt limit.
Definition: visca.cpp:898
static const unsigned int NONBLOCKING_PANTILT
Non-blocking pan/tilt item.
Definition: visca.h:60
void set_pan_tilt(int pan, int tilt)
Set pan tilt.
Definition: visca.cpp:638
void cancel_command(unsigned int socket)
Cancel a running command.
Definition: visca.cpp:542
void apply_effect_solarize()
Apply solarize effect.
Definition: visca.cpp:1203
void set_address()
Set addresses of cameras.
Definition: visca.cpp:227
static const unsigned int MAX_TILT_SPEED
Number of non-blocking items.
Definition: visca.h:65
void start_get_pan_tilt()
Query for pan/tilt but do not wait until finished This will send an inquire to the camera that asks f...
Definition: visca.cpp:723
static const unsigned int VISCA_WHITEBALANCE_MANUAL
Manual white balance.
Definition: visca.h:58
void apply_effect_pastel()
Apply pastel effect.
Definition: visca.cpp:1151
void set_power(bool powered)
Set power state.
Definition: visca.cpp:589
Exception()
Constructor for subclasses.
Definition: exception.cpp:257
void clear()
Clear command buffers.
Definition: visca.cpp:249
void set_pan_tilt_speed(unsigned char pan_speed, unsigned char tilt_speed)
Set pan/tilt speed.
Definition: visca.cpp:696
The current system call has timed out before completion.
Definition: system.h:46
static const unsigned int NONBLOCKING_ZOOM
Non-blocking zoom item.
Definition: visca.h:61
void set_zoom_speed_wide(unsigned int speed)
Set zoom speed in wide angle.
Definition: visca.cpp:1005
int _errno
Error number, should be used if the error was caused by a method that supplies errno.
Definition: exception.h:111
bool is_powered()
Check if camera is powered.
Definition: visca.cpp:610
void set_zoom_speed_tele(unsigned int speed)
Set zoom speed in tele.
Definition: visca.cpp:982
void reset_effect()
Reset effects.
Definition: visca.cpp:1138
void send_with_reply()
Send and wait for reply, blocking.
Definition: visca.cpp:430
static const unsigned int VISCA_WHITEBALANCE_INDOOR
Indoor white balance preset.
Definition: visca.h:54
virtual ~Visca()
Destructor.
Definition: visca.cpp:129
static const unsigned int NONBLOCKING_NUM
Number of non-blocking items.
Definition: visca.h:62
void reset_pan_tilt_limit()
Reset pan/tilt limit.
Definition: visca.cpp:861
ViscaInquiryRunningException()
Constructor.
Definition: visca.cpp:61
static const unsigned int VISCA_WHITEBALANCE_OUTDOOR
Outdoor white balance preset.
Definition: visca.h:55
void recv_ack(unsigned int *socket=NULL)
Receive ACK packet.
Definition: visca.cpp:349
void open()
Open serial port.
Definition: visca.cpp:138
void reset_zoom()
Reset zoom.
Definition: visca.cpp:961
Base class for exceptions in Fawkes.
Definition: exception.h:36
void set_zoom_digital_enabled(bool enabled)
Enable or disable digital zoome.
Definition: visca.cpp:1094
void apply_effect_stretch()
Apply stretch effect.
Definition: visca.cpp:1242
void get_pan_tilt(int &pan, int &tilt)
Get pan and tilt values.
Definition: visca.cpp:752
void apply_effect(unsigned char effect)
Apply effect.
Definition: visca.cpp:1119
static const unsigned int VISCA_WHITEBLANCE_AUTO
Automatic white balance.
Definition: visca.h:53
Visca exception.
Definition: visca.h:36
void reset_pan_tilt()
Reset pan/tilt.
Definition: visca.cpp:943
bool data_available()
Check data availability.
Definition: visca.cpp:298
bool is_nonblocking_finished(unsigned int item) const
Check if a non-blocking operation has been finished.
Definition: visca.cpp:419
bool get_mirror()
Get mirror sate.
Definition: visca.cpp:1317
static const unsigned int MAX_PAN_SPEED
Number of non-blocking items.
Definition: visca.h:64
void apply_effect_neg_art()
Apply negative art effect.
Definition: visca.cpp:1164
void apply_effect_sepia()
Apply sepia effect.
Definition: visca.cpp:1177
void recv(unsigned int timeout_ms=0xFFFFFFFF)
Receive data.
Definition: visca.cpp:310
void close()
Close port.
Definition: visca.cpp:216
unsigned int get_white_balance_mode()
Get white balance mode.
Definition: visca.cpp:1257
ViscaException(const char *msg)
Constructor.
Definition: visca.cpp:43
void get_pan_tilt_speed(unsigned char &pan_speed, unsigned char &tilt_speed)
Get pan/tilt speed.
Definition: visca.cpp:715
void get_zoom(unsigned int &zoom)
Get zoom.
Definition: visca.cpp:1059
void set_zoom(unsigned int zoom)
Set zoom.
Definition: visca.cpp:1028
void apply_effect_bnw()
Apply B/W effect.
Definition: visca.cpp:1190
Visca(const char *device_file, unsigned int def_timeout_ms=10, bool blocking=true)
Constructor.
Definition: visca.cpp:106
void send()
Send outbound queue.
Definition: visca.cpp:270
void set_mirror(bool mirror)
Sett mirror sate.
Definition: visca.cpp:1297
static const unsigned int VISCA_WHITEBALANCE_ONE_PUSH
One push white balance preset.
Definition: visca.h:56
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
void send_nonblocking(unsigned int *socket=NULL)
Send non-blocking.
Definition: visca.cpp:384
void process()
Process incoming data.
Definition: visca.cpp:568