Changeset 3605 for trunk/packages/vizservers/nanovis/Command.cpp
- Timestamp:
- Apr 2, 2013, 1:31:30 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/packages/vizservers/nanovis/Command.cpp
r3597 r3605 45 45 #include <vrmath/Vector3f.h> 46 46 47 #include "nanovisServer.h" 47 48 #include "nanovis.h" 49 #include "ReadBuffer.h" 50 #ifdef USE_THREADS 51 #include "ResponseQueue.h" 52 #endif 53 #include "Command.h" 48 54 #include "CmdProc.h" 49 55 #include "FlowCmd.h" 50 #include "Trace.h"51 #ifdef USE_POINTSET_RENDERER52 #include "PointSet.h"53 #endif54 56 #include "dxReader.h" 55 57 #include "VtkReader.h" 58 #include "BMPWriter.h" 59 #include "PPMWriter.h" 56 60 #include "Grid.h" 57 61 #include "HeightMap.h" 58 62 #include "NvCamera.h" 59 63 #include "NvZincBlendeReconstructor.h" 64 #include "OrientationIndicator.h" 60 65 #include "Unirect.h" 61 66 #include "Volume.h" 62 67 #include "VolumeRenderer.h" 63 68 #include "Trace.h" 69 70 using namespace nv; 64 71 using namespace nv::graphics; 65 72 using namespace vrmath; … … 102 109 }"; 103 110 111 static int lastCmdStatus; 112 113 #ifdef USE_THREADS 114 void 115 nv::queueResponse(const void *bytes, size_t len, 116 Response::AllocationType allocType, 117 Response::ResponseType type) 118 { 119 Response *response = new Response(type); 120 response->setMessage((unsigned char *)bytes, len, allocType); 121 g_queue->enqueue(response); 122 } 123 #else 124 125 ssize_t 126 nv::SocketWrite(const void *bytes, size_t len) 127 { 128 size_t ofs = 0; 129 ssize_t bytesWritten; 130 while ((bytesWritten = write(g_fdOut, (const char *)bytes + ofs, len - ofs)) > 0) { 131 ofs += bytesWritten; 132 if (ofs == len) 133 break; 134 } 135 if (bytesWritten < 0) { 136 ERROR("write: %s", strerror(errno)); 137 } 138 return bytesWritten; 139 } 140 141 #endif /*USE_THREADS*/ 142 143 bool 144 nv::SocketRead(char *bytes, size_t len) 145 { 146 ReadBuffer::BufferStatus status; 147 status = g_inBufPtr->followingData((unsigned char *)bytes, len); 148 TRACE("followingData status: %d", status); 149 return (status == ReadBuffer::OK); 150 } 151 152 bool 153 nv::SocketRead(Rappture::Buffer &buf, size_t len) 154 { 155 ReadBuffer::BufferStatus status; 156 status = g_inBufPtr->followingData(buf, len); 157 TRACE("followingData status: %d", status); 158 return (status == ReadBuffer::OK); 159 } 160 161 static int 162 ExecuteCommand(Tcl_Interp *interp, Tcl_DString *dsPtr) 163 { 164 int result; 165 #ifdef WANT_TRACE 166 char *str = Tcl_DStringValue(dsPtr); 167 std::string cmd(str); 168 cmd.erase(cmd.find_last_not_of(" \n\r\t")+1); 169 TRACE("command %lu: '%s'", g_stats.nCommands+1, cmd.c_str()); 170 #endif 171 lastCmdStatus = TCL_OK; 172 result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr), 173 Tcl_DStringLength(dsPtr), 174 TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL); 175 Tcl_DStringSetLength(dsPtr, 0); 176 if (lastCmdStatus == TCL_BREAK) { 177 return TCL_BREAK; 178 } 179 lastCmdStatus = result; 180 if (result != TCL_OK) { 181 TRACE("Error: %d", result); 182 } 183 return result; 184 } 185 104 186 bool 105 187 GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, bool *boolPtr) … … 276 358 * TCL_ERROR to indicate an error. 277 359 */ 278 staticint360 int 279 361 GetVolumeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Volume **volPtrPtr) 280 362 { … … 454 536 GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes) 455 537 { 456 char buffer[8096]; 457 458 clearerr(NanoVis::stdin); 459 while (nBytes > 0) { 460 unsigned int chunk; 461 int nRead; 462 463 chunk = (sizeof(buffer) < (unsigned int) nBytes) ? 464 sizeof(buffer) : nBytes; 465 nRead = fread(buffer, sizeof(char), chunk, NanoVis::stdin); 466 if (ferror(NanoVis::stdin)) { 467 Tcl_AppendResult(interp, "while reading data stream: ", 468 Tcl_PosixError(interp), (char*)NULL); 469 return TCL_ERROR; 470 } 471 if (feof(NanoVis::stdin)) { 472 Tcl_AppendResult(interp, "premature EOF while reading data stream", 473 (char*)NULL); 474 return TCL_ERROR; 475 } 476 buf.append(buffer, nRead); 477 nBytes -= nRead; 478 } 479 if (NanoVis::recfile != NULL) { 480 ssize_t nWritten; 481 482 nWritten = fwrite(buf.bytes(), sizeof(char), buf.size(), 483 NanoVis::recfile); 484 assert(nWritten == (ssize_t)buf.size()); 485 fflush(NanoVis::recfile); 538 if (!SocketRead(buf, nBytes)) { 539 return TCL_ERROR; 486 540 } 487 541 Rappture::Outcome err; … … 621 675 Tcl_Obj *const *objv) 622 676 { 623 int w, h; 624 625 w = NanoVis::winWidth, h = NanoVis::winHeight; 626 627 NanoVis::resizeOffscreenBuffer(2048, 2048); 628 #ifdef notdef 629 NanoVis::cam->setScreenSize(0, 0, NanoVis::winWidth, NanoVis::winHeight); 630 NanoVis::cam->setScreenSize(30, 90, 2048 - 60, 2048 - 120); 631 #endif 632 NanoVis::bindOffscreenBuffer(); //enable offscreen render 677 int origWidth, origHeight, width, height; 678 679 origWidth = NanoVis::winWidth; 680 origHeight = NanoVis::winHeight; 681 width = 2048; 682 height = 2048; 683 684 NanoVis::resizeOffscreenBuffer(width, height); 685 NanoVis::bindOffscreenBuffer(); 633 686 NanoVis::render(); 634 687 NanoVis::readScreen(); 635 636 NanoVis::ppmWrite("nv>image -type print -bytes %d"); 637 NanoVis::resizeOffscreenBuffer(w, h); 688 #ifdef USE_THREADS 689 queuePPM(g_queue, "nv>image -type print -bytes", 690 NanoVis::screenBuffer, width, height); 691 #else 692 writePPM(g_fdOut, "nv>image -type print -bytes", 693 NanoVis::screenBuffer, width, height); 694 #endif 695 NanoVis::resizeOffscreenBuffer(origWidth, origHeight); 638 696 639 697 return TCL_OK; … … 753 811 static int 754 812 ClientInfoCmd(ClientData clientData, Tcl_Interp *interp, int objc, 755 Tcl_Obj *const *objv)813 Tcl_Obj *const *objv) 756 814 { 757 815 Tcl_DString ds; … … 769 827 } 770 828 #ifdef KEEPSTATS 771 int f;772 773 829 /* Use the initial client key value pairs as the parts for a generating 774 830 * a unique file name. */ 775 f = NanoVis::getStatsFile(objv[1]);831 int f = nv::getStatsFile(interp, objv[1]); 776 832 if (f < 0) { 777 833 Tcl_AppendResult(interp, "can't open stats file: ", … … 809 865 /* date */ 810 866 Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("date", 4)); 811 strcpy(buf, ctime(& NanoVis::startTime.tv_sec));867 strcpy(buf, ctime(&nv::g_stats.start.tv_sec)); 812 868 buf[strlen(buf) - 1] = '\0'; 813 869 Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj(buf, -1)); … … 816 872 Tcl_NewStringObj("date_secs", 9)); 817 873 Tcl_ListObjAppendElement(interp, listObjPtr, 818 Tcl_NewLongObj( NanoVis::startTime.tv_sec));874 Tcl_NewLongObj(nv::g_stats.start.tv_sec)); 819 875 /* Client arguments. */ 820 876 if (Tcl_ListObjGetElements(interp, objv[1], &numItems, &items) != TCL_OK) { … … 829 885 Tcl_DStringAppend(&ds, "\n", 1); 830 886 #ifdef KEEPSTATS 831 result = NanoVis::writeToStatsFile(f, Tcl_DStringValue(&ds),832 887 result = nv::writeToStatsFile(f, Tcl_DStringValue(&ds), 888 Tcl_DStringLength(&ds)); 833 889 #else 834 890 TRACE("clientinfo: %s", Tcl_DStringValue(&ds)); … … 860 916 } 861 917 862 const char *name; 863 name = Tcl_GetString(objv[1]); 864 TransferFunction *tf = NanoVis::getTransferFunction(name); 918 const char *tfName = Tcl_GetString(objv[1]); 919 TransferFunction *tf = NanoVis::getTransferFunction(tfName); 865 920 if (tf == NULL) { 866 Tcl_AppendResult(interp, "unknown transfer function \"", name, "\"",921 Tcl_AppendResult(interp, "unknown transfer function \"", tfName, "\"", 867 922 (char*)NULL); 868 923 return TCL_ERROR; … … 876 931 NanoVis::setVolumeRanges(); 877 932 } 878 NanoVis::renderLegend(tf, Volume::valueMin, Volume::valueMax, w, h, name);933 NanoVis::renderLegend(tf, Volume::valueMin, Volume::valueMax, w, h, tfName); 879 934 return TCL_OK; 880 935 } … … 1080 1135 return TCL_ERROR; 1081 1136 } 1082 VolumeInterpolator * interpolator;1083 interpolator =NanoVis::volRenderer->getVolumeInterpolator();1137 VolumeInterpolator *interpolator = 1138 NanoVis::volRenderer->getVolumeInterpolator(); 1084 1139 interpolator->start(); 1085 1140 if (interpolator->isStarted()) { 1086 const char * fileName = (objc < 5) ? NULL : Tcl_GetString(objv[4]);1087 for (int frame _num = 0; frame_num < total; ++frame_num) {1141 const char *dirName = (objc < 5) ? NULL : Tcl_GetString(objv[4]); 1142 for (int frameNum = 0; frameNum < total; ++frameNum) { 1088 1143 float fraction; 1089 1144 1090 fraction = ((float)frame _num) / (total - 1);1145 fraction = ((float)frameNum) / (total - 1); 1091 1146 TRACE("fraction : %f", fraction); 1092 //interpolator->update(((float)frame_num) / (total - 1));1093 1147 interpolator->update(fraction); 1094 1148 … … 1103 1157 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig); 1104 1158 1105 NanoVis::bmpWriteToFile(frame_num, fileName); 1159 /* FIXME: this function requires 4-byte aligned RGB rows, 1160 * but screen buffer is now 1 byte aligned for PPM images. 1161 */ 1162 nv::writeBMPFile(frameNum, dirName, 1163 NanoVis::screenBuffer, 1164 NanoVis::winWidth, NanoVis::winHeight); 1106 1165 } 1107 1166 } … … 1185 1244 } 1186 1245 const char *tag = Tcl_GetString(objv[4]); 1187 Rappture::Buffer buf; 1246 1247 Rappture::Buffer buf(nbytes); 1188 1248 if (GetDataStream(interp, buf, nbytes) != TCL_OK) { 1189 1249 return TCL_ERROR; 1190 1250 } 1191 const char *bytes; 1192 size_t nBytes; 1193 1194 bytes = buf.bytes(); 1195 nBytes = buf.size(); 1251 const char *bytes = buf.bytes(); 1252 size_t nBytes = buf.size(); 1196 1253 1197 1254 TRACE("Checking header[%.20s]", bytes); … … 1201 1258 if ((nBytes > 5) && (strncmp(bytes, "<HDR>", 5) == 0)) { 1202 1259 TRACE("ZincBlende Stream loading..."); 1203 //std::stringstream fdata(std::ios_base::out|std::ios_base::in|std::ios_base::binary); 1204 //fdata.write(buf.bytes(),buf.size()); 1205 //vol = NvZincBlendeReconstructor::getInstance()->loadFromStream(fdata); 1206 1207 volume = NvZincBlendeReconstructor::getInstance()->loadFromMemory((void*) buf.bytes()); 1260 volume = NvZincBlendeReconstructor::getInstance()->loadFromMemory(const_cast<char *>(bytes)); 1208 1261 if (volume == NULL) { 1209 1262 Tcl_AppendResult(interp, "can't get volume instance", (char *)NULL); … … 1267 1320 volume->visible(true); 1268 1321 1269 char info[1024];1270 ssize_t nWritten;1271 1272 1322 if (Volume::updatePending) { 1273 1323 NanoVis::setVolumeRanges(); 1274 1324 } 1275 1325 1326 char info[1024]; 1276 1327 // FIXME: strlen(info) is the return value of sprintf 1277 sprintf(info, "nv>data tag %s min %g max %g vmin %g vmax %g\n", tag, 1278 volume->wAxis.min(), volume->wAxis.max(), 1279 Volume::valueMin, Volume::valueMax); 1280 nWritten = write(1, info, strlen(info)); 1281 assert(nWritten == (ssize_t)strlen(info)); 1282 } 1328 int cmdLength = 1329 sprintf(info, "nv>data tag %s min %g max %g vmin %g vmax %g\n", tag, 1330 volume->wAxis.min(), volume->wAxis.max(), 1331 Volume::valueMin, Volume::valueMax); 1332 #ifdef USE_THREADS 1333 queueResponse(info, cmdLength, Response::VOLATILE); 1334 #else 1335 ssize_t nWritten = SocketWrite(info, (size_t)cmdLength); 1336 if (nWritten != (ssize_t)cmdLength) { 1337 ERROR("Short write"); 1338 return TCL_ERROR; 1339 } 1340 #endif 1341 } 1342 1283 1343 return TCL_OK; 1284 1344 } … … 1304 1364 1305 1365 static Rappture::CmdSpec volumeDataOps[] = { 1306 {"follows", 1, VolumeDataFollowsOp, 5, 5, " sizetag",},1366 {"follows", 1, VolumeDataFollowsOp, 5, 5, "nbytes tag",}, 1307 1367 {"state", 1, VolumeDataStateOp, 4, 0, "bool ?indices?",}, 1308 1368 }; … … 1407 1467 } 1408 1468 1409 1410 1469 static Rappture::CmdSpec volumeOutlineOps[] = { 1411 1470 {"color", 1, VolumeOutlineColorOp, 6, 0, "r g b ?indices?",}, … … 1596 1655 tf->name()); 1597 1656 (*iter)->transferFunction(tf); 1598 #ifdef USE_POINTSET_RENDERER1599 // TBD..1600 if ((*iter)->pointsetIndex != -1) {1601 NanoVis::pointSet[(*iter)->pointsetIndex]->updateColor(tf->getData(), 256);1602 }1603 #endif1604 1657 } 1605 1658 return TCL_OK; … … 1656 1709 {"delete", 2, VolumeDeleteOp, 3, 0, "?name...?",}, 1657 1710 {"exists", 1, VolumeExistsOp, 3, 3, "name",}, 1658 {"names", 1, VolumeNamesOp, 2, 3, "?pattern?",},1711 {"names", 1, VolumeNamesOp, 2, 2, "",}, 1659 1712 {"outline", 1, VolumeOutlineOp, 3, 0, "oper ?args?",}, 1660 1713 {"shading", 2, VolumeShadingOp, 3, 0, "oper ?args?",}, … … 1663 1716 static int nVolumeOps = NumCmdSpecs(volumeOps); 1664 1717 1665 /*1666 * ----------------------------------------------------------------------1667 * CLIENT COMMAND:1668 * volume data state on|off ?<volumeId> ...?1669 * volume outline state on|off ?<volumeId> ...?1670 * volume outline color on|off ?<volumeId> ...?1671 * volume shading transfunc <name> ?<volumeId> ...?1672 * volume shading diffuse <value> ?<volumeId> ...?1673 * volume shading specular <value> ?<volumeId> ...?1674 * volume shading opacity <value> ?<volumeId> ...?1675 * volume state on|off ?<volumeId> ...?1676 *1677 * Clients send these commands to manipulate the volumes.1678 * ----------------------------------------------------------------------1679 */1680 1718 static int 1681 1719 VolumeCmd(ClientData clientData, Tcl_Interp *interp, int objc, … … 1702 1740 const char *tag = Tcl_GetString(objv[4]); 1703 1741 1704 Rappture::Buffer buf ;1742 Rappture::Buffer buf(nBytes); 1705 1743 if (GetDataStream(interp, buf, nBytes) != TCL_OK) { 1706 1744 return TCL_ERROR; … … 1761 1799 1762 1800 static Rappture::CmdSpec heightMapDataOps[] = { 1763 {"follows", 1, HeightMapDataFollowsOp, 5, 5, "size tag",},1764 {"visible", 1, HeightMapDataVisibleOp, 4, 0, "bool ? indices?",},1801 {"follows", 1, HeightMapDataFollowsOp, 5, 5, "size heightmapName",}, 1802 {"visible", 1, HeightMapDataVisibleOp, 4, 0, "bool ?heightmapNames...?",}, 1765 1803 }; 1766 1804 static int nHeightMapDataOps = NumCmdSpecs(heightMapDataOps); … … 1822 1860 1823 1861 static Rappture::CmdSpec heightMapLineContourOps[] = { 1824 {"color", 1, HeightMapLineContourColorOp, 4, 4, "length",},1825 {"visible", 1, HeightMapLineContourVisibleOp, 4, 0, "bool ? indices?",},1862 {"color", 1, HeightMapLineContourColorOp, 6, 0, "r g b ?heightmapNames...?",}, 1863 {"visible", 1, HeightMapLineContourVisibleOp, 4, 0, "bool ?heightmapNames...?",}, 1826 1864 }; 1827 1865 static int nHeightMapLineContourOps = NumCmdSpecs(heightMapLineContourOps); … … 1956 1994 } 1957 1995 1958 1959 1996 static int 1960 1997 HeightMapOpacityOp(ClientData clientData, Tcl_Interp *interp, int objc, … … 1978 2015 1979 2016 static Rappture::CmdSpec heightMapOps[] = { 1980 {"create", 2, HeightMapCreateOp, 10, 10, " tagxmin ymin xmax ymax xnum ynum values",},2017 {"create", 2, HeightMapCreateOp, 10, 10, "heightmapName xmin ymin xmax ymax xnum ynum values",}, 1981 2018 {"cull", 2, HeightMapCullOp, 3, 3, "mode",}, 1982 2019 {"data", 1, HeightMapDataOp, 3, 0, "oper ?args?",}, 1983 {"legend", 2, HeightMapLegendOp, 5, 5, " indexwidth height",},2020 {"legend", 2, HeightMapLegendOp, 5, 5, "heightmapName width height",}, 1984 2021 {"linecontour", 2, HeightMapLineContourOp, 2, 0, "oper ?args?",}, 1985 {"opacity", 1, HeightMapOpacityOp, 3, 0, "value ?heightmap ...? ",},2022 {"opacity", 1, HeightMapOpacityOp, 3, 0, "value ?heightmapNames...? ",}, 1986 2023 {"polygon", 1, HeightMapPolygonOp, 3, 3, "mode",}, 1987 2024 {"shading", 1, HeightMapShadingOp, 3, 3, "model",}, 1988 {"transfunc", 2, HeightMapTransFuncOp, 3, 0, "name ?heightmap ...?",},2025 {"transfunc", 2, HeightMapTransFuncOp, 3, 0, "name ?heightmapNames...?",}, 1989 2026 }; 1990 2027 static int nHeightMapOps = NumCmdSpecs(heightMapOps); … … 2118 2155 return TCL_ERROR; 2119 2156 } 2120 NanoVis:: axisOn = visible;2157 NanoVis::orientationIndicator->setVisible(visible); 2121 2158 } else { 2122 2159 Tcl_AppendResult(interp, "bad axis option \"", string, … … 2127 2164 } 2128 2165 2129 /* 2130 * This command should be Tcl procedure instead of a C command. The reason 2131 * for this that 1) we are using a safe interpreter so we would need a master 2132 * interpreter to load the Tcl environment properly (including our "unirect2d" 2133 * procedure). And 2) the way nanovis is currently deployed doesn't make it 2134 * easy to add new directories for procedures, since it's loaded into /tmp. 2135 * 2136 * Ideally, the "unirect2d" proc would do a rundimentary parsing of the data 2137 * to verify the structure and then pass it to the appropiate Tcl command 2138 * (heightmap, volume, etc). Our C command always creates a heightmap. 2166 static int 2167 ImageFlushCmd(ClientData clientData, Tcl_Interp *interp, int objc, 2168 Tcl_Obj *const *objv) 2169 { 2170 lastCmdStatus = TCL_BREAK; 2171 return TCL_OK; 2172 } 2173 2174 /** 2175 * \brief Execute commands from client in Tcl interpreter 2176 * 2177 * In this threaded model, the select call is for event compression. We 2178 * want to execute render server commands as long as they keep coming. 2179 * This lets us execute a stream of many commands but render once. This 2180 * benefits camera movements, screen resizing, and opacity changes 2181 * (using a slider on the client). The down side is you don't render 2182 * until there's a lull in the command stream. If the client needs an 2183 * image, it can issue an "imgflush" command. That breaks us out of the 2184 * read loop. 2139 2185 */ 2140 static int 2141 Unirect2dCmd(ClientData clientData, Tcl_Interp *interp, int objc, 2142 Tcl_Obj *const *objv) 2143 { 2144 Rappture::Unirect2d *dataPtr = (Rappture::Unirect2d *)clientData; 2145 2146 return dataPtr->loadData(interp, objc, objv); 2147 } 2148 2149 /* 2150 * This command should be Tcl procedure instead of a C command. The reason 2151 * for this that 1) we are using a safe interpreter so we would need a master 2152 * interpreter to load the Tcl environment properly (including our "unirect2d" 2153 * procedure). And 2) the way nanovis is currently deployed doesn't make it 2154 * easy to add new directories for procedures, since it's loaded into /tmp. 2155 * 2156 * Ideally, the "unirect2d" proc would do a rundimentary parsing of the data 2157 * to verify the structure and then pass it to the appropiate Tcl command 2158 * (heightmap, volume, etc). Our C command always creates a heightmap. 2186 int 2187 nv::processCommands(Tcl_Interp *interp, 2188 ReadBuffer *inBufPtr, int fdOut) 2189 { 2190 int ret = 1; 2191 int status = TCL_OK; 2192 2193 Tcl_DString command; 2194 Tcl_DStringInit(&command); 2195 fd_set readFds; 2196 struct timeval tv, *tvPtr; 2197 2198 FD_ZERO(&readFds); 2199 FD_SET(inBufPtr->file(), &readFds); 2200 tvPtr = NULL; /* Wait for the first read. This is so 2201 * that we don't spin when no data is 2202 * available. */ 2203 while (inBufPtr->isLineAvailable() || 2204 (select(1, &readFds, NULL, NULL, tvPtr) > 0)) { 2205 size_t numBytes; 2206 unsigned char *buffer; 2207 2208 /* A short read is treated as an error here because we assume that we 2209 * will always get commands line by line. */ 2210 if (inBufPtr->getLine(&numBytes, &buffer) != ReadBuffer::OK) { 2211 /* Terminate the server if we can't communicate with the client 2212 * anymore. */ 2213 if (inBufPtr->status() == ReadBuffer::ENDFILE) { 2214 TRACE("Exiting server on EOF from client"); 2215 return -1; 2216 } else { 2217 ERROR("Exiting server, failed to read from client: %s", 2218 strerror(errno)); 2219 return -1; 2220 } 2221 } 2222 Tcl_DStringAppend(&command, (char *)buffer, numBytes); 2223 if (Tcl_CommandComplete(Tcl_DStringValue(&command))) { 2224 struct timeval start, finish; 2225 gettimeofday(&start, NULL); 2226 status = ExecuteCommand(interp, &command); 2227 gettimeofday(&finish, NULL); 2228 g_stats.cmdTime += (MSECS_ELAPSED(start, finish) / 1.0e+3); 2229 g_stats.nCommands++; 2230 if (status == TCL_BREAK) { 2231 return 1; /* This was caused by a "imgflush" 2232 * command. Break out of the read loop 2233 * and allow a new image to be 2234 * rendered. */ 2235 } else { //if (status != TCL_OK) { 2236 ret = 0; 2237 if (handleError(interp, status, fdOut) < 0) { 2238 return -1; 2239 } 2240 } 2241 } 2242 2243 tv.tv_sec = tv.tv_usec = 0L; /* On successive reads, we break out 2244 * if no data is available. */ 2245 FD_SET(inBufPtr->file(), &readFds); 2246 tvPtr = &tv; 2247 } 2248 2249 return ret; 2250 } 2251 2252 /** 2253 * \brief Send error message to client socket 2159 2254 */ 2160 2161 static int 2162 Unirect3dCmd(ClientData clientData, Tcl_Interp *interp, int objc, 2163 Tcl_Obj *const *objv) 2164 { 2165 Rappture::Unirect3d *dataPtr = (Rappture::Unirect3d *)clientData; 2166 2167 return dataPtr->loadData(interp, objc, objv); 2168 } 2169 2170 Tcl_Interp * 2171 initTcl() 2255 int 2256 nv::handleError(Tcl_Interp *interp, int status, int fdOut) 2257 { 2258 const char *string; 2259 int nBytes; 2260 2261 if (status != TCL_OK) { 2262 string = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); 2263 nBytes = strlen(string); 2264 if (nBytes > 0) { 2265 TRACE("status=%d errorInfo=(%s)", status, string); 2266 2267 std::ostringstream oss; 2268 oss << "nv>viserror -type internal_error -token " << g_stats.nCommands << " -bytes " << nBytes << "\n" << string; 2269 nBytes = oss.str().length(); 2270 2271 #ifdef USE_THREADS 2272 queueResponse(oss.str().c_str(), nBytes, Response::VOLATILE, Response::ERROR); 2273 #else 2274 if (write(fdOut, oss.str().c_str(), nBytes) < 0) { 2275 ERROR("write failed: %s", strerror(errno)); 2276 return -1; 2277 } 2278 #endif 2279 } 2280 } 2281 2282 string = getUserMessages(); 2283 nBytes = strlen(string); 2284 if (nBytes > 0) { 2285 TRACE("userError=(%s)", string); 2286 2287 std::ostringstream oss; 2288 oss << "nv>viserror -type error -token " << g_stats.nCommands << " -bytes " << nBytes << "\n" << string; 2289 nBytes = oss.str().length(); 2290 2291 #ifdef USE_THREADS 2292 queueResponse(oss.str().c_str(), nBytes, Response::VOLATILE, Response::ERROR); 2293 #else 2294 if (write(fdOut, oss.str().c_str(), nBytes) < 0) { 2295 ERROR("write failed: %s", strerror(errno)); 2296 return -1; 2297 } 2298 #endif 2299 clearUserMessages(); 2300 } 2301 2302 return 0; 2303 } 2304 2305 void 2306 nv::initTcl(Tcl_Interp *interp, ClientData clientData) 2172 2307 { 2173 2308 /* … … 2178 2313 * a test harness through the interpreter for nanovis. 2179 2314 */ 2180 Tcl_Interp *interp; 2181 interp = Tcl_CreateInterp(); 2182 /* 2315 2183 2316 Tcl_MakeSafe(interp); 2184 */ 2185 Tcl_CreateObjCommand(interp, "axis", AxisCmd, NULL, NULL); 2186 Tcl_CreateObjCommand(interp, "camera", CameraCmd, NULL, NULL); 2187 Tcl_CreateObjCommand(interp, "clientinfo", ClientInfoCmd, NULL, NULL); 2188 Tcl_CreateObjCommand(interp, "cutplane", CutplaneCmd, NULL, NULL); 2189 if (FlowCmdInitProc(interp) != TCL_OK) { 2190 return NULL; 2191 } 2192 Tcl_CreateObjCommand(interp, "grid", GridCmd, NULL, NULL); 2193 Tcl_CreateObjCommand(interp, "heightmap", HeightMapCmd, NULL, NULL); 2194 Tcl_CreateObjCommand(interp, "legend", LegendCmd, NULL, NULL); 2195 Tcl_CreateObjCommand(interp, "screen", ScreenCmd, NULL, NULL); 2196 Tcl_CreateObjCommand(interp, "snapshot", SnapshotCmd, NULL, NULL); 2197 Tcl_CreateObjCommand(interp, "transfunc", TransfuncCmd, NULL, NULL); 2198 Tcl_CreateObjCommand(interp, "unirect2d", Unirect2dCmd, NULL, NULL); 2199 Tcl_CreateObjCommand(interp, "unirect3d", Unirect3dCmd, NULL, NULL); 2200 Tcl_CreateObjCommand(interp, "up", UpCmd, NULL, NULL); 2201 Tcl_CreateObjCommand(interp, "volume", VolumeCmd, NULL, NULL); 2317 2318 Tcl_CreateObjCommand(interp, "axis", AxisCmd, clientData, NULL); 2319 Tcl_CreateObjCommand(interp, "camera", CameraCmd, clientData, NULL); 2320 Tcl_CreateObjCommand(interp, "clientinfo", ClientInfoCmd, clientData, NULL); 2321 Tcl_CreateObjCommand(interp, "cutplane", CutplaneCmd, clientData, NULL); 2322 FlowCmdInitProc(interp, clientData); 2323 Tcl_CreateObjCommand(interp, "grid", GridCmd, clientData, NULL); 2324 Tcl_CreateObjCommand(interp, "heightmap", HeightMapCmd, clientData, NULL); 2325 Tcl_CreateObjCommand(interp, "imgflush", ImageFlushCmd, clientData, NULL); 2326 Tcl_CreateObjCommand(interp, "legend", LegendCmd, clientData, NULL); 2327 Tcl_CreateObjCommand(interp, "screen", ScreenCmd, clientData, NULL); 2328 Tcl_CreateObjCommand(interp, "snapshot", SnapshotCmd, clientData, NULL); 2329 Tcl_CreateObjCommand(interp, "transfunc", TransfuncCmd, clientData, NULL); 2330 Tcl_CreateObjCommand(interp, "up", UpCmd, clientData, NULL); 2331 Tcl_CreateObjCommand(interp, "volume", VolumeCmd, clientData, NULL); 2202 2332 2203 2333 // create a default transfer function … … 2206 2336 Tcl_GetStringResult(interp)); 2207 2337 } 2208 return interp; 2209 } 2338 }
Note: See TracChangeset
for help on using the changeset viewer.