main.C

Go to the documentation of this file.
00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
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           // Box
00163           Ref<Transform> boxTransform = Transform::create(application);
00164           boxTransform->scale = Vector3(3, 0.8, 0.1);
00165           boxTransform->children.add(inactiveBoxShape);
00166           
00167           // Text
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           // Transform
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         // Setup Point light
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; // Auto assign
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 }

Generated on Sun Jul 30 22:55:41 2006 for Archon by  doxygen 1.4.4