Fawkes API  Fawkes Development Version
shm_image.cpp
00001 
00002 /***************************************************************************
00003  *  shm_image.cpp - shared memory image buffer
00004  *
00005  *  Created: Thu Jan 12 14:10:43 2006
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 <core/exception.h>
00025 #include <fvutils/ipc/shm_image.h>
00026 #include <fvutils/ipc/shm_exceptions.h>
00027 #include <utils/system/console_colors.h>
00028 #include <utils/ipc/shm_exceptions.h>
00029 #include <utils/misc/strndup.h>
00030 
00031 #include <iostream>
00032 #include <cstring>
00033 #include <cstdlib>
00034 #include <cstdio>
00035 
00036 using namespace std;
00037 using namespace fawkes;
00038 
00039 namespace firevision {
00040 #if 0 /* just to make Emacs auto-indent happy */
00041 }
00042 #endif
00043 
00044 /** @class SharedMemoryImageBuffer <fvutils/ipc/shm_image.h>
00045  * Shared memory image buffer.
00046  * Write images to or retrieve images from a shared memory segment.
00047  * @author Tim Niemueller
00048  */
00049 
00050 /** Write Constructor.
00051  * Create a new shared memory segment. Will open a shared memory segment that
00052  * exactly fits the given information. Will throw an error if image with id
00053  * image_id exists.
00054  * I will create a new segment if no matching segment was found.
00055  * The segment is accessed in read-write mode.
00056  *
00057  * Use this constructor to open a shared memory image buffer for writing.
00058  * @param image_id image ID to open
00059  * @param cspace colorspace
00060  * @param width image width
00061  * @param height image height
00062  */
00063 SharedMemoryImageBuffer::SharedMemoryImageBuffer(const char *image_id,
00064                                                  colorspace_t cspace,
00065                                                  unsigned int width,
00066                                                  unsigned int height)
00067   : SharedMemory(FIREVISION_SHM_IMAGE_MAGIC_TOKEN,
00068                  /* read-only */ false,
00069                  /* create */ true,
00070                  /* destroy on delete */ true)
00071 {
00072   constructor(image_id, cspace, width, height, false);
00073   add_semaphore();
00074 }
00075 
00076 
00077 /** Read Constructor.
00078  * This constructor is used to search for an existing shared memory segment.
00079  * It will throw an error if it cannot find a segment with the specified data.
00080  * The segment is opened read-only by default, but this can be overridden with
00081  * the is_read_only argument if needed.
00082  *
00083  * Use this constructor to open an image for reading.
00084  * @param image_id Image ID to open
00085  * @param is_read_only true to open image read-only
00086  */
00087 SharedMemoryImageBuffer::SharedMemoryImageBuffer(const char *image_id, bool is_read_only)
00088   : SharedMemory(FIREVISION_SHM_IMAGE_MAGIC_TOKEN, is_read_only, /* create */ false, /* destroy */ false)
00089 {
00090   constructor(image_id, CS_UNKNOWN, 0, 0, is_read_only);
00091 }
00092 
00093 
00094 void
00095 SharedMemoryImageBuffer::constructor(const char *image_id, colorspace_t cspace,
00096                                      unsigned int width, unsigned int height,
00097                                      bool is_read_only)
00098 {
00099   _image_id     = strdup(image_id);
00100   _is_read_only = is_read_only;
00101 
00102   _colorspace = cspace;
00103   _width      = width;
00104   _height     = height;
00105 
00106   priv_header = new SharedMemoryImageBufferHeader(_image_id, _colorspace, width, height);
00107   _header = priv_header;
00108   try {
00109     attach();
00110     raw_header = priv_header->raw_header();
00111   } catch (Exception &e) {
00112     e.append("SharedMemoryImageBuffer: could not attach to '%s'\n", image_id);
00113     ::free(_image_id);
00114     _image_id = NULL;
00115     delete priv_header;
00116     throw;
00117   }
00118 }
00119 
00120 
00121 /** Destructor. */
00122 SharedMemoryImageBuffer::~SharedMemoryImageBuffer()
00123 {
00124   ::free(_image_id);
00125   delete priv_header;
00126 }
00127 
00128 
00129 /** Set image number.
00130  * This will close the currently opened image and will try to open the new
00131  * image. This operation should be avoided.
00132  * @param image_id new image ID
00133  * @return true on success
00134  */
00135 bool
00136 SharedMemoryImageBuffer::set_image_id(const char *image_id)
00137 {
00138   free();
00139   ::free(_image_id);
00140   _image_id = strdup(image_id);
00141   priv_header->set_image_id(_image_id);
00142   attach();
00143   raw_header = priv_header->raw_header();
00144   return (_memptr != NULL);
00145 }
00146 
00147 
00148 /** Set frame ID.
00149  * @param frame_id new frame ID
00150  */
00151 void
00152 SharedMemoryImageBuffer::set_frame_id(const char *frame_id)
00153 {
00154   priv_header->set_frame_id(frame_id);
00155   strncpy(raw_header->frame_id, frame_id, FRAME_ID_MAX_LENGTH);
00156 }
00157 
00158 
00159 /** Get Image ID.
00160  * @return image id
00161  */
00162 const char *
00163 SharedMemoryImageBuffer::image_id() const
00164 {
00165   return _image_id;
00166 }
00167 
00168 
00169 /** Get frame ID.
00170  * @return frame id
00171  */
00172 const char *
00173 SharedMemoryImageBuffer::frame_id() const
00174 {
00175   return priv_header->frame_id();
00176 }
00177 
00178 
00179 /** Get the time when the image was captured.
00180  * @param sec upon return contains the seconds part of the time
00181  * @param usec upon return contains the micro seconds part of the time
00182  */
00183 void
00184 SharedMemoryImageBuffer::capture_time(long int *sec, long int *usec) const
00185 {
00186   *sec  = raw_header->capture_time_sec;
00187   *usec = raw_header->capture_time_usec;
00188 }
00189 
00190 /** Get the time when the image was captured.
00191  * @return capture time
00192  */
00193 Time
00194 SharedMemoryImageBuffer::capture_time() const
00195 {
00196   return Time(raw_header->capture_time_sec, raw_header->capture_time_usec);
00197 }
00198 
00199 
00200 /** Set the capture time.
00201  * @param time capture time
00202  */
00203 void
00204 SharedMemoryImageBuffer::set_capture_time(Time *time)
00205 {
00206   if (_is_read_only) {
00207     throw Exception("Buffer is read-only. Not setting capture time.");
00208   }
00209 
00210   const timeval *t = time->get_timeval();
00211   raw_header->capture_time_sec  = t->tv_sec;
00212   raw_header->capture_time_usec = t->tv_usec;
00213 }
00214 
00215 /** Set the capture time.
00216  * @param sec seconds part of capture time
00217  * @param usec microseconds part of capture time
00218  */
00219 void
00220 SharedMemoryImageBuffer::set_capture_time(long int sec, long int usec)
00221 {
00222   if (_is_read_only) {
00223     throw Exception("Buffer is read-only. Not setting capture time.");
00224   }
00225 
00226   raw_header->capture_time_sec  = sec;
00227   raw_header->capture_time_usec = usec;
00228 }
00229 
00230 /** Get image buffer.
00231  * @return image buffer.
00232  */
00233 unsigned char *
00234 SharedMemoryImageBuffer::buffer() const
00235 {
00236   return (unsigned char *)_memptr;
00237 }
00238 
00239 
00240 /** Get color space.
00241  * @return colorspace
00242  */
00243 colorspace_t
00244 SharedMemoryImageBuffer::colorspace() const
00245 {
00246   return (colorspace_t)raw_header->colorspace;
00247 }
00248 
00249 
00250 /** Get image width.
00251  * @return width
00252  */
00253 unsigned int
00254 SharedMemoryImageBuffer::width() const
00255 {
00256   return raw_header->width;
00257 }
00258 
00259 
00260 /** Get image height.
00261  * @return image height
00262  */
00263 unsigned int
00264 SharedMemoryImageBuffer::height() const
00265 {
00266   return raw_header->height;
00267 }
00268 
00269 
00270 /** Get ROI X.
00271  * @return ROI X
00272  */
00273 unsigned int
00274 SharedMemoryImageBuffer::roi_x() const
00275 {
00276   return raw_header->roi_x;
00277 }
00278 
00279 
00280 /** Get ROI Y.
00281  * @return ROI Y
00282  */
00283 unsigned int
00284 SharedMemoryImageBuffer::roi_y() const
00285 {
00286   return raw_header->roi_y;
00287 }
00288 
00289 
00290 /** Get ROI width.
00291  * @return ROI width
00292  */
00293 unsigned int
00294 SharedMemoryImageBuffer::roi_width() const
00295 {
00296   return raw_header->roi_width;
00297 }
00298 
00299 
00300 /** Get ROI height.
00301  * @return ROI height
00302  */
00303 unsigned int
00304 SharedMemoryImageBuffer::roi_height() const
00305 {
00306   return raw_header->roi_height;
00307 }
00308 
00309 
00310 /** Get circle X.
00311  * @return circle X
00312  */
00313 int
00314 SharedMemoryImageBuffer::circle_x() const
00315 {
00316   return raw_header->circle_x;
00317 }
00318 
00319 
00320 /** Get circle Y.
00321  * @return circle Y
00322  */
00323 int
00324 SharedMemoryImageBuffer::circle_y() const
00325 {
00326   return raw_header->circle_y;
00327 }
00328 
00329 
00330 /** Get circle radius.
00331  * @return circle radius
00332  */
00333 unsigned int
00334 SharedMemoryImageBuffer::circle_radius() const
00335 {
00336   return raw_header->circle_radius;
00337 }
00338 
00339 
00340 /** Set ROI X.
00341  * @param roi_x new ROI X
00342  */
00343 void
00344 SharedMemoryImageBuffer::set_roi_x(unsigned int roi_x)
00345 {
00346   if (_is_read_only) {
00347     throw Exception("Buffer is read-only. Not setting ROI X.");
00348   }
00349   raw_header->roi_x = roi_x;
00350 }
00351 
00352 
00353 /** Set ROI Y.
00354  * @param roi_y new ROI Y
00355  */
00356 void
00357 SharedMemoryImageBuffer::set_roi_y(unsigned int roi_y)
00358 {
00359   if (_is_read_only) {
00360     throw Exception("Buffer is read-only. Not setting ROI Y.");
00361   }
00362   raw_header->roi_y = roi_y;
00363 }
00364 
00365 
00366 /** Set ROI width.
00367  * @param roi_w new ROI width
00368  */
00369 void
00370 SharedMemoryImageBuffer::set_roi_width(unsigned int roi_w)
00371 {
00372   if (_is_read_only) {
00373     throw Exception("Buffer is read-only. Not setting ROI width.");
00374   }
00375   raw_header->roi_width = roi_w;
00376 }
00377 
00378 
00379 /** Set ROI height.
00380  * @param roi_h new ROI height
00381  */
00382 void
00383 SharedMemoryImageBuffer::set_roi_height(unsigned int roi_h)
00384 {
00385   if (_is_read_only) {
00386     throw Exception("Buffer is read-only. Not setting ROI height.");
00387   }
00388   raw_header->roi_height = roi_h;
00389 }
00390 
00391 
00392 /** Set ROI data.
00393  * @param roi_x new ROI X
00394  * @param roi_y new ROI Y
00395  * @param roi_w new ROI width
00396  * @param roi_h new ROI height
00397  */
00398 void
00399 SharedMemoryImageBuffer::set_roi(unsigned int roi_x, unsigned int roi_y,
00400                                  unsigned int roi_w, unsigned int roi_h)
00401 {
00402   if (_is_read_only) {
00403     throw Exception("Buffer is read-only. Not setting ROI X/Y.");
00404   }
00405   raw_header->roi_x = roi_x;
00406   raw_header->roi_y = roi_y;
00407   raw_header->roi_width  = roi_w;
00408   raw_header->roi_height = roi_h;
00409 }
00410 
00411 
00412 /** Set circle X.
00413  * @param circle_x new circle X
00414  */
00415 void
00416 SharedMemoryImageBuffer::set_circle_x(int circle_x)
00417 {
00418   if (_is_read_only) {
00419     throw Exception("Buffer is read-only. Not setting circle X.");
00420   }
00421   raw_header->circle_x = circle_x;
00422 }
00423 
00424 
00425 /** Set circle Y.
00426  * @param circle_y new circle Y
00427  */
00428 void
00429 SharedMemoryImageBuffer::set_circle_y(int circle_y)
00430 {
00431   if (_is_read_only) {
00432     throw Exception("Buffer is read-only. Not setting circle Y.");
00433   }
00434   raw_header->circle_y = circle_y;
00435 }
00436 
00437 
00438 /** Set circle radius.
00439  * @param circle_radius new circle radius
00440  */
00441 void
00442 SharedMemoryImageBuffer::set_circle_radius(unsigned int circle_radius)
00443 {
00444   if (_is_read_only) {
00445     throw Exception("Buffer is read-only. Not setting circle radius.");
00446   }
00447   raw_header->circle_radius = circle_radius;
00448 }
00449 
00450 
00451 /** Set circle data.
00452  * @param x circle X
00453  * @param y circle Y
00454  * @param r circle radius
00455  */
00456 void
00457 SharedMemoryImageBuffer::set_circle(int x, int y, unsigned int r)
00458 {
00459   if (_is_read_only) {
00460     throw Exception("Buffer is read-only. Not setting circle X/Y/radius.");
00461   }
00462   raw_header->circle_x      = x;
00463   raw_header->circle_y      = y;
00464   raw_header->circle_radius = r;
00465 }
00466 
00467 
00468 /** Set circle found.
00469  * @param found true if circle found
00470  */
00471 void
00472 SharedMemoryImageBuffer::set_circle_found(bool found)
00473 {
00474   raw_header->flag_circle_found = (found ? 1 : 0);
00475 }
00476 
00477 
00478 /** Check if circle was found .
00479  * @return true if circle was found, false otherwise
00480  */
00481 bool
00482 SharedMemoryImageBuffer::circle_found() const
00483 {
00484   return (raw_header->flag_circle_found == 1);
00485 }
00486 
00487 
00488 /** List all shared memory segments that contain a FireVision image. */
00489 void
00490 SharedMemoryImageBuffer::list()
00491 {
00492   SharedMemoryImageBufferLister *lister = new SharedMemoryImageBufferLister();
00493   SharedMemoryImageBufferHeader *h      = new SharedMemoryImageBufferHeader();
00494 
00495   SharedMemory::list(FIREVISION_SHM_IMAGE_MAGIC_TOKEN, h, lister);
00496 
00497   delete lister;
00498   delete h;
00499 }
00500 
00501 
00502 /** Erase all shared memory segments that contain FireVision images.
00503  * @param use_lister if true a lister is used to print the shared memory segments
00504  * to stdout while cleaning up.
00505  */
00506 void
00507 SharedMemoryImageBuffer::cleanup(bool use_lister)
00508 {
00509   SharedMemoryImageBufferLister *lister = NULL;
00510   SharedMemoryImageBufferHeader *h      = new SharedMemoryImageBufferHeader();
00511 
00512   if (use_lister) {
00513     lister = new SharedMemoryImageBufferLister();
00514   }
00515 
00516   SharedMemory::erase_orphaned(FIREVISION_SHM_IMAGE_MAGIC_TOKEN, h, lister);
00517 
00518   delete lister;
00519   delete h;
00520 }
00521 
00522 
00523 /** Check image availability.
00524  * @param image_id image ID to check
00525  * @return true if shared memory segment with requested image exists
00526  */
00527 bool
00528 SharedMemoryImageBuffer::exists(const char *image_id)
00529 {
00530   SharedMemoryImageBufferHeader *h      = new SharedMemoryImageBufferHeader(image_id, CS_UNKNOWN, 0, 0);
00531 
00532   bool ex = SharedMemory::exists(FIREVISION_SHM_IMAGE_MAGIC_TOKEN, h);
00533 
00534   delete h;
00535   return ex;
00536 }
00537 
00538 
00539 /** Erase a specific shared memory segment that contains an image.
00540  * @param image_id ID of image to wipe
00541  */
00542 void
00543 SharedMemoryImageBuffer::wipe(const char *image_id)
00544 {
00545   SharedMemoryImageBufferHeader *h      = new SharedMemoryImageBufferHeader(image_id, CS_UNKNOWN, 0, 0);
00546 
00547   SharedMemory::erase(FIREVISION_SHM_IMAGE_MAGIC_TOKEN, h, NULL);
00548 
00549   delete h;
00550 }
00551 
00552 
00553 /** @class SharedMemoryImageBufferHeader <fvutils/ipc/shm_image.h>
00554  * Shared memory image buffer header.
00555  */
00556 
00557 /** Constructor. */
00558 SharedMemoryImageBufferHeader::SharedMemoryImageBufferHeader()
00559 {
00560   _colorspace = CS_UNKNOWN;
00561   _image_id = NULL;
00562   _frame_id = NULL;
00563   _width = 0;
00564   _height = 0;
00565   _header = NULL;
00566   _orig_image_id = NULL;
00567   _orig_frame_id = NULL;
00568 }
00569 
00570 
00571 /** Constructor.
00572  * @param image_id image id
00573  * @param colorspace colorspace
00574  * @param width width
00575  * @param height height
00576  */
00577 SharedMemoryImageBufferHeader::SharedMemoryImageBufferHeader(const char *image_id,
00578                                                              colorspace_t colorspace,
00579                                                              unsigned int width,
00580                                                              unsigned int height)
00581 {
00582   _image_id   = strdup(image_id);
00583   _colorspace = colorspace;
00584   _width      = width;
00585   _height     = height;
00586   _header     = NULL;
00587   _frame_id   = NULL;
00588 
00589   _orig_image_id   = NULL;
00590   _orig_frame_id   = NULL;
00591   _orig_width      = 0;
00592   _orig_height     = 0;
00593   _orig_colorspace = CS_UNKNOWN;
00594 }
00595 
00596 
00597 /** Copy constructor.
00598  * @param h shared memory image header to copy
00599  */
00600 SharedMemoryImageBufferHeader::SharedMemoryImageBufferHeader(const SharedMemoryImageBufferHeader *h)
00601 {
00602   if ( h->_image_id != NULL ) {
00603     _image_id   = strdup(h->_image_id);
00604   } else {
00605     _image_id = NULL;
00606   }
00607   if ( h->_frame_id != NULL ) {
00608     _frame_id   = strdup(h->_frame_id);
00609   } else {
00610     _frame_id = NULL;
00611   }
00612   _colorspace = h->_colorspace;
00613   _width      = h->_width;
00614   _height     = h->_height;
00615   _header     = h->_header;
00616 
00617   _orig_image_id   = NULL;
00618   _orig_frame_id   = NULL;
00619   _orig_width      = 0;
00620   _orig_height     = 0;
00621   _orig_colorspace = CS_UNKNOWN;
00622 }
00623 
00624 
00625 /** Destructor. */
00626 SharedMemoryImageBufferHeader::~SharedMemoryImageBufferHeader()
00627 {
00628   if ( _image_id != NULL)  free(_image_id);
00629   if ( _frame_id != NULL)  free(_frame_id);
00630   if ( _orig_image_id != NULL)  free(_orig_image_id);
00631   if ( _orig_frame_id != NULL)  free(_orig_frame_id);
00632 }
00633 
00634 
00635 size_t
00636 SharedMemoryImageBufferHeader::size()
00637 {
00638   return sizeof(SharedMemoryImageBuffer_header_t);
00639 }
00640 
00641 
00642 SharedMemoryHeader *
00643 SharedMemoryImageBufferHeader::clone() const
00644 {
00645   return new SharedMemoryImageBufferHeader(this);
00646 }
00647 
00648 
00649 size_t
00650 SharedMemoryImageBufferHeader::data_size()
00651 {
00652   if (_header == NULL) {
00653     return colorspace_buffer_size(_colorspace, _width, _height);
00654   } else {
00655     return colorspace_buffer_size((colorspace_t)_header->colorspace, _header->width, _header->height);
00656   }
00657 }
00658 
00659 
00660 bool
00661 SharedMemoryImageBufferHeader::matches(void *memptr)
00662 {
00663   SharedMemoryImageBuffer_header_t *h = (SharedMemoryImageBuffer_header_t *)memptr;
00664 
00665   if (_image_id == NULL) {
00666     return true;
00667 
00668   } else if (strncmp(h->image_id, _image_id, IMAGE_ID_MAX_LENGTH) == 0) {
00669     if ( (_colorspace == CS_UNKNOWN) ||
00670          (((colorspace_t)h->colorspace == _colorspace) &&
00671           (h->width == _width) &&
00672           (h->height == _height) &&
00673           (! _frame_id || (strncmp(h->frame_id, _frame_id, FRAME_ID_MAX_LENGTH) == 0))
00674           )
00675          )
00676     {
00677       return true;
00678     } else {
00679       throw InconsistentImageException("Inconsistent image found in memory (meta)");
00680     }
00681   } else {
00682     return false;
00683   }
00684 }
00685 
00686 /** Check for equality of headers.
00687  * First checks if passed SharedMemoryHeader is an instance of
00688  * SharedMemoryImageBufferHeader. If not returns false, otherwise it compares
00689  * image ID, colorspace, width, and height. If all match returns true, false
00690  * if any of them differs.
00691  * @param s shared memory header to compare to
00692  * @return true if the two instances identify the very same shared memory segments,
00693  * false otherwise
00694  */
00695 bool
00696 SharedMemoryImageBufferHeader::operator==(const SharedMemoryHeader &s) const
00697 {
00698   const SharedMemoryImageBufferHeader *h = dynamic_cast<const SharedMemoryImageBufferHeader *>(&s);
00699   if ( ! h ) {
00700     return false;
00701   } else {
00702     return ( (strncmp(_image_id, h->_image_id, IMAGE_ID_MAX_LENGTH) == 0) &&
00703              (! _frame_id || (strncmp(_frame_id, h->_frame_id, FRAME_ID_MAX_LENGTH) == 0)) &&
00704              (_colorspace == h->_colorspace) &&
00705              (_width == h->_width) &&
00706              (_height == h->_height) );
00707   }
00708 }
00709 
00710 /** Print some info. */
00711 void
00712 SharedMemoryImageBufferHeader::print_info()
00713 {
00714   if (_image_id == NULL) {
00715     cout << "No image set" << endl;
00716     return;
00717   }
00718   cout << "SharedMemory Image Info: " << endl;
00719   printf("    address:  %p\n", _header);
00720   cout << "    image id:  " << _image_id << endl
00721        << "    frame id:  " << (_frame_id ? _frame_id : "NOT SET") << endl
00722        << "    colorspace: " << _colorspace << endl
00723        << "    dimensions: " << _width << "x" << _height << endl;
00724   /*
00725      << "    ROI:        at (" << header->roi_x << "," << header->roi_y
00726        << ")  dim " << header->roi_width << "x" << header->roi_height << endl
00727        << "    circle:     " << (header->flag_circle_found ? "" : "not ")
00728        << "found at (" << header->circle_x << "," << header->circle_y
00729        << ")  radius " << header->circle_radius << endl
00730        << "    img ready:  " << (header->flag_image_ready ? "yes" : "no") << endl;
00731   */
00732 }
00733 
00734 
00735 /** Create if colorspace, width and height have been supplied.
00736  * @return true if colorspace has been set, width and height are greater than zero.
00737  */
00738 bool
00739 SharedMemoryImageBufferHeader::create()
00740 {
00741   return ( (_colorspace != CS_UNKNOWN) &&
00742            (_width > 0) &&
00743            (_height > 0) );
00744 }
00745 
00746 
00747 void
00748 SharedMemoryImageBufferHeader::initialize(void *memptr)
00749 {
00750   SharedMemoryImageBuffer_header_t *header = (SharedMemoryImageBuffer_header_t *)memptr;
00751   memset(memptr, 0, sizeof(SharedMemoryImageBuffer_header_t));
00752 
00753   strncpy(header->image_id, _image_id, IMAGE_ID_MAX_LENGTH);
00754   if (_frame_id) {
00755     strncpy(header->frame_id, _frame_id, FRAME_ID_MAX_LENGTH);
00756   }
00757   header->colorspace = _colorspace;
00758   header->width      = _width;
00759   header->height     = _height;
00760 
00761   _header = header;
00762 }
00763 
00764 
00765 void
00766 SharedMemoryImageBufferHeader::set(void *memptr)
00767 {
00768   SharedMemoryImageBuffer_header_t *header = (SharedMemoryImageBuffer_header_t *)memptr;
00769   if ( NULL != _orig_image_id )  free(_orig_image_id);
00770   if ( NULL != _image_id ) {
00771     _orig_image_id = strdup(_image_id);
00772     free(_image_id);
00773   } else {
00774     _orig_image_id = NULL;
00775   }
00776   if ( NULL != _orig_frame_id )  free(_orig_frame_id);
00777   if ( NULL != _frame_id ) {
00778     _orig_frame_id = strdup(_frame_id);
00779     free(_frame_id);
00780   } else {
00781     _orig_frame_id = NULL;
00782   }
00783   _orig_width = _width;
00784   _orig_height = _height;
00785   _orig_colorspace = _colorspace;
00786   _header = header;
00787 
00788   _image_id = strndup(header->image_id, IMAGE_ID_MAX_LENGTH);
00789   _frame_id = strndup(header->frame_id, FRAME_ID_MAX_LENGTH);
00790   _width = header->width;
00791   _height = header->height;
00792   _colorspace = (colorspace_t)header->colorspace;
00793 }
00794 
00795 
00796 void
00797 SharedMemoryImageBufferHeader::reset()
00798 {
00799   if ( NULL != _image_id ) {
00800     free(_image_id);
00801     _image_id = NULL;
00802   }
00803   if ( _orig_image_id != NULL ) {
00804     _image_id = strdup(_orig_image_id);
00805   }
00806   if ( NULL != _frame_id ) {
00807     free(_frame_id);
00808     _frame_id = NULL;
00809   }
00810   if ( _orig_frame_id != NULL ) {
00811     _frame_id = strdup(_orig_frame_id);
00812   }
00813   _width =_orig_width;
00814   _height =_orig_height;
00815   _colorspace =_orig_colorspace;
00816   _header = NULL;
00817 }
00818 
00819 
00820 /** Get colorspace.
00821  * @return colorspace
00822  */
00823 colorspace_t
00824 SharedMemoryImageBufferHeader::colorspace() const
00825 {
00826   if ( _header)  return (colorspace_t)_header->colorspace;
00827   else           return _colorspace;
00828 }
00829 
00830 
00831 /** Get width.
00832  * @return image width
00833  */
00834 unsigned int
00835 SharedMemoryImageBufferHeader::width() const
00836 {
00837   if ( _header)  return _header->width;
00838   else           return _width;
00839 }
00840 
00841 
00842 /** Get height.
00843  * @return image height
00844  */
00845 unsigned int
00846 SharedMemoryImageBufferHeader::height() const
00847 {
00848   if ( _header)  return _header->height;
00849   else           return _height;
00850 }
00851 
00852 
00853 /** Get image number
00854  * @return image number
00855  */
00856 const char *
00857 SharedMemoryImageBufferHeader::image_id() const
00858 {
00859   return _image_id;
00860 }
00861 
00862 
00863 /** Get frame ID.
00864  * @return reference coordinate frame ID.
00865  */
00866 const char *
00867 SharedMemoryImageBufferHeader::frame_id() const
00868 {
00869   return _frame_id;
00870 }
00871 
00872 
00873 /** Set image id
00874  * @param image_id image ID
00875  */
00876 void
00877 SharedMemoryImageBufferHeader::set_image_id(const char *image_id)
00878 {
00879   if ( _image_id != NULL)  ::free(_image_id);
00880   _image_id = strdup(image_id);
00881 }
00882 
00883 
00884 /** Set frame ID.
00885  * @param frame_id frame ID
00886  */
00887 void
00888 SharedMemoryImageBufferHeader::set_frame_id(const char *frame_id)
00889 {
00890   if ( _frame_id != NULL)  ::free(_frame_id);
00891   _frame_id = strdup(frame_id);
00892 }
00893 
00894 
00895 /** Get raw header.
00896  * @return raw header.
00897  */
00898 SharedMemoryImageBuffer_header_t *
00899 SharedMemoryImageBufferHeader::raw_header()
00900 {
00901   return _header;
00902 }
00903 
00904 
00905 /** @class SharedMemoryImageBufferLister <fvutils/ipc/shm_image.h>
00906  * Shared memory image buffer lister.
00907  */
00908 
00909 /** Constructor. */
00910 SharedMemoryImageBufferLister::SharedMemoryImageBufferLister()
00911 {
00912 }
00913 
00914 
00915 /** Destructor. */
00916 SharedMemoryImageBufferLister::~SharedMemoryImageBufferLister()
00917 {
00918 }
00919 
00920 
00921 void
00922 SharedMemoryImageBufferLister::print_header()
00923 {
00924   cout << endl << cgreen << "FireVision Shared Memory Segments - Images" << cnormal << endl
00925        << "========================================================================================" << endl
00926        << cdarkgray;
00927   printf ("%-20s %-20s %-10s %-10s %-9s %-16s %-5s %-5s %s\n",
00928           "Image ID", "Frame ID", "ShmID", "Semaphore", "Bytes", "Color Space", "Width", "Height",
00929           "State");
00930   cout << cnormal
00931        << "----------------------------------------------------------------------------------------" << endl;
00932 }
00933 
00934 
00935 void
00936 SharedMemoryImageBufferLister::print_footer()
00937 {
00938 }
00939 
00940 
00941 void
00942 SharedMemoryImageBufferLister::print_no_segments()
00943 {
00944   cout << "No FireVision shared memory segments found" << endl;
00945 }
00946 
00947 
00948 void
00949 SharedMemoryImageBufferLister::print_no_orphaned_segments()
00950 {
00951   cout << "No orphaned FireVision shared memory segments found" << endl;
00952 }
00953 
00954 
00955 void
00956 SharedMemoryImageBufferLister::print_info(const SharedMemoryHeader *header,
00957                                           int shm_id, int semaphore,
00958                                           unsigned int mem_size,
00959                                           const void *memptr)
00960 {
00961 
00962   SharedMemoryImageBufferHeader *h = (SharedMemoryImageBufferHeader *)header;
00963 
00964   const char *colorspace = colorspace_to_string(h->colorspace());
00965 
00966   printf("%-20s %-20s %-10d %-10d %-9u %-16s %-5u %-5u %s%s\n",
00967          h->image_id(), h->frame_id(), shm_id, semaphore, mem_size, colorspace,
00968          h->width(), h->height(),
00969          (SharedMemory::is_swapable(shm_id) ? "S" : ""),
00970          (SharedMemory::is_destroyed(shm_id) ? "D" : "")
00971          );
00972 }
00973 
00974 } // end namespace firevision