00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef GUI_QTDISPLAYSTREAM_C_DEFINED
00039 #define GUI_QTDISPLAYSTREAM_C_DEFINED
00040
00041 #ifdef INVT_HAVE_QT3
00042
00043 #include "GUI/QtDisplayStream.H"
00044
00045 #include "Component/GlobalOpts.H"
00046 #include "Component/ModelOptionDef.H"
00047 #include "GUI/QtImageStack.H"
00048 #include "Image/Image.H"
00049 #include "Image/Pixels.H"
00050 #include "QtUtil/ImageConvert.H"
00051 #include "QtUtil/Util.H"
00052 #include "Transport/FrameOstreamFactory.H"
00053 #include "Transport/TransportOpts.H"
00054 #include "Util/sformat.H"
00055
00056 #include <qapplication.h>
00057 #include <qpixmap.h>
00058
00059
00060 const ModelOptionDef OPT_QdisplayEcho =
00061 { MODOPT_ARG_STRING, "QdisplayEcho", &MOC_OUTPUT, OPTEXP_CORE,
00062 "Optional output destination for screen-grabs of the Qt display frames.",
00063 "qdisplay-echo", '\0', "<raster|display|mpeg|none>", "none" };
00064
00065
00066 const ModelOptionDef OPT_QdisplayPrefDims =
00067 { MODOPT_ARG(Dims), "QdisplayPrefDims", &MOC_OUTPUT, OPTEXP_CORE,
00068 "Preferred scaled dimensions for Qt display frames, "
00069 "or 0x0 for no preference",
00070 "qdisplay-pref-dims", '\0', "<WxH>", "640x480" };
00071
00072
00073 const ModelOptionDef OPT_QdisplayPrefMaxDims =
00074 { MODOPT_ARG(Dims), "QdisplayPrefMaxDims", &MOC_OUTPUT, OPTEXP_CORE,
00075 "If an image larger than these dimensions is sent to a Qt display "
00076 "frame, initially scale it down to smaller than these dimensions "
00077 "(you can always scale it up later by using the buttons on the "
00078 "Qt display widget",
00079 "qdisplay-pref-max-dims", '\0', "<WxH>", "1600x1200" };
00080
00081 namespace
00082 {
00083 QApplication* qapp = 0;
00084
00085 pthread_once_t qapp_init_once = PTHREAD_ONCE_INIT;
00086 pthread_t qapp_thread;
00087
00088 void* qapp_thread_run(void* app)
00089 {
00090 QApplication* a = static_cast<QApplication*>(app);
00091
00092
00093
00094
00095 const int result = a->exec();
00096 LDEBUG("QApplication exit status %d", result);
00097 return reinterpret_cast<void*>(result);
00098 }
00099
00100 void qapp_thread_init()
00101 {
00102 ASSERT(qapp == 0);
00103
00104 const char* dpy = getenv("DISPLAY");
00105 const bool havedpy = (dpy != 0 && dpy[0] != '\0');
00106 if (!havedpy)
00107 {
00108 if (setenv("DISPLAY", ":0.0", 1) == 0)
00109 LINFO("the DISPLAY environment variable is not set; "
00110 "assuming DISPLAY=\":0.0\"");
00111 else
00112 LFATAL("the DISPLAY environment variable is not set; "
00113 "can't use Qt without a DISPLAY");
00114 }
00115
00116
00117
00118
00119
00120
00121
00122 int argc = 1;
00123 const char* argv[2] = { "QtDisplayStream", 0 };
00124 qapp = new QApplication(argc, argv2qt(argc, argv));
00125
00126 if (0 != pthread_create(&qapp_thread, NULL, &qapp_thread_run, qapp))
00127 LFATAL("couldn't create thread for QApplication");
00128 }
00129 }
00130
00131
00132 class QAppLockClass
00133 {
00134 public:
00135 QAppLockClass(QApplication* qapp) : itsApp(qapp)
00136 {
00137 itsApp->lock();
00138 }
00139
00140 ~QAppLockClass()
00141 {
00142 itsApp->unlock();
00143 }
00144
00145 private:
00146 QAppLockClass(const QAppLockClass&);
00147 QAppLockClass& operator=(const QAppLockClass&);
00148
00149 QApplication* itsApp;
00150 };
00151
00152
00153 #define QAPP_LOCK(qapp) QAppLockClass anonymous_qapp_lock_(qapp)
00154
00155
00156 QtDisplayStream::QtDisplayStream(OptionManager& mgr,
00157 const std::string& descrName,
00158 const std::string& tagName)
00159 :
00160 FrameOstream(mgr, descrName, tagName),
00161 itsQtEcho(&OPT_QdisplayEcho, this),
00162 itsPreferredDims(&OPT_QdisplayPrefDims, this),
00163 itsPreferredMaxDims(&OPT_QdisplayPrefMaxDims, this),
00164 itsTestMode(&OPT_TestMode, this),
00165 itsWidget(0),
00166 itsShown(false),
00167 itsFrameNumber(-1),
00168 itsEcho()
00169 {
00170 pthread_once(&qapp_init_once, &qapp_thread_init);
00171
00172 ASSERT(qapp != 0);
00173
00174 QAPP_LOCK(qapp);
00175 itsWidget = new QtImageStack;
00176 }
00177
00178
00179 QtDisplayStream::~QtDisplayStream()
00180 {
00181 itsWidget->deleteLater();
00182 }
00183
00184
00185 void QtDisplayStream::paramChanged(ModelParamBase* const param,
00186 const bool valueChanged,
00187 ParamClient::ChangeStatus* status)
00188 {
00189 FrameOstream::paramChanged(param, valueChanged, status);
00190
00191 if (param == &itsQtEcho && itsQtEcho.getVal().length() > 0)
00192 {
00193 if (itsQtEcho.getVal().compare("none") == 0)
00194 {
00195 if (itsEcho.is_valid())
00196 this->removeSubComponent(*itsEcho);
00197
00198 itsEcho = nub::soft_ref<FrameOstream>();
00199 }
00200 else
00201 {
00202 itsEcho = makeFrameOstream(itsQtEcho.getVal(),
00203 this->getManager());
00204 this->addSubComponent(itsEcho);
00205 itsEcho->exportOptions(MC_RECURSE);
00206 }
00207 }
00208 else if (param == &itsPreferredDims)
00209 {
00210 itsWidget->setPreferredDims(itsPreferredDims.getVal());
00211 }
00212 else if (param == &itsPreferredMaxDims)
00213 {
00214 itsWidget->setPreferredMaxDims(itsPreferredMaxDims.getVal());
00215 }
00216 }
00217
00218
00219 bool QtDisplayStream::setFrameNumber(int n)
00220 {
00221 if (itsFrameNumber != n)
00222 {
00223 if (itsEcho.is_valid())
00224 {
00225 QAPP_LOCK(qapp);
00226 QPixmap pixmap = QPixmap::grabWidget(itsWidget);
00227 Image<PixRGB<byte> > img = convertToImage(pixmap);
00228 itsEcho->setFrameNumber(n);
00229 itsEcho->writeRGB(img, "qtecho");
00230 }
00231
00232 itsFrameNumber = n;
00233 }
00234
00235 return itsWidget->setFrameNumber(n);
00236 }
00237
00238
00239 void QtDisplayStream::writeFrame(const GenericFrame& frame,
00240 const std::string& shortname,
00241 const FrameInfo& auxinfo)
00242 {
00243 QAPP_LOCK(qapp);
00244 itsWidget->addFrame(frame, shortname, auxinfo);
00245 if (!itsShown && !itsTestMode.getVal())
00246 { itsShown = true; itsWidget->show(); }
00247 }
00248
00249
00250 bool QtDisplayStream::isVoid() const
00251 {
00252 return itsWidget->isClosed();
00253 }
00254
00255
00256 void QtDisplayStream::closeStream(const std::string& shortname)
00257 {
00258 QAPP_LOCK(qapp);
00259 itsWidget->removeFrame(shortname);
00260 }
00261
00262
00263 bool QtDisplayStream::isClosed() const
00264 {
00265 return itsWidget->isClosed();
00266 }
00267
00268 #endif // INVT_HAVE_QT3
00269
00270
00271
00272
00273
00274
00275
00276
00277 #endif // GUI_QTDISPLAYSTREAM_C_DEFINED