Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

init_linux.cpp

Go to the documentation of this file.
00001 /*
00002         $Id: init_linux.cpp,v 1.18 2001/03/19 07:26:36 plasmoid Exp $
00003 
00004         ------------------------------------------------------------------------
00005         ClanLib, the platform independent game SDK.
00006 
00007         This library is distributed under the GNU LIBRARY GENERAL PUBLIC LICENSE
00008         version 2. See COPYING for details.
00009 
00010         For a total list of contributers see CREDITS.
00011 
00012         ------------------------------------------------------------------------
00013 
00014         File purpose:
00015                 Initializes ClanLib under Linux. Home of the legendary main().
00016 
00017 */
00018 
00019 #include "Core/precomp.h"
00020 
00021 #include <sys/time.h>
00022 #include <unistd.h>
00023 #include <dlfcn.h>
00024 #include <errno.h>
00025 #include <dirent.h>
00026 #include <signal.h>
00027 #include <assert.h>
00028 #include <iostream>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include "API/core.h" // must be included. Do not remove it later on Magnus :) - mbn 21 okt 2000
00032 #include "implementation.h"
00033 #include "appconf.h"
00034 #include "API/display.h"
00035 #include "API/sound.h"
00036 #include "Display/System/Generic/setupdisplay_generic.h"
00037 #include "Sound/System/Generic/setupsound_generic.h"
00038 
00039 extern "C"
00040 {
00041         #include <Hermes/Hermes.h>
00042 }
00043 
00044 // Minor hack. The datafile compiler calls this function. Under win32 it will
00045 // create a console window for cout.
00046 void redirect_to_console(const char *title)
00047 {
00048 }
00049 
00050 
00051 #include "init_linux.h"
00052 
00053 
00054 #define TARGET_DISPLAY 0
00055 #define TARGET_SOUND 1
00056 #define TARGET_NETWORK 2
00057 
00058 
00059 struct target_structure {
00060         void *dlhandle;
00061         clan_id_proc module_id;
00062         clan_id_proc module_abbr;
00063         clan_init_proc module_init;
00064 };
00065 
00066 
00067 CL_DisplayCard *cl_current_displaycard = NULL;
00068 CL_SoundCard *cl_current_soundcard = NULL;
00069 long _begin_time;
00070 
00071 
00072 
00073 int select_display_target(const struct dirent *d)
00074 { 
00075         if (strstr(d->d_name,"libclan-display") == d->d_name &&
00076                 strstr(d->d_name,".so") != NULL &&
00077                 strstr(d->d_name,CL_VERSION_STRING) != NULL)
00078         {
00079                 return 1;
00080         }
00081         else
00082         {
00083                 return 0; 
00084         }
00085 }
00086 
00087 int select_sound_target(const struct dirent *d)
00088 { 
00089         if (strstr(d->d_name,"libclan-sound")==d->d_name &&
00090                 strstr(d->d_name,".so") != NULL &&
00091                 strstr(d->d_name,CL_VERSION_STRING) != NULL)
00092         {
00093                 return 1;
00094         }
00095         else
00096         {
00097                 return 0;
00098         }
00099 }
00100 
00101 
00102 int select_network_target(const struct dirent *d)
00103 { 
00104         if (strstr(d->d_name,"libclan-network")==d->d_name &&
00105                 strstr(d->d_name,".so") != NULL &&
00106                 strstr(d->d_name,CL_VERSION_STRING) != NULL)
00107         {
00108                 return 1;
00109         }
00110         else
00111         {
00112                 return 0;
00113         }
00114 }
00115 
00116 #ifdef USE_DYN
00117 
00118 static int num_targets_display=0;
00119 static int num_targets_sound=0;
00120 static int num_targets_network=0;
00121 
00122 target_structure* detect_targets(int target_type,const char* target_dir) 
00123 {
00124         struct dirent **filenames;
00125         int res = 0;
00126 
00127 //      std:cout << "Scanning " << target_dir << std::endl;
00128 
00129         switch(target_type)
00130         {
00131         case TARGET_DISPLAY:
00132                 res = scandir(
00133                         target_dir,
00134                         &filenames,
00135                         select_display_target,
00136                         alphasort);
00137 
00138                 num_targets_display = res;
00139                 break;
00140 
00141         case TARGET_SOUND:
00142                 res = scandir(
00143                         target_dir,
00144                         &filenames,
00145                         select_sound_target,
00146                         alphasort);
00147 
00148                 num_targets_sound = res;
00149                 break;
00150 
00151         case TARGET_NETWORK:
00152                 res = scandir(
00153                         target_dir,
00154                         &filenames,
00155                         select_network_target,
00156                         alphasort);
00157 
00158                 num_targets_network=res;
00159                 break;
00160 
00161         default:
00162                 cl_assert(false);
00163         }
00164 
00165         if (res > 0)
00166         {
00167                 char fullname[256];
00168 
00169                 target_structure *targets=new target_structure[res];
00170 
00171                 for (int i=0;i<res;i++)
00172                 {
00173                         targets[i].dlhandle=0;
00174 
00175                         strcpy(fullname,target_dir);
00176                         strcat(fullname,"/");
00177                         strcat(fullname,filenames[i]->d_name);
00178 
00179 //                      std::cout << "Trying " << filenames[i]->d_name << "... ";
00180                         
00181                         targets[i].dlhandle=dlopen(fullname,RTLD_NOW);
00182                         if (!targets[i].dlhandle)
00183                         {
00184                                 std::cout << "dlopen failed!" << std::endl;
00185                                 std::cout << dlerror() << std::endl;
00186                                 continue;
00187                         }
00188 
00189                         char *error;
00190 
00191                         targets[i].module_id = (clan_id_proc) dlsym(
00192                                         targets[i].dlhandle,
00193                                         "clan_module_identify");
00194 
00195                         if ((error = dlerror()) != NULL)
00196                         {
00197                                 std::cout << "identification failed!" << std::endl;
00198                                 continue;
00199                         }
00200 
00201                         targets[i].module_abbr = (clan_id_proc) dlsym(
00202                                 targets[i].dlhandle,
00203                                 "clan_module_abbreviation");
00204 
00205                         if ((error = dlerror()) != NULL)
00206                         {
00207                                 std::cout << "abbreviation identification failed!" << std::endl;
00208                                 continue;
00209                         }
00210                         
00211                         targets[i].module_init = (clan_init_proc) dlsym(
00212                                 targets[i].dlhandle,
00213                                 "clan_module_init");
00214 
00215                         if ((error = dlerror()) != NULL)
00216                         {
00217                                 std::cout << "module initialisation unresolved!" << std::endl;
00218                                 continue;
00219                         }
00220 
00221 //                      std::cout << "OK!" << std::endl;
00222                 }
00223 
00224                 return targets;
00225         }
00226 
00227         return 0;
00228 }
00229 
00230 #else
00231 
00232 #ifdef USE_X11
00233 #include "implementation_xwindow.h"
00234 #endif
00235 
00236 #ifdef USE_PTC
00237 #include "implementation_ptc.h"
00238 #endif
00239 
00240 #ifdef USE_SVGALIB
00241 #include "implementation_svgalib.h"
00242 #endif
00243 
00244 #ifdef USE_GGI
00245 #include "implementation_ggi.h"
00246 #endif
00247 
00248 #ifdef USE_FBDEV
00249 #include "implementation_fbdev.h"
00250 #endif
00251 
00252 #ifdef USE_OPENGL
00253 #include "implementation_glx.h"
00254 #endif
00255 
00256 #ifdef USE_CLANSOUND
00257 #include "implementation_clansound.h"
00258 #endif
00259 
00260 #ifdef USE_NETWORK
00261 #include "../../../Network/Unix/network_unix.h"
00262 #endif
00263 
00264 static int num_targets_display=6;
00265 static int num_targets_sound=1;
00266 static int num_targets_network=1;
00267 
00268 target_structure* detect_targets(int target_type,const char* target_dir)
00269 {
00270         static target_structure disp_targets[6]=
00271         {
00272                 {(void*)0xff,xwindow_identify,xwindow_abbreviation,xwindow_init},
00273 #ifdef USE_PTC
00274                 {(void*)0xff,ptc_identify,ptc_abbreviation,ptc_init},
00275 #else
00276                 {(void*)0,(clan_id_proc)0,(clan_id_proc)0,(clan_init_proc)0},
00277 #endif
00278 #ifdef USE_SVGALIB
00279                 {(void*)0xff,svgalib_identify,svgalib_abbreviation,svgalib_init},
00280 #else
00281                 {(void*)0,(clan_id_proc)0,(clan_id_proc)0,(clan_init_proc)0},
00282 #endif
00283 #ifdef USE_GGI
00284                 {(void*)0xff,ggi_identify,ggi_abbreviation,ggi_init},
00285 #else
00286                 {(void*)0,(clan_id_proc)0,(clan_id_proc)0,(clan_init_proc)0},
00287 #endif
00288 #ifdef USE_FBDEV
00289                 {(void*)0xff,fbdev_identify,fbdev_abbreviation,fbdev_init},
00290 #else
00291                 {(void*)0,(clan_id_proc)0,(clan_id_proc)0,(clan_init_proc)0},
00292 #endif
00293 #ifdef USE_OPENGL
00294                 {(void*)0xff,glx_identify,glx_abbreviation,glx_init},
00295 #else
00296                 {(void*)0,(clan_id_proc)0,(clan_id_proc)0,(clan_init_proc)0},
00297 #endif
00298         };
00299 
00300 #ifdef USE_CLANSOUND
00301         static target_structure sound_targets[1]=
00302         {
00303                 {(void*)0xff,clansound_identify,clansound_abbreviation,clansound_init}
00304         };
00305 #endif
00306 
00307 #ifdef USE_NETWORK
00308         static target_structure net_targets[1]=
00309         {
00310                 {(void*)0xff,network_identify,network_abbreviation,network_init}
00311         };
00312 #endif
00313 
00314         switch (target_type)
00315         {
00316         case TARGET_DISPLAY:
00317                 return disp_targets;
00318 
00319 #ifdef USE_CLANSOUND
00320         case TARGET_SOUND:
00321                 return sound_targets;
00322 #endif
00323 
00324 #ifdef USE_NETWORK
00325         case TARGET_NETWORK:
00326                 return net_targets;
00327 #endif
00328         }
00329 
00330         // Make the compiler happy
00331         return (target_structure*)0x0;
00332 }
00333 
00334 
00335 #endif
00336 
00337 void CL_SetupDisplay::init()
00338 {
00339         FileConfig config("clanlib");
00340         std::string display = config.readEntry("display", "default");
00341         std::string scandir = config.readEntry("targetdir", CL_SCANDIR);
00342         
00343         // Check if any library forces a particular display target:
00344         if (strcmp(CL_Force_DispTarget::get_name().c_str(), "") != 0)
00345         {
00346                 display = CL_Force_DispTarget::get_name();
00347         }
00348 /*      if (strcmp(CL_Force_DispTarget::name.c_str(), "") != 0)
00349         {
00350                 display = CL_Force_DispTarget::name;
00351         }
00352 */
00353         target_structure *targets = detect_targets(TARGET_DISPLAY,scandir.c_str());
00354         target_structure *chosen_display = 0;
00355 
00356         char choice[16];
00357         
00358         // try and use the X11 target, if it is available. If it is not, ask the user.
00359         if (display == "default")
00360         {
00361                 bool found = false;
00362                 display = "x11";
00363                 for (int i=0;i<num_targets_display;i++) 
00364                 {
00365                         if (targets[i].dlhandle!=0)
00366                         {
00367                                 if (!strcmp(targets[i].module_abbr(),display.c_str()))
00368                                 {
00369                                         found = true;
00370                                         break;
00371                                 }
00372                         }
00373                 }
00374                 
00375                 if (found==false) display = "ask";
00376         }
00377         if(getenv("DISPLAY")==NULL && display=="x11") 
00378                 display="ask";
00379         //Sanity check X11
00380 
00381         if (display == "ask")
00382         {
00383                 std::cout << std::endl << "Please select a display target by entering its abbreviation: " << std::endl;
00384                 
00385                 for (int i=0;i<num_targets_display;i++) 
00386                 {
00387                         if (targets[i].dlhandle!=0)
00388                         {
00389                                 std::cout << "  [" << targets[i].module_abbr() << "] ";
00390                                 std::cout << targets[i].module_id() << std::endl;
00391                         }
00392                 }
00393 
00394                 std::cout << "Your choice: ";
00395                 std::cin >> choice;
00396         }
00397         else
00398         {
00399                 strcpy(choice, display.c_str());
00400         }
00401 
00402         for (int i=0;i<num_targets_display;i++) 
00403         {
00404                 if (targets[i].dlhandle!=0)
00405                 {
00406                         if (!strcmp(targets[i].module_abbr(),choice))
00407                         {
00408                                 chosen_display=&targets[i];
00409                                 break;
00410                         }
00411                 }
00412         }
00413 
00414         if (!chosen_display)
00415         {
00416                 throw CL_Error("Cannot open display target");
00417         }
00418         else
00419         {
00420                 for (int i=0;i<num_targets_display;i++)
00421                 {
00422                         if (targets[i].dlhandle!=0)
00423                         {
00424                                 if (!strcmp(targets[i].module_abbr(),display.c_str()))
00425                                 {
00426                                         chosen_display=&targets[i];
00427                                         break;
00428                                 }
00429                         }
00430                 }
00431 
00432                 if (!chosen_display) throw CL_Error("Cannot open display target");
00433         }
00434 
00435         chosen_display->module_init();
00436 
00437 //      CL_Display::num_cards = CL_Display::cards.size();
00438         cl_current_displaycard = CL_Display::cards[0];
00439         
00440         CL_SetupDisplay_Generic::init();
00441 }
00442 
00443 void CL_SetupSound::init()
00444 {
00445         FileConfig config("clanlib");
00446         std::string scandir = config.readEntry("targetdir", CL_SCANDIR);
00447 
00448         target_structure* targets=detect_targets(TARGET_SOUND,scandir.c_str());
00449 
00450         if (num_targets_sound<=0 || targets[0].dlhandle==0)
00451                 return;
00452 //              throw CL_Error("Unable to load any sound implementations");
00453 
00454         targets[0].module_init();
00455         if (CL_Sound::cards.size() > 0) cl_current_soundcard = CL_Sound::cards[0];
00456 
00457         CL_SetupSound_Generic::init();
00458 }
00459 
00460 /*
00461 void CL_SetupNetwork::init()
00462 {
00463         FileConfig config("clanlib");
00464         std::string scandir = config.readEntry("targetdir", CL_SCANDIR);
00465         target_structure* targets=detect_targets(TARGET_NETWORK,scandir.c_str());
00466 
00467         if (num_targets_network<=0 || targets[0].dlhandle==0)
00468                 return;
00469 //              throw CL_Error("Unable to load any network implementations");
00470 
00471         targets[0].module_init();
00472 }
00473 */
00474 
00475 void CL_SetupDisplay::deinit()
00476 {
00477         CL_SetupDisplay_Generic::deinit();
00478 
00479         int num_cards = CL_Display::cards.size();
00480         for (int i=0; i<num_cards; i++) delete CL_Display::cards[i];
00481         CL_Display::cards.clear();
00482 //      CL_Display::num_cards = 0;
00483 }
00484 
00485 void CL_SetupSound::deinit()
00486 {
00487         CL_SetupSound_Generic::deinit();
00488 
00489         int num_cards = CL_Sound::cards.size();
00490         for (int i=0; i<num_cards; i++) delete CL_Sound::cards[i]; 
00491         CL_Sound::cards.clear();
00492 //      CL_Sound::num_cards = 0;
00493 }
00494 
00495 /*
00496 void CL_SetupDisplay::deinit()
00497 {
00498 #ifdef USE_NETWORK
00499         // TODO: Add deinit code here...
00500 #endif
00501 }
00502 */
00503 
00504 void deinit()
00505 {
00506         // Deinitialization:
00507         CL_SetupDisplay::deinit();
00508         CL_SetupSound::deinit();
00509         //CL_SetupNetwork::deinit();
00510 
00511         int num_keyboards = CL_Input::keyboards.size();
00512         int num_joysticks = CL_Input::joysticks.size();
00513         int num_pointers = CL_Input::pointers.size();
00514 
00515         for (int i=0; i<num_keyboards; i++) delete CL_Input::keyboards[i];
00516         for (int i=0; i<num_joysticks; i++) delete CL_Input::joysticks[i];
00517         for (int i=0; i<num_pointers; i++) delete CL_Input::pointers[i];
00518         #ifdef NDEBUG
00519         signal(SIGSEGV,SIG_DFL); //restore default behavior
00520         #endif
00521 }
00522 
00523 static int init_ref_count = 0;
00524 void init_system()
00525 {
00526         init_ref_count++;
00527         if (init_ref_count > 1) return;
00528 
00529         Hermes_Init();
00530 
00531         timeval tv;
00532         gettimeofday(&tv, NULL);
00533         _begin_time = (long) tv.tv_sec*(long) 1000+(long) tv.tv_usec/(long) 1000;
00534         #ifdef NDEBUG
00535         signal(SIGSEGV, deinit);
00536         #endif
00537         
00538 
00539 }
00540 
00541 void deinit_system()
00542 {
00543         init_ref_count--;
00544         if (init_ref_count > 0) return;
00545 
00546         deinit();
00547 }
00548 
00549 unsigned int CL_System::get_time()
00550 {
00551         timeval tv;
00552         gettimeofday(&tv, NULL);
00553 
00554         long tid = (long) tv.tv_sec*(long) 1000 + (long) tv.tv_usec/(long) 1000 - _begin_time;
00555 
00556         return tid;
00557 }
00558 
00559 void CL_System::sleep(int millis)
00560 {
00561         struct timeval tv;
00562         // select doesn't modify timeval if interrupted on non Linux systems
00563 #ifndef linux 
00564         int then, now, elapsed;
00565         then = CL_System::get_time();
00566 #else
00567         tv.tv_sec = millis/ 1000;
00568         tv.tv_usec = (millis%1000)*1000;
00569 #endif
00570 
00571         int was_error;  
00572         do
00573         {
00574                 errno = 0;
00575 #ifndef linux
00576                 now = CL_System::get_time();
00577                 elapsed = now - then;
00578                 then = now;
00579                 if ( elapsed >= millis )
00580                         break;
00581                 millis -= elapsed;
00582                 tv.tv_sec = millis/1000;
00583                 tv.tv_ysec = (millis%1000)*1000;
00584 #endif
00585                 was_error = select(0, NULL, NULL, NULL, &tv);
00586         }
00587         while ( (errno == EINTR) && was_error); 
00588 //      usleep(millis*1000);
00589 }
00590 
00591 void CL_Display::select_card(CL_DisplayCard *card)
00592 {
00593         cl_current_displaycard = card;
00594 }
00595 
00596 CL_DisplayCard *CL_Display::get_current_card()
00597 {
00598         cl_assert(cl_current_displaycard != NULL);
00599         return cl_current_displaycard;
00600 }
00601 
00602 void CL_Sound::select_card(CL_SoundCard *card)
00603 {
00604         cl_current_soundcard = card;
00605 }
00606 
00607 /*CL_SoundCard *CL_Sound::get_current_card()
00608 {
00609         cl_assert(cl_current_soundcard != NULL);
00610         return cl_current_soundcard;
00611 }
00612 */
00613 // -----------------------------------------------------------------------
00614 
00615 std::string CL_Force_DispTarget::name;
00616 
00617 CL_Force_DispTarget::CL_Force_DispTarget(const char *_name)
00618 {
00619         // Make sure there is only one display target force!
00620         cl_assert( strcmp(name.c_str(), "") == 0 );
00621 
00622         name = _name;
00623 }

Generated at Wed Apr 4 19:54:00 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001