src/SDL.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 06 Jul 2013 12:28:57 -0700
changeset 7360 b86947ea2749
parent 7346 ff228f955a48
child 7588 f1ca6adffc4b
permissions -rw-r--r--
Make it possible to use SDL events separately from the video subsystem.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* Initialization code for SDL */
    24 
    25 #include "SDL.h"
    26 #include "SDL_bits.h"
    27 #include "SDL_revision.h"
    28 #include "SDL_fatal.h"
    29 #include "SDL_assert_c.h"
    30 #include "events/SDL_events_c.h"
    31 #include "haptic/SDL_haptic_c.h"
    32 #include "joystick/SDL_joystick_c.h"
    33 
    34 /* Initialization/Cleanup routines */
    35 #if !SDL_TIMERS_DISABLED
    36 extern int SDL_TimerInit(void);
    37 extern void SDL_TimerQuit(void);
    38 extern void SDL_InitTicks(void);
    39 #endif
    40 #if SDL_VIDEO_DRIVER_WINDOWS
    41 extern int SDL_HelperWindowCreate(void);
    42 extern int SDL_HelperWindowDestroy(void);
    43 #endif
    44 
    45 
    46 /* The initialized subsystems */
    47 #ifdef SDL_MAIN_NEEDED
    48 static SDL_bool SDL_MainIsReady = SDL_FALSE;
    49 #else
    50 static SDL_bool SDL_MainIsReady = SDL_TRUE;
    51 #endif
    52 static SDL_bool SDL_bInMainQuit = SDL_FALSE;
    53 static Uint8 SDL_SubsystemRefCount[ 32 ];
    54 
    55 /* Private helper to increment a subsystem's ref counter. */
    56 static void
    57 SDL_PrivateSubsystemRefCountIncr(Uint32 subsystem)
    58 {
    59     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    60     SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
    61     ++SDL_SubsystemRefCount[subsystem_index];
    62 }
    63 
    64 /* Private helper to decrement a subsystem's ref counter. */
    65 static void
    66 SDL_PrivateSubsystemRefCountDecr(Uint32 subsystem)
    67 {
    68     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    69     if (SDL_SubsystemRefCount[subsystem_index] > 0) {
    70         --SDL_SubsystemRefCount[subsystem_index];
    71     }
    72 }
    73 
    74 /* Private helper to check if a system needs init. */
    75 static SDL_bool
    76 SDL_PrivateShouldInitSubsystem(Uint32 subsystem)
    77 {
    78     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    79     SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
    80     return (SDL_SubsystemRefCount[subsystem_index] == 0);
    81 }
    82 
    83 /* Private helper to check if a system needs to be quit. */
    84 static SDL_bool
    85 SDL_PrivateShouldQuitSubsystem(Uint32 subsystem) {
    86     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    87     if (SDL_SubsystemRefCount[subsystem_index] == 0) {
    88       return SDL_FALSE;
    89     }
    90 
    91     /* If we're in SDL_Quit, we shut down every subsystem, even if refcount
    92      * isn't zero.
    93      */
    94     return SDL_SubsystemRefCount[subsystem_index] == 1 || SDL_bInMainQuit;
    95 }
    96 
    97 void
    98 SDL_SetMainReady(void)
    99 {
   100     SDL_MainIsReady = SDL_TRUE;
   101 }
   102 
   103 int
   104 SDL_InitSubSystem(Uint32 flags)
   105 {
   106     if (!SDL_MainIsReady) {
   107         SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?");
   108         return -1;
   109     }
   110 
   111 #if !SDL_TIMERS_DISABLED
   112     SDL_InitTicks();
   113 #endif
   114 
   115     if ((flags & SDL_INIT_GAMECONTROLLER)) {
   116         /* game controller implies joystick */
   117         flags |= SDL_INIT_JOYSTICK;
   118     }
   119 
   120     if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
   121         /* video or joystick implies events */
   122         flags |= SDL_INIT_EVENTS;
   123     }
   124 
   125     /* Initialize the event subsystem */
   126     if ((flags & SDL_INIT_EVENTS)) {
   127 #if !SDL_EVENTS_DISABLED
   128         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_EVENTS)) {
   129             if (SDL_StartEventLoop() < 0) {
   130                 return (-1);
   131             }
   132             SDL_QuitInit();
   133         }
   134         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_EVENTS);
   135 #else
   136         return SDL_SetError("SDL not built with events support");
   137 #endif
   138     }
   139 
   140     /* Initialize the timer subsystem */
   141     if ((flags & SDL_INIT_TIMER)){
   142 #if !SDL_TIMERS_DISABLED
   143         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_TIMER)) {
   144             if (SDL_TimerInit() < 0) {
   145                 return (-1);
   146             }
   147         }
   148         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_TIMER);
   149 #else
   150         return SDL_SetError("SDL not built with timer support");
   151 #endif
   152     }
   153 
   154     /* Initialize the video subsystem */
   155     if ((flags & SDL_INIT_VIDEO)){
   156 #if !SDL_VIDEO_DISABLED
   157         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_VIDEO)) {
   158             if (SDL_VideoInit(NULL) < 0) {
   159                 return (-1);
   160             }
   161         }
   162         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_VIDEO);
   163 #else
   164         return SDL_SetError("SDL not built with video support");
   165 #endif
   166     }
   167 
   168     /* Initialize the audio subsystem */
   169     if ((flags & SDL_INIT_AUDIO)){
   170 #if !SDL_AUDIO_DISABLED
   171         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_AUDIO)) {
   172             if (SDL_AudioInit(NULL) < 0) {
   173                 return (-1);
   174             }
   175         }
   176         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_AUDIO);
   177 #else
   178         return SDL_SetError("SDL not built with audio support");
   179 #endif
   180     }
   181 
   182     /* Initialize the joystick subsystem */
   183     if ((flags & SDL_INIT_JOYSTICK)){
   184 #if !SDL_JOYSTICK_DISABLED
   185         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_JOYSTICK)) {
   186            if (SDL_JoystickInit() < 0) {
   187                return (-1);
   188            }
   189         }
   190         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_JOYSTICK);
   191 #else
   192         return SDL_SetError("SDL not built with joystick support");
   193 #endif
   194     }
   195 
   196     if ((flags & SDL_INIT_GAMECONTROLLER)){
   197 #if !SDL_JOYSTICK_DISABLED
   198         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_GAMECONTROLLER)) {
   199             if (SDL_GameControllerInit() < 0) {
   200                 return (-1);
   201             }
   202         }
   203         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_GAMECONTROLLER);
   204 #else
   205         return SDL_SetError("SDL not built with joystick support");
   206 #endif
   207     }
   208 
   209     /* Initialize the haptic subsystem */
   210     if ((flags & SDL_INIT_HAPTIC)){
   211 #if !SDL_HAPTIC_DISABLED
   212         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_HAPTIC)) {
   213             if (SDL_HapticInit() < 0) {
   214                 return (-1);
   215             }
   216         }
   217         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_HAPTIC);
   218 #else
   219         return SDL_SetError("SDL not built with haptic (force feedback) support");
   220 #endif
   221     }
   222 
   223     return (0);
   224 }
   225 
   226 int
   227 SDL_Init(Uint32 flags)
   228 {
   229     if (SDL_AssertionsInit() < 0) {
   230         return -1;
   231     }
   232 
   233     /* Clear the error message */
   234     SDL_ClearError();
   235 
   236 #if SDL_VIDEO_DRIVER_WINDOWS
   237     if (SDL_HelperWindowCreate() < 0) {
   238         return -1;
   239     }
   240 #endif
   241 
   242     /* Initialize the desired subsystems */
   243     if (SDL_InitSubSystem(flags) < 0) {
   244         return (-1);
   245     }
   246 
   247     /* Everything is initialized */
   248     if (!(flags & SDL_INIT_NOPARACHUTE)) {
   249         SDL_InstallParachute();
   250     }
   251 
   252     return (0);
   253 }
   254 
   255 void
   256 SDL_QuitSubSystem(Uint32 flags)
   257 {
   258     /* Shut down requested initialized subsystems */
   259 #if !SDL_JOYSTICK_DISABLED
   260     if ((flags & SDL_INIT_GAMECONTROLLER)) {
   261         /* game controller implies joystick */
   262         flags |= SDL_INIT_JOYSTICK;
   263 
   264         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_GAMECONTROLLER)) {
   265             SDL_GameControllerQuit();
   266         }
   267         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_GAMECONTROLLER);
   268     }
   269 
   270     if ((flags & SDL_INIT_JOYSTICK)) {
   271         /* joystick implies events */
   272         flags |= SDL_INIT_EVENTS;
   273 
   274         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_JOYSTICK)) {
   275             SDL_JoystickQuit();
   276         }
   277         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_JOYSTICK);
   278     }
   279 #endif
   280 
   281 #if !SDL_HAPTIC_DISABLED
   282     if ((flags & SDL_INIT_HAPTIC)) {
   283         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_HAPTIC)) {
   284             SDL_HapticQuit();
   285         }
   286         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_HAPTIC);
   287     }
   288 #endif
   289 
   290 #if !SDL_AUDIO_DISABLED
   291     if ((flags & SDL_INIT_AUDIO)) {
   292         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_AUDIO)) {
   293             SDL_AudioQuit();
   294         }
   295         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_AUDIO);
   296     }
   297 #endif
   298 
   299 #if !SDL_VIDEO_DISABLED
   300     if ((flags & SDL_INIT_VIDEO)) {
   301         /* video implies events */
   302         flags |= SDL_INIT_EVENTS;
   303 
   304         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_VIDEO)) {
   305             SDL_VideoQuit();
   306         }
   307         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_VIDEO);
   308     }
   309 #endif
   310 
   311 #if !SDL_TIMERS_DISABLED
   312     if ((flags & SDL_INIT_TIMER)) {
   313         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_TIMER)) {
   314             SDL_TimerQuit();
   315         }
   316         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_TIMER);
   317     }
   318 #endif
   319 
   320 #if !SDL_EVENTS_DISABLED
   321     if ((flags & SDL_INIT_EVENTS)) {
   322         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_EVENTS)) {
   323             SDL_QuitQuit();
   324             SDL_StopEventLoop();
   325         }
   326         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_EVENTS);
   327     }
   328 #endif
   329 }
   330 
   331 Uint32
   332 SDL_WasInit(Uint32 flags)
   333 {
   334     int i;
   335     int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount);
   336     Uint32 initialized = 0;
   337 
   338     if (!flags) {
   339         flags = SDL_INIT_EVERYTHING;
   340     }
   341 
   342     num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1);
   343 
   344     /* Iterate over each bit in flags, and check the matching subsystem. */
   345     for (i = 0; i < num_subsystems; ++i) {
   346         if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) {
   347             initialized |= (1 << i);
   348         }
   349 
   350         flags >>= 1;
   351     }
   352 
   353     return initialized;
   354 }
   355 
   356 void
   357 SDL_Quit(void)
   358 {
   359     SDL_bInMainQuit = SDL_TRUE;
   360 
   361     /* Quit all subsystems */
   362 #if SDL_VIDEO_DRIVER_WINDOWS
   363     SDL_HelperWindowDestroy();
   364 #endif
   365     SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
   366 
   367     /* Uninstall any parachute signal handlers */
   368     SDL_UninstallParachute();
   369 
   370     SDL_ClearHints();
   371     SDL_AssertionsQuit();
   372     SDL_LogResetPriorities();
   373 
   374     /* Now that every subsystem has been quit, we reset the subsystem refcount
   375      * and the list of initialized subsystems.
   376      */
   377     SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
   378 
   379     SDL_bInMainQuit = SDL_FALSE;
   380 }
   381 
   382 /* Get the library version number */
   383 void
   384 SDL_GetVersion(SDL_version * ver)
   385 {
   386     SDL_VERSION(ver);
   387 }
   388 
   389 /* Get the library source revision */
   390 const char *
   391 SDL_GetRevision(void)
   392 {
   393     return SDL_REVISION;
   394 }
   395 
   396 /* Get the library source revision number */
   397 int
   398 SDL_GetRevisionNumber(void)
   399 {
   400     return SDL_REVISION_NUMBER;
   401 }
   402 
   403 /* Get the name of the platform */
   404 const char *
   405 SDL_GetPlatform()
   406 {
   407 #if __AIX__
   408     return "AIX";
   409 #elif __ANDROID__
   410     return "Android";
   411 #elif __BEOS__
   412     return "BeOS";
   413 #elif __BSDI__
   414     return "BSDI";
   415 #elif __DREAMCAST__
   416     return "Dreamcast";
   417 #elif __FREEBSD__
   418     return "FreeBSD";
   419 #elif __HAIKU__
   420     return "Haiku";
   421 #elif __HPUX__
   422     return "HP-UX";
   423 #elif __IRIX__
   424     return "Irix";
   425 #elif __LINUX__
   426     return "Linux";
   427 #elif __MINT__
   428     return "Atari MiNT";
   429 #elif __MACOS__
   430     return "MacOS Classic";
   431 #elif __MACOSX__
   432     return "Mac OS X";
   433 #elif __NETBSD__
   434     return "NetBSD";
   435 #elif __OPENBSD__
   436     return "OpenBSD";
   437 #elif __OS2__
   438     return "OS/2";
   439 #elif __OSF__
   440     return "OSF/1";
   441 #elif __QNXNTO__
   442     return "QNX Neutrino";
   443 #elif __RISCOS__
   444     return "RISC OS";
   445 #elif __SOLARIS__
   446     return "Solaris";
   447 #elif __WIN32__
   448     return "Windows";
   449 #elif __IPHONEOS__
   450     return "iPhone OS";
   451 #elif __PSP__
   452     return "PlayStation Portable";
   453 #else
   454     return "Unknown (see SDL_platform.h)";
   455 #endif
   456 }
   457 
   458 #if defined(__WIN32__)
   459 
   460 #if !defined(HAVE_LIBC) || (defined(__WATCOMC__) && defined(BUILD_DLL))
   461 /* Need to include DllMain() on Watcom C for some reason.. */
   462 #include "core/windows/SDL_windows.h"
   463 
   464 BOOL APIENTRY
   465 _DllMainCRTStartup(HANDLE hModule,
   466                    DWORD ul_reason_for_call, LPVOID lpReserved)
   467 {
   468     switch (ul_reason_for_call) {
   469     case DLL_PROCESS_ATTACH:
   470     case DLL_THREAD_ATTACH:
   471     case DLL_THREAD_DETACH:
   472     case DLL_PROCESS_DETACH:
   473         break;
   474     }
   475     return TRUE;
   476 }
   477 #endif /* building DLL with Watcom C */
   478 
   479 #endif /* __WIN32__ */
   480 
   481 /* vi: set sts=4 ts=4 sw=4 expandtab: */