00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00047 #include <sys/types.h>
00048 #include <dirent.h>
00049 #include <unistd.h>
00050 #include <fcntl.h>
00051 #include <signal.h>
00052 #include <stropts.h>
00053
00054 #include <iostream>
00055
00056 #include <archon/math/vector.H>
00057 #include <archon/util/thread.H>
00058 #include <archon/util/ref.H>
00059 #include <archon/util/options.H>
00060 #include <archon/util/file.H>
00061 #include <archon/util/text.H>
00062
00063 #include <archon/x3d/proxy/exception.H>
00064 #include <archon/x3d/proxy/proxy.H>
00065
00066 using namespace std;
00067 using namespace Archon;
00068 using namespace Archon::Math;
00069 using namespace Archon::Utilities;
00070 using namespace Archon::X3D::Proxy;
00071
00072 namespace Archon
00073 {
00074 namespace SaiTestApps
00075 {
00076 namespace Filebrowser
00077 {
00078 Mutex mutex;
00079 Condition directoryRefresh(mutex);
00080
00081 string path;
00082
00083 Ref<Shape> inactiveBoxShape;
00084 Ref<Shape> activeBoxShape;
00085
00086 void handleSignalIO(int s)
00087 {
00088 directoryRefresh.notifyAll();
00089 }
00090
00091 void handleBack(Time)
00092 {
00093 {
00094 Mutex::Lock l(mutex);
00095 chdir("..");
00096 path = File::getCWD();
00097 }
00098 directoryRefresh.notifyAll();
00099 }
00100
00101 void handleSubdir(Time, string dir)
00102 {
00103 {
00104 Mutex::Lock l(mutex);
00105 chdir(dir.c_str());
00106 path = File::getCWD();
00107 }
00108 directoryRefresh.notifyAll();
00109 }
00110
00111 void handleText(Time, string file)
00112 {
00113 {
00114 cerr << "FILE=" << file << "\n";
00115 Mutex::Lock l(mutex);
00116 string s = "archon_textviewer " + file + " &";
00117 system(s.c_str());
00118 }
00119 }
00120
00121 void handleX3D(Time, string file)
00122 {
00123 {
00124 cerr << "FILE=" << file << "\n";
00125 Mutex::Lock l(mutex);
00126 string s = "archon_x3d_viewer " + file + " &";
00127 system(s.c_str());
00128 }
00129 }
00130
00131 void handlePDB(Time, string file)
00132 {
00133 {
00134 cerr << "FILE=" << file << "\n";
00135 Mutex::Lock l(mutex);
00136 string s = "archon_molecule " + file + " &";
00137 system(s.c_str());
00138 }
00139 }
00140
00141 void handleExecutable(Time, string file)
00142 {
00143 {
00144 cerr << "FILE=" << file << "\n";
00145 Mutex::Lock l(mutex);
00146 string s = file + " &";
00147 system(s.c_str());
00148 }
00149 }
00150
00151 class TextBox: public virtual RefObjectBase
00152 {
00153 string textString;
00154 Ref<Application> application;
00155 Ref<Transform> transform;
00156 public:
00157 TextBox(string s, Ref<Application> a)
00158 {
00159 textString = s;
00160 application = a;
00161
00162
00163 Ref<Transform> boxTransform = Transform::create(application);
00164 boxTransform->scale = Vector3(3, 0.8, 0.1);
00165 boxTransform->children.add(inactiveBoxShape);
00166
00167
00168 Ref<Transform> textTransform = Transform::create(application);
00169 textTransform->translation = Vector3(-2.9, 0, 0.11);
00170
00171 Ref<FontStyle> fontStyle = FontStyle::create(application);
00172 vector<string> justifyStrings;
00173 justifyStrings.push_back("BEGIN");
00174 justifyStrings.push_back("MIDDLE");
00175 fontStyle->justify = justifyStrings;
00176
00177 Ref<X3D::Proxy::Text> text = X3D::Proxy::Text::create(application);
00178 text->string.add(textString);
00179 text->maxExtent = 5.8;
00180 text->fontStyle = fontStyle;
00181
00182 Ref<Shape> textShape = Shape::create(application);
00183 Ref<Appearance> textApp= Appearance::create(application);
00184 Ref<Material> textMaterial = Material::create(application);
00185 textMaterial->diffuseColor = Vector3(0.7, 0.7, 0.2);
00186 textApp->material = textMaterial;
00187 textShape->appearance = textApp;
00188 textShape->geometry = text;
00189 textTransform->children.add(textShape);
00190
00191
00192 transform = Transform::create(application);
00193 transform->children.add(boxTransform);
00194 transform->children.add(textTransform);
00195 }
00196
00197 Ref<Transform> getTransform()
00198 {
00199 return transform;
00200 }
00201
00202 };
00203
00204
00205 class FileScan
00206 {
00207 private:
00208 DIR *fd;
00209
00210 public:
00211 FileScan(string s, void(*func)(int))
00212 {
00213 struct sigaction sa;
00214 sa.sa_handler = func;
00215
00216 if(sigaction(SIGIO, &sa, 0))
00217 {
00218 cerr << "Signal handler NOT installed\n";
00219 abort();
00220 }
00221
00222 fd = opendir(s.c_str());
00223 int fd_dir = dirfd(fd);
00224 if(fd_dir == -1)
00225 {
00226 cerr << "Directory -> FD failed\n";
00227 abort();
00228 }
00229
00230 if(fcntl(fd_dir, F_SETFL, O_ASYNC) == -1)
00231 {
00232 cerr << "IOCTL NOT called succesfully\n";
00233 abort();
00234 }
00235
00236 if(fcntl(fd_dir, F_NOTIFY, DN_MULTISHOT|DN_CREATE|DN_DELETE|DN_RENAME) == -1)
00237 {
00238 cerr << "IOCTL NOT called succesfully\n";
00239 abort();
00240 }
00241 }
00242
00243 ~FileScan()
00244 {
00245 if(fd)
00246 if(closedir(fd))
00247 {
00248 cerr << "IO-operation (close) failed.\n";
00249 abort();
00250 }
00251 }
00252 };
00253
00254 int fileSort(const void *a, const void *b)
00255 {
00256 struct stat a_filestat;
00257 struct stat b_filestat;
00258
00259
00260 lstat((*(const struct dirent **)(a))->d_name, &a_filestat);
00261 lstat((*(const struct dirent **)(b))->d_name, &b_filestat);
00262
00263 if(S_ISDIR(a_filestat.st_mode) && !S_ISDIR(b_filestat.st_mode))
00264 return -1;
00265 else if(!S_ISDIR(a_filestat.st_mode) && S_ISDIR(b_filestat.st_mode))
00266 return 1;
00267 else
00268 return alphasort(a, b);
00269 }
00270
00271 void drawDirectory(string fullPath, Ref<Application> application, Ref<GroupingNode> rootGroup)
00272 {
00273 struct stat filestat;
00274 struct dirent **namelist;
00275 int n;
00276 int radius=30;
00277 int x=0;
00278 int y=11;
00279 vector<Ref<ChildNode> > children0;
00280 Ref<Transform> rootTransform;
00281
00282
00283 Ref<Transform> lightTransform = Transform::create(application);
00284 lightTransform->translation = Vector3(0, 10, 0);
00285 Ref<PointLight> light = PointLight::create(application);
00286 light->location = Vector3(0, 10, 0);
00287 light->on = true;
00288 light->color = Vector3(1, 1, 1);
00289 light->intensity = 0.7;
00290 lightTransform->children.add(light);
00291 children0.push_back(lightTransform);
00292
00293 n = scandir(fullPath.c_str(), &namelist, 0, fileSort);
00294 if(n < 0)
00295 {
00296 cerr << "scandir error\n";
00297 abort();
00298 }
00299 else
00300 {
00301 for(int i=0;i<n;++i)
00302 {
00303 if(strcmp(namelist[i]->d_name,".") == 0)
00304 {
00305 free(namelist[i]);
00306 continue;
00307 }
00308
00309 rootTransform = Transform::create(application);
00310 rootTransform->rotation = Rotation3(Vector3(0, -1, 0), x*6.05/radius);
00311 rootTransform->translation = Vector3(0, 0, 0);
00312
00313 if(strcmp(namelist[i]->d_name,"..") == 0)
00314 {
00315
00316 Ref<TextBox> textBox = new TextBox("../", application);
00317 Ref<Transform> tr = textBox->getTransform();
00318 tr->translation = Vector3(0, y*1.8, -radius);
00319
00320 Ref<TouchSensor> touch = TouchSensor::create(application);
00321 touch->touchTime.registerInterest<SFTime>(new FuncCaller<SFTime>(handleBack));
00322 rootTransform->children.add(tr);
00323 rootTransform->children.add(touch);
00324 children0.push_back(rootTransform);
00325
00326 free(namelist[i]);
00327 y--;
00328 if(y<1)
00329 {
00330 y=11;
00331 x++;
00332 }
00333 continue;
00334 }
00335
00336 string s;
00337 if(fullPath == "/")
00338 s = fullPath + static_cast<string>(namelist[i]->d_name);
00339 else
00340 s = fullPath + "/" + static_cast<string>(namelist[i]->d_name);
00341 lstat(s.c_str(), &filestat);
00342 int perm = access(s.c_str(), X_OK);
00343
00344 s = static_cast<string>(namelist[i]->d_name);
00345
00346 if(S_ISDIR(filestat.st_mode))
00347 {
00348 Ref<TextBox> textBox = new TextBox(s + "/", application);
00349 Ref<Transform> tr = textBox->getTransform();
00350 tr->setTranslation(Vector3(0, y*1.8, -radius));
00351
00352 if(perm==0)
00353 {
00354 Ref<TouchSensor> touch = TouchSensor::create(application);
00355 touch->touchTime.registerInterest<SFTime>(new CookieFuncCaller<SFTime, string>(handleSubdir, s));
00356 rootTransform->children.add(touch);
00357 }
00358 rootTransform->children.add(tr);
00359 }
00360 else
00361 {
00362 Ref<TextBox> textBox = new TextBox(s, application);
00363 Ref<Transform> tr = textBox->getTransform();
00364 tr->translation = Vector3(0, y*1.8, -radius);
00365
00366 if(perm==0)
00367 {
00368 Ref<TouchSensor> touch = TouchSensor::create(application);
00369 touch->touchTime.registerInterest<SFTime>(new CookieFuncCaller<SFTime, string>(handleExecutable, s));
00370 rootTransform->children.add(touch);
00371 }
00372 else if(Archon::Utilities::Text::isSuffixOf(".x3d", s, true))
00373 {
00374 Ref<TouchSensor> touch = TouchSensor::create(application);
00375 touch->touchTime.registerInterest<SFTime>(new CookieFuncCaller<SFTime, string>(handleX3D, s));
00376 rootTransform->children.add(touch);
00377 }
00378 else if(Archon::Utilities::Text::isSuffixOf(".pdb", s, true))
00379 {
00380 Ref<TouchSensor> touch = TouchSensor::create(application);
00381 touch->touchTime.registerInterest<SFTime>(new CookieFuncCaller<SFTime, string>(handlePDB, s));
00382 rootTransform->children.add(touch);
00383 }
00384 else
00385 {
00386 Ref<TouchSensor> touch = TouchSensor::create(application);
00387 touch->touchTime.registerInterest<SFTime>(new CookieFuncCaller<SFTime, string>(handleText, s));
00388 rootTransform->children.add(touch);
00389 }
00390
00391 rootTransform->children.add(tr);
00392 }
00393 children0.push_back(rootTransform);
00394 free(namelist[i]);
00395 y--;
00396 if(y<1)
00397 {
00398 y=11;
00399 x++;
00400 }
00401 }
00402 free(namelist);
00403 }
00404
00405 children0.push_back(rootTransform);
00406 rootGroup->children = children0;
00407 }
00408
00409 int main(int argc, const char *argv[]) throw()
00410 {
00411 bool opt_help = false;
00412 int opt_corbaEndpointPort = -1;
00413 string opt_serverName = "archon";
00414
00415 Options o;
00416
00417 o.addSwitch("h", "help", opt_help, true,
00418 "Describe the parameters");
00419 o.addConfig("p", "corba-endpoint-port", opt_corbaEndpointPort, opt_corbaEndpointPort,
00420 "The TCP/IP port on which the CORBA Orb listens (-1 for auto assign)",
00421 Options::wantArg_always);
00422 o.addConfig("n", "server-name", opt_serverName, opt_serverName,
00423 "The name of the server to connect to",
00424 Options::wantArg_always);
00425
00426 if(o.processCommandLine(argc, argv))
00427 {
00428 cerr << "Try --help\n";
00429 return 1;
00430 }
00431
00432 if(opt_help)
00433 {
00434 cout <<
00435 "Test Application for 3D-Console by Brian Kristiansen & Kristian Spangsege\n"
00436 "\n"
00437 "Synopsis: " << argv[0] << "\n"
00438 "\n"
00439 "Available options:\n";
00440 cout << o.list();
00441 return 0;
00442 }
00443
00444 if(argc > 2)
00445 {
00446 cerr << "Too many aguments\n";
00447 cerr << "Try --help\n";
00448 return 1;
00449 }
00450
00451 if(argc == 2)
00452 {
00453 path = argv[1];
00454 chdir(argv[1]);
00455 }
00456 else path = File::getCWD();
00457
00458 Ref<Session> session =
00459 Session::create(opt_serverName, opt_corbaEndpointPort);
00460
00461 Ref<Application> application =
00462 Application::create(session, Uri());
00463
00464 Ref<Group> rootGroup = Group::create(application);
00465
00466 inactiveBoxShape = Shape::create(application);
00467 Ref<Appearance> inactiveAppearance = Appearance::create(application);
00468 Ref<Material> inactiveMaterial = Material::create(application);
00469 inactiveMaterial->diffuseColor = Vector3(0.3, 0.3, 0.8);
00470 inactiveMaterial->transparency = 0.7;
00471 inactiveAppearance->material = inactiveMaterial;
00472 Ref<Box> inactiveBox = Box::create(application);
00473 inactiveBoxShape->geometry = inactiveBox;
00474 inactiveBoxShape->appearance = inactiveAppearance;
00475
00476 activeBoxShape = Shape::create(application);
00477 Ref<Appearance> activeAppearance = Appearance::create(application);
00478 Ref<Material> activeMaterial = Material::create(application);
00479 activeMaterial->diffuseColor = Vector3(0.5, 0.5, 0.8);
00480 activeMaterial->transparency = 0.2;
00481 activeAppearance->material = activeMaterial;
00482 Ref<Box> activeBox = Box::create(application);
00483 activeBoxShape->geometry = activeBox;
00484 activeBoxShape->appearance = activeAppearance;
00485
00486 Ref<Transform> rootTransform = Transform::create(application);
00487 rootTransform->scale = Vector3(.8, .8, .8);
00488 rootTransform->translation = Vector3(0, -7, 4);
00489
00490 rootGroup->children.add(rootTransform);
00491
00492 application->setRootGroup(rootGroup);
00493 application->launch();
00494
00495 for(;;)
00496 {
00497 FileScan fs(path, handleSignalIO);
00498 session->beginUpdate();
00499 drawDirectory(path, application, rootTransform);
00500 session->endUpdate();
00501 directoryRefresh.wait();
00502 }
00503
00504 return 0;
00505 }
00506 }
00507 }
00508 }
00509
00510 int main(int argc, const char *argv[]) throw()
00511 {
00512 using namespace std;
00513 using namespace Archon::Utilities;
00514 using namespace Archon::X3D;
00515
00516 set_unexpected(Exception::terminal<Proxy::exceptionCatchInfo>);
00517 set_terminate (Exception::terminal<Proxy::exceptionCatchInfo>);
00518
00519 return Archon::SaiTestApps::Filebrowser::main(argc, argv);
00520 }