QtDisplayStream4.C

00001 /*!@file GUI/QtDisplayStream.C FrameOstream subclass that displays images in a QWidgetStack */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/GUI/QtDisplayStream4.C $
00035 // $Id: QtDisplayStream4.C 12962 2010-03-06 02:13:53Z irock $
00036 //
00037 
00038 #include "GUI/QtDisplayStream4.H"
00039 
00040 #include "Component/GlobalOpts.H"
00041 #include "Component/ModelOptionDef.H"
00042 #include "GUI/QtImageStack.qt.H"
00043 #include "Image/Image.H"
00044 #include "Image/Pixels.H"
00045 #include "QtUtil/ImageConvert4.H"
00046 #include "QtUtil/Util.H" // for argv2qt()
00047 #include "Raster/GenericFrame.H"
00048 #include "Transport/FrameInfo.H"
00049 #include "Transport/FrameOstreamFactory.H"
00050 #include "Transport/TransportOpts.H"
00051 #include "Util/sformat.H"
00052 
00053 #include <QtGui/QApplication>
00054 #include <QtGui/QPixmap>
00055 #include <QtCore/QReadWriteLock>
00056 
00057 // Used by: QtDisplayStream
00058 const ModelOptionDef OPT_QdisplayEcho =
00059   { MODOPT_ARG_STRING, "QdisplayEcho", &MOC_OUTPUT, OPTEXP_CORE,
00060     "Optional output destination for screen-grabs of the Qt display frames.",
00061     "qdisplay-echo", '\0', "<raster|display|mpeg|none>", "none" };
00062 
00063 // Used by: QtDisplayStream
00064 const ModelOptionDef OPT_QdisplayPrefDims =
00065   { MODOPT_ARG(Dims), "QdisplayPrefDims", &MOC_OUTPUT, OPTEXP_CORE,
00066     "Preferred scaled dimensions for Qt display frames, "
00067     "or 0x0 for no preference",
00068     "qdisplay-pref-dims", '\0', "<WxH>", "640x480" };
00069 
00070 // Used by: QtDisplayStream
00071 const ModelOptionDef OPT_QdisplayPrefMaxDims =
00072   { MODOPT_ARG(Dims), "QdisplayPrefMaxDims", &MOC_OUTPUT, OPTEXP_CORE,
00073     "If an image larger than these dimensions is sent to a Qt display "
00074     "frame, initially scale it down to smaller than these dimensions "
00075     "(you can always scale it up later by using the buttons on the "
00076     "Qt display widget",
00077     "qdisplay-pref-max-dims", '\0', "<WxH>", "1600x1200" };
00078 
00079 #define EVT_WRITEFRAME (QEvent::User)
00080 #define EVT_REMOVEFRAME ((QEvent::Type)(int(QEvent::User) + 1))
00081 
00082 namespace
00083 {
00084   // ######################################################################
00085   void *qapp_thread_run(void *c)
00086   {
00087     QtDisplayStream *d = reinterpret_cast<QtDisplayStream *>(c);
00088     return d->run();
00089   }
00090 
00091   // ######################################################################
00092   class QEventWriteFrame : public QEvent
00093   {
00094   public:
00095     QEventWriteFrame(const GenericFrame& fram, const std::string& shortnam, const FrameInfo& auxinf)
00096       : QEvent(EVT_WRITEFRAME), frame(fram), shortname(shortnam), auxinfo(auxinf) { }
00097     virtual ~QEventWriteFrame() { }
00098 
00099     const GenericFrame frame;
00100     const std::string shortname;
00101     const FrameInfo auxinfo;
00102   };
00103 
00104   // ######################################################################
00105   class QEventRemoveFrame : public QEvent
00106   {
00107   public:
00108     QEventRemoveFrame(const std::string& shortnam) : QEvent(EVT_REMOVEFRAME), shortname(shortnam) { }
00109     virtual ~QEventRemoveFrame() { }
00110 
00111     const std::string shortname;
00112   };
00113 }
00114 
00115 // ######################################################################
00116 //! class to filter events
00117 class EventFilt : public QObject {
00118 public:
00119   EventFilt(QtDisplayStream *master) : m(master) { }
00120 
00121   virtual ~EventFilt() { }
00122 
00123 protected:
00124   virtual bool eventFilter(QObject *obj, QEvent *event)
00125   {
00126     if (obj == m->itsWidget) {
00127       if (event->type() == EVT_WRITEFRAME)
00128         {
00129           QEventWriteFrame *e = static_cast<QEventWriteFrame*>(event);
00130           m->itsWidget->addFrame(e->frame, e->shortname, e->auxinfo);
00131           if (!m->itsShown && !m->itsTestMode.getVal()) { m->itsShown = true; m->itsWidget->show(); }
00132           return true;  // the event queue will delete the event
00133         }
00134       else if (event->type() == EVT_REMOVEFRAME)
00135         {
00136           QEventRemoveFrame *e = static_cast<QEventRemoveFrame*>(event);
00137           m->itsWidget->removeFrame(e->shortname);
00138           return true;  // the event queue will delete the event
00139         }
00140       else
00141         return false;
00142     }
00143 
00144     // else, pass the event on to the parent class:
00145     return QObject::eventFilter(obj, event);
00146   }
00147 
00148 private:
00149   QtDisplayStream *m;
00150 };
00151 
00152 
00153 // ######################################################################
00154 QtDisplayStream::QtDisplayStream(OptionManager& mgr,
00155                                  const std::string& descrName,
00156                                  const std::string& tagName) :
00157   FrameOstream(mgr, descrName, tagName),
00158   itsQtEcho(&OPT_QdisplayEcho, this),
00159   itsPreferredDims(&OPT_QdisplayPrefDims, this),
00160   itsPreferredMaxDims(&OPT_QdisplayPrefMaxDims, this),
00161   itsTestMode(&OPT_TestMode, this),
00162   itsWidget(0), itsFilter(0),
00163   itsShown(false),
00164   itsFrameNumber(-1),
00165   itsEcho(), itsReady(false)
00166 { }
00167 
00168 // ######################################################################
00169 void QtDisplayStream::start1()
00170 {
00171   // get our thread going and our app started:
00172   if (0 != pthread_create(&runner, NULL, &qapp_thread_run, this)) LFATAL("couldn't create thread for QApplication");
00173 
00174   while(itsReady == false) usleep(10000);
00175 }
00176 
00177 // ######################################################################
00178 QtDisplayStream::~QtDisplayStream()
00179 {
00180   itsWidget->deleteLater();
00181 }
00182 
00183 // ######################################################################
00184 void* QtDisplayStream::run()
00185 {
00186   // this runs in a thread dedicated to handling the display and events
00187   const char* dpy = getenv("DISPLAY");
00188   const bool havedpy = (dpy != 0 && dpy[0] != '\0');
00189   if (!havedpy) {
00190     if (setenv("DISPLAY", ":0.0", 1) == 0)  LINFO("DISPLAY environment variable not set; assuming DISPLAY=\":0.0\"");
00191     else LFATAL("DISPLAY environment variable not set; can't use Qt without a DISPLAY");
00192   }
00193 
00194   // create a QApplication:
00195   int argc = 1; const char* argv[1] = { "QtDisplayStream" };
00196   QApplication *a = new QApplication(argc, argv2qt(argc, argv));
00197 
00198   // Create our widget:
00199   itsWidget = new QtImageStack;
00200   itsWidget->setPreferredDims(itsPreferredDims.getVal());
00201   itsWidget->setPreferredMaxDims(itsPreferredMaxDims.getVal());
00202 
00203   // Install an event filter so that we get called (in this thread) when new images come in:
00204   itsFilter = new EventFilt(this);
00205   itsWidget->installEventFilter(itsFilter);
00206 
00207   // ready to rock:
00208   itsReady = true;
00209 
00210   // main loop for QApplication:
00211   const int result = a->exec();
00212   LDEBUG("QApplication exit status %d", result);
00213   return reinterpret_cast<void*>(result);
00214 }
00215 
00216 // ######################################################################
00217 void QtDisplayStream::paramChanged(ModelParamBase* const param,
00218                                    const bool valueChanged,
00219                                    ParamClient::ChangeStatus* status)
00220 {
00221   FrameOstream::paramChanged(param, valueChanged, status);
00222 
00223   if (param == &itsQtEcho && itsQtEcho.getVal().length() > 0)
00224     {
00225       if (itsQtEcho.getVal().compare("none") == 0)
00226         {
00227           if (itsEcho.is_valid()) this->removeSubComponent(*itsEcho);
00228           itsEcho = nub::soft_ref<FrameOstream>();
00229         }
00230       else
00231         {
00232           itsEcho = makeFrameOstream(itsQtEcho.getVal(), this->getManager());
00233           this->addSubComponent(itsEcho);
00234           itsEcho->exportOptions(MC_RECURSE);
00235         }
00236     }
00237 }
00238 
00239 // ######################################################################
00240 bool QtDisplayStream::setFrameNumber(int n)
00241 {
00242   if (itsFrameNumber != n)
00243     {
00244       if (itsEcho.is_valid())
00245         {
00246           QPixmap pixmap = QPixmap::grabWidget(itsWidget);
00247           Image<PixRGB<byte> > img = convertToImage4(pixmap);
00248           itsEcho->setFrameNumber(n);
00249           itsEcho->writeRGB(img, "qtecho");
00250         }
00251 
00252       itsFrameNumber = n;
00253     }
00254 
00255   return itsWidget->setFrameNumber(n);
00256 }
00257 
00258 // ######################################################################
00259 void QtDisplayStream::writeFrame(const GenericFrame& frame,
00260                                  const std::string& shortname,
00261                                  const FrameInfo& auxinfo)
00262 {
00263   QEventWriteFrame *event = new QEventWriteFrame(frame, shortname, auxinfo);
00264   QApplication::postEvent(itsWidget, event);
00265 }
00266 
00267 // ######################################################################
00268 bool QtDisplayStream::isVoid() const
00269 {
00270   return itsWidget->isClosed();
00271 }
00272 
00273 // ######################################################################
00274 void QtDisplayStream::closeStream(const std::string& shortname)
00275 {
00276   QEventRemoveFrame *event = new QEventRemoveFrame(shortname);
00277   QApplication::postEvent(itsWidget, event);
00278 }
00279 
00280 // ######################################################################
00281 bool QtDisplayStream::isClosed() const
00282 {
00283   return itsWidget->isClosed();
00284 }
00285 
00286 // ######################################################################
00287 /* So things look consistent in everyone's emacs... */
00288 /* Local Variables: */
00289 /* mode: c++ */
00290 /* indent-tabs-mode: nil */
00291 /* End: */
Generated on Sun May 8 08:04:48 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3