00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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"
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
00045
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
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
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
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
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
00344 if (strcmp(CL_Force_DispTarget::get_name().c_str(), "") != 0)
00345 {
00346 display = CL_Force_DispTarget::get_name();
00347 }
00348
00349
00350
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
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
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
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
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
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
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
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
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 void deinit()
00505 {
00506
00507 CL_SetupDisplay::deinit();
00508 CL_SetupSound::deinit();
00509
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);
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
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
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
00608
00609
00610
00611
00612
00613
00614
00615 std::string CL_Force_DispTarget::name;
00616
00617 CL_Force_DispTarget::CL_Force_DispTarget(const char *_name)
00618 {
00619
00620 cl_assert( strcmp(name.c_str(), "") == 0 );
00621
00622 name = _name;
00623 }