PageRenderTime 35ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/ATF2/control-software/epics-3.14.10/extensions/src/edm/videowidget/TwoDProfileMonitor.cc

http://atf2flightsim.googlecode.com/
C++ | 1542 lines | 1065 code | 257 blank | 220 comment | 83 complexity | 636d57c2301506e40a6874824646ce06 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause
  1. // g++ -shared -o TwoDProfileMonitor.so TwoDProfileMonitor.cc -g -O -Wall -ansi
  2. // -pedantic -I/ade/epics/supTop/extensions/R3.14.4/src/edm/util
  3. // -I/ade/epics/supTop/extensions/R3.14.4/src/edm/lib
  4. // -I/ade/epics/supTop/extensions/R3.14.4/src/edm/pvlib
  5. // -I /ade/epics/supTop/base/R3.14.4/include -I/usr/X11R6/include
  6. // -L/usr/X11R6/lib widget.cc -lXpm
  7. // To Do: class initialization, serialization, configuration (all related)
  8. // Any chance of allowing overlapped widgets to be on top?
  9. #define VIDEO_MAX_LOAD_FACTOR 4
  10. #define VIDEO_MAX_DATA_WIDTH 10000
  11. #define VIDEO_MAX_DATA_HEIGHT 10000
  12. #define VIDEO_NBITSPERPIXEL_DEFAULT 8
  13. #define VIDEO_MAJOR_VERSION 4
  14. #define VIDEO_MINOR_VERSION 1
  15. #define VIDEO_RELEASE 1
  16. #include <time.h>
  17. #include <iostream>
  18. //#ifdef SOLARIS
  19. //#include <iostream.h>
  20. //#else
  21. //#include <stream.h>
  22. //#endif
  23. #include <act_grf.h>
  24. #include <act_win.h>
  25. #include <app_pkg.h>
  26. #include <entry_form.h>
  27. #include <pv_factory.h>
  28. #include "edm.version"
  29. //#include "widget.h"
  30. #include "image.h"
  31. void _edmDebug ( void );
  32. // our widget class
  33. class TwoDProfileMonitor : public activeGraphicClass
  34. {
  35. // standard colours for various PV states
  36. pvColorClass pvColour;
  37. // width of data (fixed or from PV)
  38. int dataWidth, dataHeight;
  39. int pvBasedDataSize;
  40. // globals for the edit popup
  41. int xBuf;
  42. int yBuf;
  43. int wBuf;
  44. int hBuf;
  45. int nBitsPerPixelBuf;
  46. char dataPvBuf[activeGraphicClass::MAX_PV_NAME+1];
  47. char widthPvBuf[activeGraphicClass::MAX_PV_NAME+1];
  48. char heightPvBuf[activeGraphicClass::MAX_PV_NAME+1];
  49. expStringClass dataPvStr, widthPvStr, heightPvStr;
  50. ProcessVariable *dataPv, *widthPv, *heightPv;
  51. // text stuff (for edit mode drawing)
  52. char *textFontTag;
  53. int textAlignment;
  54. int textColour;
  55. int initialDataConnection, initialWidthConnection, initialHeightConnection;
  56. int needConnectInit, needInfoInit, needDraw, needRefresh;
  57. unsigned char pvNotConnectedMask;
  58. int dataPvExists, widthPvExists, heightPvExists;
  59. int init, active, activeMode;
  60. struct timeval lasttv;
  61. unsigned long average_time_usec;
  62. int opComplete;
  63. int nBitsPerPixel;
  64. // widget-specific stuff
  65. //widgetData wd;
  66. //Widget twoDWidget;
  67. // image object
  68. imageClass *img;
  69. // constructor "helper" function
  70. void constructCommon (void);
  71. public:
  72. // constructors/destructor
  73. TwoDProfileMonitor (void);
  74. TwoDProfileMonitor (const TwoDProfileMonitor &s);
  75. virtual ~TwoDProfileMonitor (void);
  76. // Called when the data process variable connects or disconnects
  77. static void monitorDataConnectState (ProcessVariable *pv,
  78. void *userarg );
  79. // Called when the width process variable connects or disconnects
  80. static void monitorWidthConnectState (ProcessVariable *pv,
  81. void *userarg );
  82. // Called when the height process variable connects or disconnects
  83. static void monitorHeightConnectState (ProcessVariable *pv,
  84. void *userarg );
  85. // Called when the value of the data process variable changes
  86. static void dataUpdate (ProcessVariable *pv,
  87. void *userarg );
  88. // Called when the value of the width or height process variable changes
  89. static void sizeUpdate (ProcessVariable *pv,
  90. void *userarg );
  91. static void grabButtonEvent (Widget w, XtPointer closure, XEvent* event,
  92. Boolean* b)
  93. {
  94. TwoDProfileMonitor *me = (TwoDProfileMonitor *) closure;
  95. // normalize dimensions (button and motion events store x,y in the
  96. // same location)
  97. event->xbutton.x += me->getX0 ();
  98. event->xbutton.y += me->getY0 ();
  99. // now send this event to EDM
  100. XtDispatchEventToWidget (me->actWin->executeWidget, event);
  101. *b = False; // terminate this "dispatch path"
  102. }
  103. virtual int draw ( void );
  104. virtual int drawActive ( void );
  105. // called in response to "cut" command
  106. virtual int erase ( void );
  107. virtual int activate (int pass, void *ptr);
  108. // apply the results of either "Apply" or "OK" buttons
  109. void applyEditChanges (void);
  110. // user hit the "OK" button on the edit popup
  111. static void editOK (Widget w,
  112. XtPointer client,
  113. XtPointer call );
  114. // user hit the "Apply" button on the edit popup
  115. static void editApply (Widget w,
  116. XtPointer client,
  117. XtPointer call );
  118. // user hit the "Cancel" button on the edit popup
  119. static void editCancel (Widget w,
  120. XtPointer client,
  121. XtPointer call );
  122. // user hit the "Cancel" button on the edit popup during widget creation
  123. static void editCancelCreate (Widget w,
  124. XtPointer client,
  125. XtPointer call );
  126. // "helper" function for editing widget under a variety of circumstances
  127. void editCommon ( activeWindowClass *actWin, entryFormClass *ef,
  128. int create = 0 ) ;
  129. // user created object from GUI (after drawing rectangle)
  130. virtual int createInteractive (activeWindowClass *actWin,
  131. int x,
  132. int y,
  133. int w,
  134. int h );
  135. // object created from saved description on disk
  136. virtual int createFromFile (FILE *fptr,
  137. char *name,
  138. activeWindowClass *actWin );
  139. // object created from ????
  140. virtual int importFromXchFile (FILE *fptr,
  141. char *name,
  142. activeWindowClass *actWin );
  143. // save to disk
  144. virtual int save ( FILE *fptr );
  145. virtual int edit ( void );
  146. // ========================================================
  147. // execute mode widget functions
  148. virtual int deactivate ( int pass );
  149. virtual int expand1st (int numMacros,
  150. char *macros[],
  151. char *expansions[] )
  152. {
  153. int stat;
  154. stat = dataPvStr.expand1st (numMacros, macros, expansions);
  155. if (stat)
  156. stat = widthPvStr.expand1st (numMacros, macros, expansions);
  157. if (stat)
  158. stat = heightPvStr.expand1st (numMacros, macros, expansions);
  159. return stat;
  160. }
  161. // currently only used by mux devices (which we are not)
  162. virtual int expand2nd (int numMacros,
  163. char *macros[],
  164. char *expansions[] )
  165. {
  166. int stat;
  167. stat = dataPvStr.expand2nd (numMacros, macros, expansions);
  168. if (stat)
  169. stat = widthPvStr.expand2nd (numMacros, macros, expansions);
  170. if (stat)
  171. stat = heightPvStr.expand2nd (numMacros, macros, expansions);
  172. return stat;
  173. }
  174. // currently only used by mux devices (which we are not)
  175. virtual int containsMacros ( void )
  176. {
  177. return dataPvStr.containsPrimaryMacros () ? 1 : 0;
  178. }
  179. template<class T> double * to_double (unsigned size, const T * data)
  180. {
  181. double * temp = (double *) malloc (sizeof (double) * size);
  182. for (unsigned s = 0; s < size; ++s)
  183. {
  184. temp[s] = data[s];
  185. }
  186. return temp;
  187. }
  188. static double *int_to_double (size_t s, const int *i)
  189. {
  190. double *d = (double *) malloc (sizeof (double)* s);
  191. if (!d) return d;
  192. for (size_t index = 0; index < s; index++)
  193. {
  194. d[index] = i[index];
  195. }
  196. return d;
  197. }
  198. // here is where we deal with updating the execute-mode widget (data and
  199. // connect state)
  200. virtual void executeDeferred ( void )
  201. {
  202. int ni, nc, nr;
  203. struct timeval tv;
  204. #ifdef DEBUG
  205. printf ("Start of TwoDProfMon::executeDeferred\n");
  206. #endif
  207. if (actWin->isIconified)
  208. {
  209. #ifdef DEBUG
  210. printf ("TwoDProfMon::execDeferred return - window iconified\n");
  211. #endif
  212. return;
  213. }
  214. // The widget may not be able to handle video data as fast as it is
  215. // produced (particularly if it is displaying a large image on a
  216. // remote X display). If this happens, unprocessed channel access
  217. // data is queued for transmission in the IOC and eventually some
  218. // has to be discarded. What is lost is not necessarily video data,
  219. // with the result that other edm widgets appear to stop working.
  220. // To avoid this happening, we must make sure we receive all screen
  221. // images that are produced and ignore any we haven't time to put out.
  222. // The following code does this.
  223. gettimeofday (&tv, 0);
  224. unsigned long elapsedusec = (tv.tv_sec - lasttv.tv_sec) * 1000000
  225. + tv.tv_usec - lasttv.tv_usec;
  226. #ifdef DEBUG
  227. printf ("TwoDProfMon::executeDeferred - elapsed time = %lu\n",
  228. elapsedusec);
  229. #endif
  230. if (elapsedusec < average_time_usec * VIDEO_MAX_LOAD_FACTOR)
  231. {
  232. #ifdef DEBUG
  233. printf ("TwoDProfMon::execDef return - elapsed time too short\n");
  234. #endif
  235. return;
  236. }
  237. lasttv.tv_sec = tv.tv_sec;
  238. lasttv.tv_usec = tv.tv_usec;
  239. #ifdef DEBUG
  240. printf ("Start of processing for TwoDProfMon::executeDeferred\n");
  241. #endif
  242. actWin->appCtx->proc->lock ();
  243. nc = needConnectInit; needConnectInit = 0;
  244. ni = needInfoInit; needInfoInit = 0;
  245. nr = needRefresh; needRefresh = 0;
  246. actWin->remDefExeNode (aglPtr);
  247. actWin->appCtx->proc->unlock ();
  248. if (!activeMode)
  249. {
  250. #ifdef DEBUG
  251. printf ("TwoDProfMon::executeDeferred return - not active mode\n");
  252. #endif
  253. return;
  254. }
  255. lasttv.tv_sec = tv.tv_sec;
  256. lasttv.tv_usec = tv.tv_usec;
  257. if (nc)
  258. {
  259. ni = 1;
  260. }
  261. if (ni)
  262. {
  263. active = 1;
  264. init = 1;
  265. if (initialDataConnection)
  266. {
  267. initialDataConnection = 0;
  268. #ifdef DEBUG
  269. printf (
  270. "TwoDProfMon::execDeferred - add data value callback\n");
  271. #endif
  272. dataPv->add_value_callback ( dataUpdate, this );
  273. }
  274. if (initialWidthConnection)
  275. {
  276. initialWidthConnection = 0;
  277. #ifdef DEBUG
  278. printf (
  279. "TwoDProfMon::execDeferred - add width value callback\n");
  280. #endif
  281. widthPv->add_value_callback ( sizeUpdate, this );
  282. }
  283. if (initialHeightConnection)
  284. {
  285. initialHeightConnection = 0;
  286. #ifdef DEBUG
  287. printf (
  288. "TwoDProfMon::execDeferred - add height value callback\n");
  289. #endif
  290. heightPv->add_value_callback ( sizeUpdate, this );
  291. }
  292. }
  293. // need to check if we're being updated because of width change
  294. #ifdef DEBUG
  295. printf ("executeDeferred (TwoDMon.cc) - pvBasedDataWidth = %d\n",
  296. pvBasedDataWidth);
  297. printf ("executeDeferred (TwoDMon.cc) - widthPv = %x\n", (int) widthPv);
  298. if ( widthPv ) {
  299. printf ("executeDeferred (TwoDMon.cc) - is_valid = %d\n",
  300. widthPv->is_valid ());
  301. }
  302. #endif
  303. if (pvBasedDataSize && widthPv && widthPv->is_valid ())
  304. {
  305. #ifdef DEBUG
  306. printf ("executeDeferred (TwoDMon.cc) - pv based width\n");
  307. #endif
  308. dataWidth = (int) widthPv->get_int ();
  309. #if 0
  310. switch (widthPv->get_type ().type)
  311. {
  312. case ProcessVariable::Type::real:
  313. dataWidth = (int) widthPv->get_double ();
  314. break;
  315. case ProcessVariable::Type::integer:
  316. dataWidth = (int) widthPv->get_int ();
  317. break;
  318. default:
  319. dataWidth = -1;
  320. break;
  321. }
  322. #endif
  323. #ifdef DEBUG
  324. printf ("executeDeferred (TwoDMon.cc) - width = %d\n", dataWidth);
  325. #endif
  326. if (heightPv && heightPv->is_valid ())
  327. {
  328. dataHeight = (int) heightPv->get_int ();
  329. #if 0
  330. switch (heightPv->get_type ().type)
  331. {
  332. case ProcessVariable::Type::real:
  333. dataHeight = (int) heightPv->get_double ();
  334. break;
  335. case ProcessVariable::Type::integer:
  336. dataHeight = (int) heightPv->get_int ();
  337. break;
  338. default:
  339. dataHeight = -1;
  340. }
  341. #endif
  342. }
  343. }
  344. if (dataWidth <= 0 || dataWidth > VIDEO_MAX_DATA_WIDTH ||
  345. dataHeight < 0 || dataHeight > VIDEO_MAX_DATA_HEIGHT)
  346. {
  347. printf (
  348. "TwoDProfMon::execDef - return dataWidth %d dataHeight %d\n",
  349. dataWidth, dataHeight);
  350. return;
  351. }
  352. #if 0
  353. if ((dataHeight != 0) &&
  354. ((dataHeight * dataWidth) != (int)dataPv->get_dimension ()))
  355. {
  356. // Data height or width has changed. Ignore the current data which
  357. // is the wrong size. Cancel subscription and restart it to make
  358. // IOC / Channel Access send data of the correct size.
  359. #ifdef DEBUG
  360. printf (
  361. "TwoDProfMon::execDef - resubscribe - new dataW %d dataH %d\n",
  362. dataWidth, dataHeight);
  363. #endif
  364. //actWin->appCtx->proc->lock ();
  365. dataPv->remove_value_callback ( dataUpdate, this );
  366. dataPv->remove_conn_state_callback (monitorDataConnectState, this);
  367. dataPv->release ();
  368. dataPv = the_PV_Factory->create ( dataPvStr.getExpanded () );
  369. dataPv->add_conn_state_callback ( monitorDataConnectState, this );
  370. dataPv->add_value_callback ( dataUpdate, this );
  371. //actWin->appCtx->proc->unlock ();
  372. return;
  373. }
  374. //actWin->appCtx->proc->lock ();
  375. #endif
  376. #ifdef DEBUG
  377. printf ("executeDeferred (TwoDMon.cc) - before data PV type switch\n");
  378. #endif
  379. if (dataPv && dataPv->is_valid ())
  380. {
  381. switch (dataPv->get_type ().type)
  382. {
  383. case ProcessVariable::Type::real:
  384. // printf ("real\n");
  385. // ??????????
  386. //widgetNewDisplayData (
  387. // wd, dataPv->get_time_t (), dataPv->get_nano (),
  388. // (unsigned long) w, (unsigned long) h, dataWidth,
  389. // (dataHeight > 0 ? dataHeight
  390. // : dataPv->get_dimension () / dataWidth),
  391. // (const double *) dataPv->get_double_array ());
  392. img->update( dataWidth,
  393. (dataHeight > 0 ? dataHeight
  394. : dataPv->get_dimension () / dataWidth),
  395. (double *) dataPv->get_double_array() );
  396. if ( img->validImage() ) {
  397. XPutImage( actWin->d, XtWindow(actWin->executeWidget),
  398. actWin->executeGc.normGC(), img->ximage(),
  399. 0, 0, x, y, w, h );
  400. }
  401. break;
  402. case ProcessVariable::Type::text:
  403. {
  404. double * temp = to_double<char>(
  405. dataPv->get_dimension (),
  406. dataPv->get_char_array ());
  407. #ifdef DEBUG
  408. printf ("TwoDProfMon::execDef calling widgetNewDispData\n");
  409. #endif
  410. // ????????????????????
  411. //widgetNewDisplayData (
  412. // wd, dataPv->get_time_t (), dataPv->get_nano (),
  413. // (unsigned long)w, (unsigned long) h, dataWidth,
  414. // (dataHeight > 0 ? dataHeight
  415. // : dataPv->get_dimension() / dataWidth),
  416. // temp);
  417. img->update( dataWidth,
  418. (dataHeight > 0 ? dataHeight
  419. : dataPv->get_dimension () / dataWidth),
  420. temp );
  421. free (temp);
  422. if ( img->validImage() ) {
  423. XPutImage( actWin->d, XtWindow(actWin->executeWidget),
  424. actWin->executeGc.normGC(), img->ximage(),
  425. 0, 0, x, y, w, h );
  426. }
  427. }
  428. break;
  429. case ProcessVariable::Type::integer:
  430. // printf ("int\n");
  431. {
  432. double* temp = int_to_double (dataPv->get_dimension (),
  433. dataPv->get_int_array ());
  434. // ?????????????????
  435. //widgetNewDisplayData (
  436. // wd, dataPv->get_time_t (), dataPv->get_nano (),
  437. // (unsigned long) w, (unsigned long) h, dataWidth,
  438. // (dataHeight > 0 ? dataHeight
  439. // : dataPv->get_dimension() / dataWidth),
  440. // temp);
  441. img->update( dataWidth,
  442. (dataHeight > 0 ? dataHeight
  443. : dataPv->get_dimension () / dataWidth),
  444. temp );
  445. free (temp);
  446. if ( img->validImage() ) {
  447. XPutImage( actWin->d, XtWindow(actWin->executeWidget),
  448. actWin->executeGc.normGC(), img->ximage(),
  449. 0, 0, x, y, w, h );
  450. }
  451. }
  452. break;
  453. default:
  454. // nothing to do!
  455. break;
  456. }
  457. // ??????????????????????
  458. //widgetNewDisplayInfo (wd, true, dataPv->get_status (),
  459. // dataPv->get_severity ());
  460. }
  461. else
  462. {
  463. // ????????????????
  464. //widgetNewDisplayInfo (wd, false, 0, 0);
  465. }
  466. // actWin->remDefExeNode (aglPtr);
  467. // actWin->appCtx->proc->unlock ();
  468. // Get approx average elapsed time for call - no point in being precise
  469. gettimeofday (&tv, 0);
  470. elapsedusec = (tv.tv_sec - lasttv.tv_sec) * 1000000 + tv.tv_usec - lasttv.tv_usec;
  471. if (!average_time_usec)
  472. average_time_usec = elapsedusec;
  473. else
  474. average_time_usec = (average_time_usec * 9 + elapsedusec) / 10;
  475. #ifdef DEBUG
  476. printf ("End of TwoDProfMon::execDef - average elapsed time = %lu\n",
  477. average_time_usec);
  478. #endif
  479. }
  480. // let the user select among a field of functional names for drag-n-drop
  481. virtual char *firstDragName ( void ){ return "data PV"; };
  482. virtual char *nextDragName ( void ){ return NULL; } ;
  483. virtual char *dragValue ( int i )
  484. { return i ? NULL : dataPvStr.getExpanded (); };
  485. // yes we use PVs, therefore we support drag-n-drop and info dialogs
  486. virtual int atLeastOneDragPv (int x,
  487. int y ){ return 1; };
  488. // this one is to support an info dialog about widget-related PVs
  489. virtual void getPvs (int max,
  490. ProcessVariable *pvs[],
  491. int *n ){ *n = 1; pvs[0] = dataPv;};
  492. // This is a funny interface. It seems that the idea is to have a generic
  493. // interface to all widgets with a "standard" set of parameters (e.g.
  494. // control PV). However, there doesn't seem to be a clean way to associate
  495. // widget values with their generic equivalents. I.e. the generic "control
  496. // PV" name is maintained in actWin->allSelectedCtlPvName[0]. One *could*
  497. // use that data storage for the control PV for a widget, but it is not
  498. // obvious (to me) that that interface is encouraged (or is guaranteed to
  499. // be supported in the future).
  500. // what I will do here is what most of the widgets do, which is to pick
  501. // out of the user supplied values anything that I see an obvious equivalent
  502. // in my "private" parameters, and copy in that data. Note that my "private"
  503. // equivalent might change (via the "edit" popup, and that change will not
  504. // be reflected in this popup. I *could* "blank out" the fields I use after
  505. // copying out the data, but that is not the behavior implemented in other
  506. // widgets.
  507. // I think that the *good* thing about this interface is that it hints at
  508. // what parameters each widget should support
  509. virtual void changePvNames (int flag,
  510. int numCtlPvs,
  511. char *ctlPvs[],
  512. int numReadbackPvs,
  513. char *readbackPvs[],
  514. int numNullPvs,
  515. char *nullPvs[],
  516. int numVisPvs,
  517. char *visPvs[],
  518. int numAlarmPvs,
  519. char *alarmPvs[] )
  520. {
  521. if ((flag & ACTGRF_READBACKPVS_MASK) && numReadbackPvs)
  522. dataPvStr.setRaw (readbackPvs[0]);
  523. }
  524. // see previous comments
  525. virtual void changeDisplayParams (unsigned int flag,
  526. char *fontTag,
  527. int alignment,
  528. char *ctlFontTag,
  529. int ctlAlignment,
  530. char *btnFontTag,
  531. int btnAlignment,
  532. int textFgColour,
  533. int fg1Colour,
  534. int fg2Colour,
  535. int offsetColour,
  536. int bgColour,
  537. int topShadowColour,
  538. int botShadowColour )
  539. {
  540. if (flag & ACTGRF_FONTTAG_MASK) textFontTag = fontTag; // strcpy???
  541. if (flag & ACTGRF_ALIGNMENT_MASK) textAlignment = alignment;
  542. if (flag & ACTGRF_TEXTFGCOLOR_MASK) textColour = textFgColour;
  543. }
  544. private:
  545. TwoDProfileMonitor &operator=(const TwoDProfileMonitor &s);
  546. };
  547. // class for read/write tags
  548. // I like to break this out because it forces me to
  549. // enumerate all the data memebers that are saved
  550. // It is more work, but less error-prone (IMHO)
  551. class TwoDProfileMonitorTags : public tagClass
  552. {
  553. public:
  554. TwoDProfileMonitorTags (void){ init (); }
  555. ~TwoDProfileMonitorTags (){}
  556. int read (TwoDProfileMonitor* mon,
  557. FILE *fptr,
  558. int *x, int *y, int *w, int *h, int *nBitsPerPixel,
  559. expStringClass *dataPvStr,
  560. expStringClass *widthPvStr,
  561. expStringClass *heightPvStr,
  562. int *dataWidth,
  563. int *pvBasedDataSize)
  564. {
  565. int major, minor, release;
  566. int stat;
  567. loadR ("beginObjectProperties" );
  568. loadR ( "major", &major );
  569. loadR ( "minor", &minor );
  570. loadR ( "release", &release );
  571. loadR ( "x", x );
  572. loadR ( "y", y );
  573. loadR ( "w", w );
  574. loadR ( "h", h );
  575. loadR ( "dataPvStr", dataPvStr, (char *) "" );
  576. loadR ( "widthPvStr", widthPvStr, (char *) "" );
  577. loadR ( "heightPvStr", heightPvStr, (char *) "" );
  578. loadR ( "dataWidth", dataWidth);
  579. loadR ( "pvBasedDataSize", pvBasedDataSize);
  580. loadR ( "nBitsPerPixel", nBitsPerPixel );
  581. stat = readTags ( fptr, "endObjectProperties" );
  582. if (major > VIDEO_MAJOR_VERSION ||
  583. (major == VIDEO_MAJOR_VERSION && minor > VIDEO_MINOR_VERSION))
  584. {
  585. // edl file was produced by a more recent version of edm than
  586. // this and we can't predict the future
  587. mon->postIncompatable ();
  588. return 0;
  589. }
  590. if (major < VIDEO_MAJOR_VERSION)
  591. {
  592. // Major version changes render old edl files incompatible
  593. mon->postIncompatable ();
  594. return 0;
  595. }
  596. return stat;
  597. }
  598. int write (FILE *fptr,
  599. int *x, int *y, int *w, int *h, int *nBitsPerPixel,
  600. expStringClass *dataPvStr,
  601. expStringClass *widthPvStr,
  602. expStringClass *heightPvStr,
  603. int *dataWidth,
  604. int *pvBasedDataSize)
  605. {
  606. int major, minor, release;
  607. major = VIDEO_MAJOR_VERSION;
  608. minor = VIDEO_MINOR_VERSION;
  609. release = VIDEO_RELEASE;
  610. loadW ("beginObjectProperties" );
  611. loadW ( "major", &major );
  612. loadW ( "minor", &minor );
  613. loadW ( "release", &release );
  614. loadW ( "x", x );
  615. loadW ( "y", y );
  616. loadW ( "w", w );
  617. loadW ( "h", h );
  618. loadW ( "dataPvStr", dataPvStr, (char *) "" );
  619. loadW ( "widthPvStr", widthPvStr, (char *) "" );
  620. loadW ( "heightPvStr", heightPvStr, (char *) "" );
  621. loadW ( "dataWidth", dataWidth);
  622. loadW ( "pvBasedDataSize", pvBasedDataSize);
  623. loadW ( "nBitsPerPixel", nBitsPerPixel );
  624. loadW ( "endObjectProperties" );
  625. loadW ( "" );
  626. return writeTags ( fptr );
  627. }
  628. private:
  629. TwoDProfileMonitorTags (const TwoDProfileMonitorTags &s);
  630. TwoDProfileMonitorTags &operator= (const TwoDProfileMonitorTags &s);
  631. };
  632. // stuff needed for EDM to load from DLL
  633. extern "C"
  634. {
  635. void *create_TwoDProfileMonitorClassPtr ( void )
  636. {
  637. return (new TwoDProfileMonitor ());
  638. }
  639. }
  640. extern "C"
  641. {
  642. void *clone_TwoDProfileMonitorClassPtr ( void *s )
  643. {
  644. return (new TwoDProfileMonitor (*(TwoDProfileMonitor *)s));
  645. }
  646. }
  647. // Support registration
  648. #include "environment.str"
  649. typedef struct libRecTag
  650. {
  651. char *className;
  652. char *typeName;
  653. char *text;
  654. } libRecType, *libRecPtr;
  655. static int libRecIndex = 0;
  656. static libRecType libRec[] =
  657. {
  658. { "TwoDProfileMonitorClass", global_str2, "Hoff Video" }
  659. };
  660. extern "C"
  661. {
  662. char *version ( void ) {
  663. static char *v = VERSION;
  664. return v;
  665. }
  666. char *author ( void ) {
  667. static char *a = "Lawrence T. Hoff (hoff@bnl.gov)";
  668. return a;
  669. }
  670. int firstRegRecord (char **className,
  671. char **typeName,
  672. char **text )
  673. {
  674. libRecIndex = 0;
  675. *className = libRec[libRecIndex].className;
  676. *typeName = libRec[libRecIndex].typeName;
  677. *text = libRec[libRecIndex].text;
  678. return 0; // OK
  679. }
  680. int nextRegRecord (char **className,
  681. char **typeName,
  682. char **text )
  683. {
  684. if (libRecIndex >= sizeof (libRec)/sizeof (libRecType) - 1)
  685. return -1; // done
  686. ++libRecIndex;
  687. *className = libRec[libRecIndex].className;
  688. *typeName = libRec[libRecIndex].typeName;
  689. *text = libRec[libRecIndex].text;
  690. return 0; // OK
  691. }
  692. }
  693. void TwoDProfileMonitor::constructCommon (void)
  694. {
  695. /* start off not knowing image data width */
  696. pvBasedDataSize = 0;
  697. dataWidth = -1;
  698. dataHeight = 0; // 0 if no PV supplied which is OK, -1 if invalid PV
  699. activeMode = 0;
  700. // ???????????????
  701. //wd = widgetCreate ();
  702. //twoDWidget = NULL;
  703. name = "TwoDProfileMonitorClass";
  704. dataPvStr.setRaw ("");
  705. widthPvStr.setRaw ("");
  706. heightPvStr.setRaw ("");
  707. dataPv = NULL;
  708. widthPv = NULL;
  709. heightPv = NULL;
  710. strcpy (dataPvBuf, ""); // just to be safe
  711. strcpy (widthPvBuf, ""); // just to be safe
  712. strcpy (heightPvBuf, ""); // just to be safe
  713. //twoDWidget = NULL;
  714. average_time_usec = 0;
  715. #if (0)
  716. // text stuff (for edit mode drawing)
  717. char *textFontTag;
  718. int textAlignment;
  719. int textColour;
  720. #endif
  721. img = NULL;
  722. }
  723. TwoDProfileMonitor::TwoDProfileMonitor (void) : activeGraphicClass ()
  724. {
  725. constructCommon ();
  726. }
  727. TwoDProfileMonitor::TwoDProfileMonitor (const TwoDProfileMonitor &s)
  728. {
  729. // clone base class data
  730. // why doesn't activeGraphicClass copy constructor do this?
  731. activeGraphicClass::clone ( &s );
  732. constructCommon ();
  733. // does the copy constructor work?
  734. // dataPvStr = s.dataPvStr;
  735. // widthPvStr = s.widthPvStr;
  736. dataPvStr.setRaw (s.dataPvStr.rawString);
  737. widthPvStr.setRaw (s.widthPvStr.rawString);
  738. heightPvStr.setRaw (s.heightPvStr.rawString);
  739. pvBasedDataSize = s.pvBasedDataSize;
  740. dataWidth = s.dataWidth;
  741. }
  742. TwoDProfileMonitor::~TwoDProfileMonitor (void) {
  743. // ?????????????????
  744. //widgetDestroy (wd);
  745. }
  746. // called when widget is made active as edm changes to "execute" mode,
  747. // pass values are 0-6
  748. int TwoDProfileMonitor::activate ( int pass,
  749. void *ptr )
  750. {
  751. switch (pass)
  752. {
  753. case 1:
  754. opComplete = 0;
  755. aglPtr = ptr;
  756. break;
  757. case 2:
  758. if ( !opComplete ) {
  759. _edmDebug();
  760. img = new imageClass( actWin->d, actWin->ci->getColorMap(),
  761. actWin->executeGc.normGC(), w, h, nBitsPerPixel );
  762. opComplete = 1;
  763. }
  764. initialDataConnection = 1;
  765. initialWidthConnection = 0;
  766. initialHeightConnection = 0;
  767. needConnectInit = needInfoInit = needRefresh = 0;
  768. pvNotConnectedMask = active = init = 0;
  769. activeMode = 1;
  770. if (!dataPvStr.getExpanded () ||
  771. blankOrComment (dataPvStr.getExpanded ()))
  772. {
  773. dataPvExists = 0;
  774. }
  775. else
  776. {
  777. dataPvExists = 1;
  778. pvNotConnectedMask |= 1;
  779. }
  780. if (!pvBasedDataSize)
  781. {
  782. widthPvExists = 0;
  783. heightPvExists = 0;
  784. }
  785. else
  786. {
  787. if (!widthPvStr.getExpanded () ||
  788. blankOrComment (widthPvStr.getExpanded ()))
  789. {
  790. widthPvExists = 0;
  791. }
  792. else
  793. {
  794. widthPvExists = 1;
  795. initialWidthConnection = 1;
  796. pvNotConnectedMask |= 2;
  797. }
  798. if (!heightPvStr.getExpanded () ||
  799. blankOrComment (heightPvStr.getExpanded ()))
  800. {
  801. heightPvExists = 0;
  802. }
  803. else
  804. {
  805. heightPvExists = 1;
  806. initialHeightConnection = 1;
  807. pvNotConnectedMask |= 4;
  808. }
  809. }
  810. #ifdef DEBUG
  811. printf (
  812. "TwoDProfileMonitor::activate pass 1 - pvNotConnectedMask = %d\n",
  813. pvNotConnectedMask);
  814. #endif
  815. break;
  816. // connect PVs during pass 2
  817. case 3:
  818. {
  819. // assume the best!
  820. pvColour.setColorIndex ( actWin->defaultTextFgColor, actWin->ci );
  821. if (!dataPvExists)
  822. break; // don't bother the factory
  823. dataPv = the_PV_Factory->create ( dataPvStr.getExpanded () );
  824. if ( dataPv )
  825. {
  826. #ifdef DEBUG
  827. printf (
  828. "TwoDProfMon::activate pass 2 - add data connect cb\n");
  829. #endif
  830. dataPv->add_conn_state_callback (monitorDataConnectState,
  831. this);
  832. //dataPv->add_value_callback ( pvUpdate, this );
  833. }
  834. if (!widthPvExists)
  835. break; // no need to set up width PV
  836. // printf ("activate (TwoDMon.cc) - width PV = %s = %s\n",
  837. // widthPvStr.getRaw(),
  838. // widthPvStr.getExpanded());
  839. widthPv = the_PV_Factory->create ( widthPvStr.getExpanded () );
  840. if ( widthPv )
  841. {
  842. #ifdef DEBUG
  843. printf (
  844. "TwoDProfMon::activate pass 2 - adding width connect cb\n");
  845. #endif
  846. widthPv->add_conn_state_callback (monitorWidthConnectState,
  847. this);
  848. //widthPv->add_value_callback ( pvUpdate, this );
  849. }
  850. if (!heightPvExists)
  851. break; // no need to set up height PV
  852. // printf ("activate (TwoDMon.cc) - height PV = %s = %s\n",
  853. // heightPvStr.getRaw(),
  854. // heightPvStr.getExpanded());
  855. heightPv = the_PV_Factory->create ( heightPvStr.getExpanded () );
  856. if ( heightPv )
  857. {
  858. #ifdef DEBUG
  859. printf (
  860. "TwoDProfMon::activate pass 2 - adding height connect cb\n");
  861. #endif
  862. heightPv->add_conn_state_callback (monitorHeightConnectState,
  863. this);
  864. //heightPv->add_value_callback ( pvUpdate, this );
  865. }
  866. #ifdef DEBUG
  867. if ( dataPv ) {
  868. printf ("activate (TwoDMon.cc) - dataPv->is_valid = %d\n",
  869. dataPv->is_valid ());
  870. }
  871. if ( widthPv ) {
  872. printf ("activate (TwoDMon.cc) - widthPv->is_valid = %d\n",
  873. widthPv->is_valid ());
  874. }
  875. if ( heightPv ) {
  876. printf ("activate (TwoDMon.cc) - heightPv->is_valid = %d\n",
  877. heightPv->is_valid ());
  878. }
  879. #endif
  880. }
  881. break;
  882. // OK, now create the widget
  883. case 6:
  884. // create the execute-mode widget using XRT or other
  885. // standard Motif 2-D data widget
  886. // ????????????????
  887. //twoDWidget = widgetCreateWidget (
  888. // wd, actWin->appCtx->appContext (), actWin->d,
  889. // actWin->ci->getColorMap (), actWin->executeWidget,
  890. // x, y, h, w);
  891. // capture events to pass on to EDM
  892. //XtAddEventHandler (
  893. // twoDWidget,
  894. // LeaveWindowMask | EnterWindowMask | PointerMotionMask |
  895. // ButtonPressMask |ButtonReleaseMask,
  896. // False, grabButtonEvent, (XtPointer) this);
  897. // hand over control
  898. //XtManageChild (twoDWidget);
  899. break;
  900. default:
  901. break;
  902. }
  903. return 1;
  904. }
  905. // user hit the "OK" button on the edit popup
  906. void TwoDProfileMonitor::editOK (Widget w,
  907. XtPointer client,
  908. XtPointer call )
  909. {
  910. TwoDProfileMonitor *me = (TwoDProfileMonitor *) client;
  911. // first apply any changes
  912. editApply (w, client, call);
  913. me->ef.popdown ();
  914. me->operationComplete ();
  915. }
  916. // user hit the "Apply" button on the edit popup
  917. void TwoDProfileMonitor::editApply (Widget w,
  918. XtPointer client,
  919. XtPointer call )
  920. {
  921. TwoDProfileMonitor *me = (TwoDProfileMonitor *) client;
  922. me->eraseSelectBoxCorners ();
  923. me->erase ();
  924. me->x = me->xBuf;
  925. me->y = me->yBuf;
  926. me->w = me->wBuf;
  927. me->h = me->hBuf;
  928. me->nBitsPerPixel = me->nBitsPerPixelBuf;
  929. me->sboxX = me->xBuf;
  930. me->sboxY = me->yBuf;
  931. me->sboxW = me->wBuf;
  932. me->sboxH = me->hBuf;
  933. // do the PV name(s)
  934. me->dataPvStr.setRaw ( me->dataPvBuf );
  935. // now the width: if fixed is indicated, interpret PV string as int
  936. me->widthPvStr.setRaw ( me->widthPvBuf );
  937. if (!me->pvBasedDataSize)
  938. me->dataWidth = atoi ( me->widthPvBuf );
  939. else
  940. me->dataWidth = -1; // just to be safe
  941. me->heightPvStr.setRaw ( me->heightPvBuf );
  942. me->dataHeight = 0; // correct if PV null, will be overwritten otherwise
  943. // support auto-save
  944. me->actWin->setChanged ();
  945. // let EDM know that "Apply" was invoked
  946. me->refresh ();
  947. }
  948. // user hit the "Cancel" button on the edit popup
  949. void TwoDProfileMonitor::editCancel (Widget w,
  950. XtPointer client,
  951. XtPointer call )
  952. {
  953. TwoDProfileMonitor *me = (TwoDProfileMonitor *) client;
  954. me->ef.popdown ();
  955. // no need for EDM to do anything
  956. me->operationCancel ();
  957. }
  958. // user hit the "Cancel" button on the edit popup
  959. void TwoDProfileMonitor::editCancelCreate (Widget w,
  960. XtPointer client,
  961. XtPointer call )
  962. {
  963. TwoDProfileMonitor *me = (TwoDProfileMonitor *) client;
  964. me->ef.popdown ();
  965. // remove all traces of our existence!
  966. me->erase ();
  967. me->deleteRequest = 1;
  968. // no need for EDM to do anything
  969. me->operationCancel ();
  970. }
  971. void TwoDProfileMonitor::editCommon ( activeWindowClass *actWin,
  972. entryFormClass *_ef, int create )
  973. {
  974. // create edit box
  975. ef.create ( actWin->top, actWin->appCtx->ci.getColorMap (),
  976. &actWin->appCtx->entryFormX,
  977. &actWin->appCtx->entryFormY, &actWin->appCtx->entryFormW,
  978. &actWin->appCtx->entryFormH, &actWin->appCtx->largestH,
  979. "2D Profile Monitor Properties", NULL, NULL, NULL );
  980. xBuf = x;
  981. yBuf = y;
  982. wBuf = w;
  983. hBuf = h;
  984. nBitsPerPixelBuf = nBitsPerPixel;
  985. ef.addTextField ("X", 30, &xBuf);
  986. ef.addTextField ("Y", 30, &yBuf);
  987. ef.addTextField ("Widget Width", 30, &wBuf);
  988. ef.addTextField ("Widget Height", 30, &hBuf);
  989. ef.addTextField ("Bits per pixel", 30, &nBitsPerPixelBuf);
  990. // copy out, we'll copy in during "Apply"
  991. strncpy (dataPvBuf, dataPvStr.getRaw (), sizeof (dataPvBuf) - 1);
  992. ef.addTextField ("Data PV", 30, dataPvBuf, sizeof (dataPvBuf) - 1);
  993. // copy out, we'll copy in during "Apply"
  994. strncpy (widthPvBuf, widthPvStr.getRaw (), sizeof (widthPvBuf) - 1);
  995. ef.addTextField ("Data Width (Fixed/PV)", 30, widthPvBuf,
  996. sizeof (widthPvBuf) - 1);
  997. strncpy (heightPvBuf,heightPvStr.getRaw (), sizeof (heightPvBuf) - 1);
  998. ef.addTextField ("Data Height PV (ignored for fixed size)",
  999. 30, heightPvBuf, sizeof (heightPvBuf) - 1);
  1000. ef.addOption ("Data Size Type", "Fixed|PV-based", &pvBasedDataSize);
  1001. // ef.addToggle ("PV-based Width", &height);
  1002. // Map dialog box form buttons to callbacks
  1003. ef.finished ( editOK, editApply, create ? editCancelCreate : editCancel,
  1004. this );
  1005. // Required by display engine
  1006. actWin->currentEf = _ef;
  1007. // popup the dialog box
  1008. ef.popup ();
  1009. }
  1010. int TwoDProfileMonitor::edit ( void )
  1011. {
  1012. editCommon ( actWin, &ef );
  1013. return 1;
  1014. }
  1015. int TwoDProfileMonitor::createInteractive (activeWindowClass *actWin,
  1016. int x,
  1017. int y,
  1018. int w,
  1019. int h )
  1020. {
  1021. this->actWin = actWin;
  1022. this->x = x;
  1023. this->y = y;
  1024. this->w = w;
  1025. this->h = h;
  1026. this->nBitsPerPixel = VIDEO_NBITSPERPIXEL_DEFAULT;
  1027. draw ();
  1028. editCommon ( actWin, NULL, ~0 );
  1029. return 1;
  1030. }
  1031. int TwoDProfileMonitor::createFromFile (FILE *fptr,
  1032. char *name,
  1033. activeWindowClass *actWin )
  1034. {
  1035. this->actWin = actWin;
  1036. // use tag class and name to read from file
  1037. TwoDProfileMonitorTags tag;
  1038. nBitsPerPixel = 8;
  1039. if ( !(1 & tag.read ( this,
  1040. fptr, &x, &y, &w, &h, &nBitsPerPixel, &dataPvStr,
  1041. &widthPvStr, &heightPvStr,
  1042. &dataWidth, &pvBasedDataSize ) ) )
  1043. {
  1044. actWin->appCtx->postMessage ( tag.errMsg () );
  1045. }
  1046. updateDimensions ();
  1047. initSelectBox ();
  1048. return 1;
  1049. }
  1050. // What is an exchange file?
  1051. int TwoDProfileMonitor::importFromXchFile (FILE *fptr,
  1052. char *name,
  1053. activeWindowClass *actWin )
  1054. {
  1055. cerr << "Import from eXchange file not supported" << endl;
  1056. return 0;
  1057. }
  1058. int TwoDProfileMonitor::save ( FILE *fptr )
  1059. {
  1060. // use tag class to serialize data
  1061. TwoDProfileMonitorTags tag;
  1062. return tag.write ( fptr, &x, &y, &w, &h, &nBitsPerPixel, &dataPvStr,
  1063. &widthPvStr, &heightPvStr,
  1064. &dataWidth, &pvBasedDataSize );
  1065. }
  1066. // called any time the widget needs to draw or re-draw itself
  1067. // in edit-mode
  1068. int TwoDProfileMonitor::draw (void)
  1069. {
  1070. // draw rectangle using X primitives
  1071. XFillRectangle ( actWin->d, XtWindow (actWin->drawWidget),
  1072. actWin->drawGc.eraseGC (), x, y, w, h );
  1073. XDrawRectangle ( actWin->d, XtWindow (actWin->drawWidget),
  1074. actWin->drawGc.normGC (), x, y, w, h );
  1075. // Draw label text (crude because we can escape widget boundaries)
  1076. XDrawImageString ( actWin->d, XtWindow (actWin->drawWidget),
  1077. actWin->drawGc.normGC (), x + 5, y + h / 2,
  1078. dataPvStr.getRaw (), strlen (dataPvStr.getRaw ()) );
  1079. return 1;
  1080. //return activeGraphicClass::draw ();
  1081. } ;
  1082. // erase widget in responce to "cut" command
  1083. // in edit-mode
  1084. int TwoDProfileMonitor::erase (void)
  1085. {
  1086. // draw rectangle using X primitives
  1087. XDrawRectangle ( actWin->d, XtWindow (actWin->drawWidget),
  1088. actWin->drawGc.eraseGC (), x, y, w, h );
  1089. return 1;
  1090. //return activeGraphicClass::erase ();
  1091. } ;
  1092. int TwoDProfileMonitor::drawActive (void)
  1093. {
  1094. if ( img->validImage() ) {
  1095. XPutImage( actWin->d, XtWindow(actWin->executeWidget),
  1096. actWin->executeGc.normGC(), img->ximage(),
  1097. 0, 0, x, y, w, h );
  1098. }
  1099. return 1;
  1100. }
  1101. // returning to edit mode, pass values are 1 and 2
  1102. int TwoDProfileMonitor::deactivate ( int pass )
  1103. {
  1104. active = 0;
  1105. activeMode = 0;
  1106. if ( dataPv != NULL )
  1107. {
  1108. actWin->appCtx->proc->lock ();
  1109. dataPv->remove_conn_state_callback ( monitorDataConnectState, this );
  1110. #ifdef DEBUG
  1111. printf ("TwoDProfileMonitor::deactivate - removing data callback\n");
  1112. #endif
  1113. dataPv->remove_value_callback ( dataUpdate, this );
  1114. dataPv->release ();
  1115. dataPv = NULL;
  1116. actWin->appCtx->proc->unlock ();
  1117. }
  1118. if ( widthPv != NULL )
  1119. {
  1120. actWin->appCtx->proc->lock ();
  1121. widthPv->remove_conn_state_callback ( monitorWidthConnectState, this );
  1122. widthPv->remove_value_callback ( sizeUpdate, this );
  1123. widthPv->release ();
  1124. widthPv = NULL;
  1125. actWin->appCtx->proc->unlock ();
  1126. }
  1127. if ( heightPv != NULL )
  1128. {
  1129. actWin->appCtx->proc->lock ();
  1130. heightPv->remove_conn_state_callback ( monitorHeightConnectState, this );
  1131. heightPv->remove_value_callback ( sizeUpdate, this );
  1132. heightPv->release ();
  1133. heightPv = NULL;
  1134. actWin->appCtx->proc->unlock ();
  1135. }
  1136. // disconnect PV timeout on pass 1
  1137. if ( pass == 1 )
  1138. {
  1139. // disable deferred processing before anything else
  1140. actWin->appCtx->proc->lock ();
  1141. actWin->remDefExeNode (aglPtr);
  1142. actWin->appCtx->proc->unlock ();
  1143. }
  1144. // now turn off the Widget
  1145. if ( pass == 2 )
  1146. {
  1147. #ifdef DEBUG
  1148. printf ("TwoDProfileMonitor::deactivate - pass 2\n");
  1149. #endif
  1150. // ???????????????????
  1151. //widgetNewDisplayInfo (wd, false, 0, 0);
  1152. //XtUnmanageChild (twoDWidget);
  1153. //XtDestroyWidget (twoDWidget);
  1154. // ????????????????????
  1155. //widgetDestroyWidget (wd);
  1156. _edmDebug();
  1157. img->destroy();
  1158. }
  1159. return 1;
  1160. //return activeGraphicClass::deactivate (pass);
  1161. }
  1162. void TwoDProfileMonitor::monitorDataConnectState (ProcessVariable *pv,
  1163. void *userarg )
  1164. {
  1165. TwoDProfileMonitor *me = ( TwoDProfileMonitor *) userarg;
  1166. me->actWin->appCtx->proc->lock ();
  1167. if (me->activeMode)
  1168. {
  1169. if (pv->is_valid())
  1170. {
  1171. me->pvNotConnectedMask &= ~((unsigned char) 1);
  1172. #ifdef DEBUG
  1173. printf ("TwoDProfMon::monDataConState - set pvNotConnMask to %d\n",
  1174. me->pvNotConnectedMask);
  1175. #endif
  1176. if (!me->pvNotConnectedMask)
  1177. {
  1178. // All PVs connected
  1179. me->needConnectInit = 1;
  1180. me->actWin->addDefExeNode (me->aglPtr);
  1181. }
  1182. }
  1183. else
  1184. {
  1185. me->pvNotConnectedMask |= 1;
  1186. me->active = 0;
  1187. me->bufInvalidate();
  1188. me->needDraw = 1;
  1189. me->actWin->addDefExeNode (me->aglPtr);
  1190. }
  1191. }
  1192. me->actWin->appCtx->proc->unlock ();
  1193. }
  1194. void TwoDProfileMonitor::monitorWidthConnectState (ProcessVariable *pv,
  1195. void *userarg )
  1196. {
  1197. TwoDProfileMonitor *me = ( TwoDProfileMonitor *) userarg;
  1198. me->actWin->appCtx->proc->lock ();
  1199. if (me->activeMode)
  1200. {
  1201. if (pv->is_valid())
  1202. {
  1203. me->pvNotConnectedMask &= ~((unsigned char) 2);
  1204. #ifdef DEBUG
  1205. printf ("TwoDProfMon::monWidthConState - set pvNotConMask to %d\n",
  1206. me->pvNotConnectedMask);
  1207. #endif
  1208. if (!me->pvNotConnectedMask)
  1209. {
  1210. // All PVs connected
  1211. me->needConnectInit = 1;
  1212. me->actWin->addDefExeNode (me->aglPtr);
  1213. }
  1214. }
  1215. else
  1216. {
  1217. me->pvNotConnectedMask |= 2;
  1218. me->active = 0;
  1219. me->bufInvalidate();
  1220. me->needDraw = 1;
  1221. me->actWin->addDefExeNode (me->aglPtr);
  1222. }
  1223. }
  1224. me->actWin->appCtx->proc->unlock ();
  1225. }
  1226. void TwoDProfileMonitor::monitorHeightConnectState (ProcessVariable *pv,
  1227. void *userarg )
  1228. {
  1229. TwoDProfileMonitor *me = ( TwoDProfileMonitor *) userarg;
  1230. me->actWin->appCtx->proc->lock ();
  1231. if (me->activeMode)
  1232. {
  1233. if (pv->is_valid())
  1234. {
  1235. me->pvNotConnectedMask &= ~((unsigned char) 4);
  1236. #ifdef DEBUG
  1237. printf ("TwoDProfMon::monHeightConState - set pvNotConMsk to %d\n",
  1238. me->pvNotConnectedMask);
  1239. #endif
  1240. if (!me->pvNotConnectedMask)
  1241. {
  1242. // All PVs connected
  1243. me->needConnectInit = 1;
  1244. me->actWin->addDefExeNode (me->aglPtr);
  1245. }
  1246. }
  1247. else
  1248. {
  1249. me->pvNotConnectedMask |= 2;
  1250. me->active = 0;
  1251. me->bufInvalidate();
  1252. me->needDraw = 1;
  1253. me->actWin->addDefExeNode (me->aglPtr);
  1254. }
  1255. }
  1256. me->actWin->appCtx->proc->unlock ();
  1257. }
  1258. void TwoDProfileMonitor::dataUpdate (ProcessVariable *pv,
  1259. void *userarg )
  1260. {
  1261. TwoDProfileMonitor *me = ( TwoDProfileMonitor *) userarg;
  1262. me->actWin->appCtx->proc->lock ();
  1263. me->actWin->addDefExeNode (me->aglPtr);
  1264. me->actWin->appCtx->proc->unlock ();
  1265. }
  1266. void TwoDProfileMonitor::sizeUpdate (ProcessVariable *pv,
  1267. void *userarg )
  1268. {
  1269. // This function no longer does anything. Leave it in in case we need it
  1270. // again later.
  1271. #ifdef COMMENT_OUT
  1272. TwoDProfileMonitor *me = ( TwoDProfileMonitor *) userarg;
  1273. // Delete the data PV and recreate it.
  1274. // Hopefully this will reinitialise the element count to match
  1275. // the new size.
  1276. me->actWin->appCtx->proc->lock ();
  1277. me->dataPv->remove_value_callback ( dataUpdate, me );
  1278. me->dataPv->remove_conn_state_callback ( monitorDataConnectState, me );
  1279. me->dataPv->release ();
  1280. me->dataPv = the_PV_Factory->create ( me->dataPvStr.getExpanded () );
  1281. me->dataPv->add_conn_state_callback ( monitorDataConnectState, me );
  1282. me->dataPv->add_value_callback ( dataUpdate, me );
  1283. me->actWin->appCtx->proc->unlock ();
  1284. #endif
  1285. }