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