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