From 7a45400695202fda9ad2731dcf682ed9980f7411 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 7 Jun 2009 06:06:35 +0000 Subject: [PATCH] Initial work on power subsystem for SDL 1.3. --- Makefile.dc | 1 + Makefile.ds | 2 + Makefile.in | 2 +- Makefile.minimal | 1 + Makefile.pandora | 2 +- configure.in | 35 ++++++ include/SDL.h | 1 + include/SDL_config.h.in | 9 ++ include/SDL_config_dreamcast.h | 2 + include/SDL_config_iphoneos.h | 3 + include/SDL_config_macosx.h | 3 + include/SDL_config_nintendods.h | 3 + include/SDL_config_os2.h | 3 + include/SDL_config_win32.h | 3 + include/SDL_power.h | 84 +++++++++++++ src/power/SDL_power.c | 110 ++++++++++++++++ src/power/linux/SDL_syspower.c | 207 +++++++++++++++++++++++++++++++ src/power/macosx/SDL_syspower.c | 193 ++++++++++++++++++++++++++++ src/power/nds/SDL_syspower.c | 45 +++++++ src/power/os2/SDL_syspower.c | 135 ++++++++++++++++++++ src/power/windows/SDL_syspower.c | 78 ++++++++++++ test/Makefile.in | 5 +- test/testpower.c | 65 ++++++++++ 23 files changed, 989 insertions(+), 3 deletions(-) create mode 100644 include/SDL_power.h create mode 100644 src/power/SDL_power.c create mode 100644 src/power/linux/SDL_syspower.c create mode 100644 src/power/macosx/SDL_syspower.c create mode 100644 src/power/nds/SDL_syspower.c create mode 100644 src/power/os2/SDL_syspower.c create mode 100644 src/power/windows/SDL_syspower.c create mode 100644 test/testpower.c diff --git a/Makefile.dc b/Makefile.dc index 5885abf6e..3af2f8359 100644 --- a/Makefile.dc +++ b/Makefile.dc @@ -31,6 +31,7 @@ SRCS = \ src/events/SDL_quit.c \ src/events/SDL_resize.c \ src/file/SDL_rwops.c \ + src/power/SDL_power.c \ src/joystick/dc/SDL_sysjoystick.c \ src/joystick/SDL_joystick.c \ src/loadso/dummy/SDL_sysloadso.c \ diff --git a/Makefile.ds b/Makefile.ds index 7ed0e178a..c44647ac9 100644 --- a/Makefile.ds +++ b/Makefile.ds @@ -55,6 +55,8 @@ src/events/SDL_mouse.c \ src/events/SDL_quit.c \ src/events/SDL_windowevents.c \ src/file/SDL_rwops.c \ +src/power/SDL_power.c \ +src/power/nds/SDL_syspower.c \ src/haptic/SDL_haptic.c \ src/haptic/nds/SDL_syshaptic.c \ src/joystick/nds/SDL_sysjoystick.c \ diff --git a/Makefile.in b/Makefile.in index 8f7e1bca4..1699fcae4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -42,7 +42,7 @@ SDLMAIN_OBJECTS = @SDLMAIN_OBJECTS@ DIST = acinclude.m4 autogen.sh Borland.html Borland.zip BUGS build-scripts configure configure.in COPYING CREDITS docs docs.html include INSTALL Makefile.dc Makefile.minimal Makefile.in README* sdl-config.in sdl.m4 sdl.pc.in SDL.qpg.in SDL.spec SDL.spec.in src test TODO VisualC.html VisualC VisualCE Watcom-OS2.zip Watcom-Win32.zip WhatsNew Xcode -HDRS = SDL.h SDL_audio.h SDL_cdrom.h SDL_compat.h SDL_cpuinfo.h SDL_endian.h SDL_error.h SDL_events.h SDL_haptic.h SDL_joystick.h SDL_keyboard.h SDL_keysym.h SDL_loadso.h SDL_main.h SDL_mouse.h SDL_mutex.h SDL_name.h SDL_opengl.h SDL_opengles.h SDL_pixels.h SDL_platform.h SDL_quit.h SDL_rect.h SDL_revision.h SDL_rwops.h SDL_scancode.h SDL_stdinc.h SDL_surface.h SDL_syswm.h SDL_thread.h SDL_timer.h SDL_types.h SDL_version.h SDL_video.h begin_code.h close_code.h +HDRS = SDL.h SDL_audio.h SDL_cdrom.h SDL_compat.h SDL_cpuinfo.h SDL_endian.h SDL_error.h SDL_events.h SDL_haptic.h SDL_joystick.h SDL_keyboard.h SDL_keysym.h SDL_loadso.h SDL_main.h SDL_mouse.h SDL_mutex.h SDL_name.h SDL_opengl.h SDL_opengles.h SDL_pixels.h SDL_platform.h SDL_power.h SDL_quit.h SDL_rect.h SDL_revision.h SDL_rwops.h SDL_scancode.h SDL_stdinc.h SDL_surface.h SDL_syswm.h SDL_thread.h SDL_timer.h SDL_types.h SDL_version.h SDL_video.h begin_code.h close_code.h LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ diff --git a/Makefile.minimal b/Makefile.minimal index c8057894a..6f000f97b 100644 --- a/Makefile.minimal +++ b/Makefile.minimal @@ -20,6 +20,7 @@ SOURCES = \ src/thread/*.c \ src/timer/*.c \ src/video/*.c \ + src/power/*.c \ src/audio/dummy/*.c \ src/video/dummy/*.c \ src/joystick/dummy/*.c \ diff --git a/Makefile.pandora b/Makefile.pandora index ed8e33e3c..bd7dca182 100644 --- a/Makefile.pandora +++ b/Makefile.pandora @@ -14,7 +14,7 @@ TARGET = libSDL.a SOURCES = ./src/*.c ./src/audio/*.c ./src/cdrom/*.c ./src/cpuinfo/*.c ./src/events/*.c \ ./src/file/*.c ./src/stdlib/*.c ./src/thread/*.c ./src/timer/*.c ./src/video/*.c \ - ./src/joystick/*.c ./src/haptic/*.c ./src/video/dummy/*.c ./src/audio/disk/*.c \ + ./src/joystick/*.c ./src/haptic/*.c ./src/power/*.c ./src/video/dummy/*.c ./src/audio/disk/*.c \ ./src/audio/dummy/*.c ./src/loadso/dlopen/*.c ./src/audio/dsp/*.c ./src/audio/dma/*.c \ ./src/thread/pthread/SDL_systhread.c ./src/thread/pthread/SDL_syssem.c \ ./src/thread/pthread/SDL_sysmutex.c ./src/thread/pthread/SDL_syscond.c \ diff --git a/configure.in b/configure.in index 4648823ec..86bbd8c9d 100644 --- a/configure.in +++ b/configure.in @@ -250,6 +250,14 @@ if test x$enable_haptic != xyes; then else SOURCES="$SOURCES $srcdir/src/haptic/*.c" fi +AC_ARG_ENABLE(power, +AC_HELP_STRING([--enable-power], [Enable the power subsystem [[default=yes]]]), + , enable_power=yes) +if test x$enable_power != xyes; then + AC_DEFINE(SDL_POWER_DISABLED) +else + SOURCES="$SOURCES $srcdir/src/power/*.c" +fi AC_ARG_ENABLE(cdrom, AC_HELP_STRING([--enable-cdrom], [Enable the cdrom subsystem [[default=yes]]]), , enable_cdrom=yes) @@ -2446,6 +2454,16 @@ case "$host" in esac fi fi + # Set up files for the power library + if test x$enable_power = xyes; then + case $ARCH in + linux) + AC_DEFINE(SDL_POWER_LINUX) + SOURCES="$SOURCES $srcdir/src/power/linux/*.c" + have_power=yes + ;; + esac + fi # Set up files for the cdrom library if test x$enable_cdrom = xyes; then case $ARCH in @@ -2620,6 +2638,12 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau SOURCES="$SOURCES $srcdir/src/loadso/win32/*.c" have_loadso=yes fi + # Set up files for the system power library + if test x$enable_power = xyes; then + AC_DEFINE(SDL_POWER_WINDOWS) + SOURCES="$SOURCES $srcdir/src/power/windows/*.c" + have_power=yes + fi # Set up the system libraries we need EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lcoredll -lcommctrl -lmmtimer" # The Win32 platform requires special setup @@ -2691,6 +2715,11 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau have_haptic=yes fi fi + if test x$enable_power = xyes; then + AC_DEFINE(SDL_POWER_WINDOWS) + SOURCES="$SOURCES $srcdir/src/power/windows/SDL_syspower.c" + have_power=yes + fi # Set up files for the cdrom library if test x$enable_cdrom = xyes; then AC_DEFINE(SDL_CDROM_WIN32) @@ -2842,6 +2871,12 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau have_haptic=yes EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,ForceFeedback" fi + # Set up files for the power library + if test x$enable_power = xyes; then + AC_DEFINE(SDL_POWER_MACOSX) + SOURCES="$SOURCES $srcdir/src/power/macosx/*.c" + have_power=yes + fi # Set up files for the cdrom library if test x$enable_cdrom = xyes; then AC_DEFINE(SDL_CDROM_MACOSX) diff --git a/include/SDL.h b/include/SDL.h index f1078304d..8182433c1 100644 --- a/include/SDL.h +++ b/include/SDL.h @@ -84,6 +84,7 @@ Enjoy! #include "SDL_events.h" #include "SDL_loadso.h" #include "SDL_mutex.h" +#include "SDL_power.h" #include "SDL_rwops.h" #include "SDL_thread.h" #include "SDL_timer.h" diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 68ac2809c..47d4738d0 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -166,6 +166,7 @@ #undef SDL_THREADS_DISABLED #undef SDL_TIMERS_DISABLED #undef SDL_VIDEO_DISABLED +#undef SDL_POWER_DISABLED /* Enable various audio drivers */ #undef SDL_AUDIO_DRIVER_ALSA @@ -324,6 +325,14 @@ #undef SDL_VIDEO_OPENGL_OSMESA #undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC +/* Enable system power support */ +#undef SDL_POWER_LINUX +#undef SDL_POWER_WINDOWS +#undef SDL_POWER_MACOSX +#undef SDL_POWER_OS2 +#undef SDL_POWER_NINTENDODS +#undef SDL_POWER_HARDWIRED + /* Enable assembly routines */ #undef SDL_ASSEMBLY_ROUTINES #undef SDL_ALTIVEC_BLITTERS diff --git a/include/SDL_config_dreamcast.h b/include/SDL_config_dreamcast.h index 5b8175c8a..f57c1eecf 100644 --- a/include/SDL_config_dreamcast.h +++ b/include/SDL_config_dreamcast.h @@ -104,4 +104,6 @@ typedef unsigned long uintptr_t; #define SDL_VIDEO_DRIVER_DC 1 #define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_POWER_HARDWIRED 1 + #endif /* _SDL_config_dreamcast_h */ diff --git a/include/SDL_config_iphoneos.h b/include/SDL_config_iphoneos.h index 82d6731f1..815c47510 100644 --- a/include/SDL_config_iphoneos.h +++ b/include/SDL_config_iphoneos.h @@ -131,6 +131,9 @@ typedef unsigned long uintptr_t; #define SDL_VIDEO_OPENGL_ES 1 #define SDL_VIDEO_RENDER_OGL_ES 1 +/* Enable system power support */ +#define SDL_POWER_MACOSX 1 + /* enable iPhone keyboard support */ #define SDL_IPHONE_KEYBOARD 1 diff --git a/include/SDL_config_macosx.h b/include/SDL_config_macosx.h index 1a4351652..1b284ebe9 100644 --- a/include/SDL_config_macosx.h +++ b/include/SDL_config_macosx.h @@ -137,6 +137,9 @@ #define SDL_VIDEO_OPENGL_CGL 1 #define SDL_VIDEO_RENDER_OGL 1 +/* Enable system power support */ +#define SDL_POWER_MACOSX 1 + /* Enable assembly routines */ #define SDL_ASSEMBLY_ROUTINES 1 #ifdef __ppc__ diff --git a/include/SDL_config_nintendods.h b/include/SDL_config_nintendods.h index 043ad08ef..d1a5d765b 100644 --- a/include/SDL_config_nintendods.h +++ b/include/SDL_config_nintendods.h @@ -116,4 +116,7 @@ typedef unsigned __PTRDIFF_TYPE__ uintptr_t; #define SDL_VIDEO_DRIVER_NDS 1 /*#define SDL_VIDEO_DRIVER_DUMMY 1 TODO: uncomment this later*/ +/* Enable system power support */ +#define SDL_POWER_NINTENDODS 1 + #endif /* _SDL_config_nintendods_h */ diff --git a/include/SDL_config_os2.h b/include/SDL_config_os2.h index b80c85a13..d6c118bca 100644 --- a/include/SDL_config_os2.h +++ b/include/SDL_config_os2.h @@ -136,6 +136,9 @@ typedef unsigned long long uint64_t; /* Enable OpenGL support */ /* Nothing here yet for OS/2... :( */ +/* Enable system power support */ +#define SDL_POWER_OS2 1 + /* Enable assembly routines where available */ #define SDL_ASSEMBLY_ROUTINES 1 diff --git a/include/SDL_config_win32.h b/include/SDL_config_win32.h index 9d0da4dcd..86b771ce1 100644 --- a/include/SDL_config_win32.h +++ b/include/SDL_config_win32.h @@ -185,6 +185,9 @@ typedef unsigned int uintptr_t; #define SDL_VIDEO_RENDER_OGL 1 #endif +/* Enable system power support */ +#define SDL_POWER_WINDOWS 1 + /* Enable assembly routines (Win64 doesn't have inline asm) */ #ifndef _WIN64 #define SDL_ASSEMBLY_ROUTINES 1 diff --git a/include/SDL_power.h b/include/SDL_power.h new file mode 100644 index 000000000..a2ac3aa71 --- /dev/null +++ b/include/SDL_power.h @@ -0,0 +1,84 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef _SDL_power_h +#define _SDL_power_h + +/** + * \file SDL_power.h + * + * Header for the SDL power management routines + */ + +#include "SDL_stdinc.h" + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** + * \enum SDL_PowerState + * + * \brief The basic state for the system's power supply. + */ +typedef enum +{ + SDL_POWERSTATE_UNKNOWN, /**< cannot determine power status */ + SDL_POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */ + SDL_POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */ + SDL_POWERSTATE_CHARGING, /**< Plugged in, charging battery */ + SDL_POWERSTATE_CHARGED, /**< Plugged in, battery charged */ +} SDL_PowerState; + + +/** + * \fn int SDL_GetPowerInfo(void) + * + * \brief Get the current power supply details. + * + * \param secs Seconds of battery life left. You can pass a NULL here if + * you don't care. Will return -1 if we can't determine a + * value, or we're not running on a battery. + * + * \param pct Percentage of battery life left, between 0 and 100. You can + * pass a NULL here if you don't care. Will return -1 if we + * can't determine a value, or we're not running on a battery. + * + * \return The state of the battery (if any). + */ +extern DECLSPEC SDL_PowerState SDLCALL SDL_GetPowerInfo(int *secs, int *pct); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#include "close_code.h" + +#endif /* _SDL_power_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/power/SDL_power.c b/src/power/SDL_power.c new file mode 100644 index 000000000..356e2391a --- /dev/null +++ b/src/power/SDL_power.c @@ -0,0 +1,110 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" +#include "SDL_power.h" + +/* + * Returns SDL_TRUE if we have a definitive answer. + * SDL_FALSE to try next implementation. + */ +typedef SDL_bool +(*SDL_GetPowerInfo_Impl)(SDL_PowerState *state, int *seconds, int *percent); + +SDL_bool SDL_GetPowerInfo_Linux_sys_power(SDL_PowerState*, int*, int*); +SDL_bool SDL_GetPowerInfo_Linux_proc_apci(SDL_PowerState*, int*, int*); +SDL_bool SDL_GetPowerInfo_Linux_proc_apm(SDL_PowerState*, int*, int*); +SDL_bool SDL_GetPowerInfo_Windows(SDL_PowerState*, int*, int*); +SDL_bool SDL_GetPowerInfo_MacOSX(SDL_PowerState*, int*, int*); +SDL_bool SDL_GetPowerInfo_OS2(SDL_PowerState*, int*, int*); +SDL_bool SDL_GetPowerInfo_NintendoDS(SDL_PowerState*, int*, int*); + +#ifndef SDL_POWER_DISABLED +#ifdef SDL_POWER_HARDWIRED +/* This is for things that _never_ have a battery, like the Dreamcast, etc. */ +static SDL_bool +SDL_GetPowerInfo_Hardwired(SDL_PowerState *state, int *seconds, int *percent) +{ + *seconds = -1; + *percent = -1; + *state = SDL_POWERSTATE_NO_BATTERY; + return SDL_TRUE; +} +#endif +#endif + + +static SDL_GetPowerInfo_Impl implementations[] = { +#ifndef SDL_POWER_DISABLED +#ifdef SDL_POWER_LINUX /* in order of preference. More than could work. */ + SDL_GetPowerInfo_Linux_sys_power, + SDL_GetPowerInfo_Linux_proc_apci, + SDL_GetPowerInfo_Linux_proc_apm, +#endif +#ifdef SDL_POWER_WINDOWS /* handles Win32, Win64, PocketPC. */ + SDL_GetPowerInfo_Windows, +#endif +#ifdef SDL_POWER_MACOSX /* handles Mac OS X, Darwin, iPhone. */ + SDL_GetPowerInfo_MacOSX, +#endif +#ifdef SDL_POWER_OS2 /* handles OS/2, Warp, eComStation. */ + SDL_GetPowerInfo_OS2, +#endif +#ifdef SDL_POWER_NINTENDODS /* handles Nintendo DS. */ + SDL_GetPowerInfo_NintendoDS, +#endif +#ifdef SDL_POWER_HARDWIRED + SDL_GetPowerInfo_Hardwired, +#endif +#endif +}; + +SDL_PowerState +SDL_GetPowerInfo(int *seconds, int *percent) +{ + const int total = sizeof (implementations) / sizeof (implementations[0]); + int _seconds, _percent; + SDL_PowerState retval; + int i; + + /* Make these never NULL for platform-specific implementations. */ + if (seconds == NULL) { + seconds = &_seconds; + } + + if (percent == NULL) { + percent = &_percent; + } + + for (i = 0; i < total; i++) { + if (implementations[i](&retval, seconds, percent)) { + return retval; + } + } + + /* nothing was definitive. */ + *seconds = -1; + *percent = -1; + return SDL_POWERSTATE_UNKNOWN; +} + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/power/linux/SDL_syspower.c b/src/power/linux/SDL_syspower.c new file mode 100644 index 000000000..1852e9436 --- /dev/null +++ b/src/power/linux/SDL_syspower.c @@ -0,0 +1,207 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef SDL_POWER_DISABLED +#ifdef SDL_POWER_LINUX + +#include +#include + +#include "SDL_power.h" + +SDL_bool +SDL_GetPowerInfo_Linux_sys_power(SDL_PowerState *state, + int *seconds, int *percent) +{ + return SDL_FALSE; /* !!! FIXME: write me. */ +#if 0 + const int fd = open("/sys/power", O_RDONLY); + if (fd == -1) { + return SDL_FALSE; /* can't use this interface. */ + } + return SDL_TRUE; +#endif +} + +SDL_bool +SDL_GetPowerInfo_Linux_sys_proc_acpi(SDL_PowerState *state, + int *seconds, int *percent) +{ + return SDL_FALSE; /* !!! FIXME: write me. */ +#if 0 + const int fd = open("/proc/acpi", O_RDONLY); + if (fd == -1) { + return SDL_FALSE; /* can't use this interface. */ + } + return SDL_TRUE; +#endif +} + +static SDL_bool +next_string(char **_ptr, char **_str) +{ + char *ptr = *_ptr; + char *str = *_str; + + while (*ptr == ' ') { /* skip any spaces... */ + ptr++; + } + + if (*ptr == '\0') { + return SDL_FALSE; + } + + str = ptr; + while ((*ptr != ' ') && (*ptr != '\0')) + ptr++; + + if (*ptr != '\0') + *(ptr++) = '\0'; + + *_str = str; + *_ptr = ptr; + return SDL_TRUE; +} + +static SDL_bool +int_string(char *str, int *val) +{ + char *endptr = NULL; + *val = (int) strtol(str+2, &endptr, 16); + return ((*str != '\0') && (*endptr == '\0')); +} + +/* http://lxr.linux.no/linux+v2.6.29/drivers/char/apm-emulation.c */ +SDL_bool +SDL_GetPowerInfo_Linux_sys_proc_apm(SDL_PowerState *state, + int *seconds, int *percent) +{ + SDL_bool need_details = SDL_FALSE; + int ac_status = 0; + int battery_status = 0; + int battery_flag = 0; + int battery_percent = 0; + int battery_time = 0; + const int fd = open("/proc/apm", O_RDONLY); + char buf[128]; + char *ptr = &buf[0]; + char *str = NULL; + ssize_t br; + + if (fd == -1) { + return SDL_FALSE; /* can't use this interface. */ + } + + br = read(fd, buf, sizeof (buf) - 1); + close(fd); + + if (br < 0) { + return SDL_FALSE; + } + + buf[br] = '\0'; // null-terminate the string. + if (!next_string(&ptr, &str)) { /* driver version */ + return SDL_FALSE; + } + if (!next_string(&ptr, &str)) { /* BIOS version */ + return SDL_FALSE; + } + if (!next_string(&ptr, &str)) { /* APM flags */ + return SDL_FALSE; + } + + if (!next_string(&ptr, &str)) { /* AC line status */ + return SDL_FALSE; + } else if (!int_string(str, &ac_status)) { + return SDL_FALSE; + } + + if (!next_string(&ptr, &str)) { /* battery status */ + return SDL_FALSE; + } else if (!int_string(str, &battery_status)) { + return SDL_FALSE; + } + if (!next_string(&ptr, &str)) { /* battery flag */ + return SDL_FALSE; + } else if (!int_string(str, &battery_flag)) { + return SDL_FALSE; + } + if (!next_string(&ptr, &str)) { /* remaining battery life percent */ + return SDL_FALSE; + } + if (str[strlen(str) - 1] == '%') { + str[strlen(str) - 1] = '\0'; + } + if (!int_string(str, &battery_percent)) { + return SDL_FALSE; + } + + if (!next_string(&ptr, &str)) { /* remaining battery life time */ + return SDL_FALSE; + } else if (!int_string(str, &battery_time)) { + return SDL_FALSE; + } + + if (!next_string(&ptr, &str)) { /* remaining battery life time units */ + return SDL_FALSE; + } else if (strcmp(str, "min") == 0) { + battery_time *= 60; + } + + if (battery_flag == 0xFF) { /* unknown state */ + *state = SDL_POWERSTATE_UNKNOWN; + } else if (battery_flag & (1 << 7)) { /* no battery */ + *state = SDL_POWERSTATE_NO_BATTERY; + } else if (battery_flag & (1 << 3)) { /* charging */ + *state = SDL_POWERSTATE_CHARGING; + need_details = SDL_TRUE; + } else if (ac_status == 1) { + *state = SDL_POWERSTATE_CHARGED; /* on AC, not charging. */ + need_details = SDL_TRUE; + } else { + *state = SDL_POWERSTATE_ON_BATTERY; + need_details = SDL_TRUE; + } + + *percent = -1; + *seconds = -1; + if (need_details) { + const int pct = battery_percent; + const int secs = battery_time; + + if (pct >= 0) { /* -1 == unknown */ + *percent = (pct > 100) ? 100 : pct; /* clamp between 0%, 100% */ + } + if (secs >= 0) { /* -1 == unknown */ + *seconds = secs; + } + } + + return SDL_TRUE; +} + +#endif /* SDL_POWER_LINUX */ +#endif /* SDL_POWER_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/power/macosx/SDL_syspower.c b/src/power/macosx/SDL_syspower.c new file mode 100644 index 000000000..a9ea48187 --- /dev/null +++ b/src/power/macosx/SDL_syspower.c @@ -0,0 +1,193 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef SDL_POWER_DISABLED +#ifdef SDL_POWER_MACOSX + +#include +#include +#include + +#include "SDL_power.h" + +/* Carbon is so verbose... */ +#define STRMATCH(a,b) (CFStringCompare(a, b, 0) == kCFCompareEqualTo) +#define GETVAL(k,v) \ + CFDictionaryGetValueIfPresent(dict, CFSTR(k), (const void **) v) + +/* Note that AC power sources also include a laptop battery it is charging. */ +static void +checkps(CFDictionaryRef dict, SDL_bool *have_ac, SDL_bool *have_battery, + SDL_bool *charging, int *seconds, int *percent) +{ + CFStringRef strval; /* don't CFRelease() this. */ + CFBooleanRef bval; + CFNumberRef numval; + SDL_bool charge = SDL_FALSE; + SDL_bool choose = SDL_FALSE; + SDL_bool is_ac = SDL_FALSE; + int secs = -1; + int maxpct = -1; + int pct = -1; + + if ((GETVAL(kIOPSIsPresentKey, &bval)) && (bval == kCFBooleanFalse)) { + return; /* nothing to see here. */ + } + + if (!GETVAL(kIOPSPowerSourceStateKey, &strval)) { + return; + } + + if (STRMATCH(strval, CFSTR(kIOPSACPowerValue))) { + is_ac = *have_ac = SDL_TRUE; + } else if (!STRMATCH(strval, CFSTR(kIOPSBatteryPowerValue))) { + return; /* not a battery? */ + } + + if ((GETVAL(kIOPSIsChargingKey, &bval)) && (bval == kCFBooleanTrue)) { + charge = SDL_TRUE; + } + + if (GETVAL(kIOPSMaxCapacityKey, &numval)) { + SInt32 val = -1; + CFNumberGetValue(numval, kCFNumberSInt32Type, &val); + if (val > 0) { + *have_battery = SDL_TRUE; + maxpct = (int) val; + } + } + + if (GETVAL(kIOPSMaxCapacityKey, &numval)) { + SInt32 val = -1; + CFNumberGetValue(numval, kCFNumberSInt32Type, &val); + if (val > 0) { + *have_battery = SDL_TRUE; + maxpct = (int) val; + } + } + + if (GETVAL(kIOPSTimeToEmptyKey, &numval)) { + SInt32 val = -1; + CFNumberGetValue(numval, kCFNumberSInt32Type, &val); + + /* Mac OS X reports 0 minutes until empty if you're plugged in. :( */ + if ((val == 0) && (is_ac)) { + val = -1; /* !!! FIXME: calc from timeToFull and capacity? */ + } + + secs = (int) val; + if (secs > 0) { + secs *= 60; /* value is in minutes, so convert to seconds. */ + } + } + + if (GETVAL(kIOPSCurrentCapacityKey, &numval)) { + SInt32 val = -1; + CFNumberGetValue(numval, kCFNumberSInt32Type, &val); + pct = (int) val; + } + + if ((pct > 0) && (maxpct > 0)) { + pct = (int) ((((double)pct)/((double)maxpct)) * 100.0); + } + + if (pct > 100) { + pct = 100; + } + + /* + * We pick the battery that claims to have the most minutes left. + * (failing a report of minutes, we'll take the highest percent.) + */ + if ((secs < 0) && (*seconds < 0)) { + if ((pct < 0) && (*percent < 0)) { + choose = SDL_TRUE; /* at least we know there's a battery. */ + } + if (pct > *percent) { + choose = SDL_TRUE; + } + } else if (secs > *seconds) { + choose = SDL_TRUE; + } + + if (choose) { + *seconds = secs; + *percent = pct; + *charging = charge; + } +} + +#undef GETVAL +#undef STRMATCH + + +SDL_bool +SDL_GetPowerInfo_MacOSX(SDL_PowerState *state, int *seconds, int *percent) +{ + CFTypeRef blob = IOPSCopyPowerSourcesInfo(); + + *seconds = -1; + *percent = -1; + *state = SDL_POWERSTATE_UNKNOWN; + + if (blob != NULL) { + CFArrayRef list = IOPSCopyPowerSourcesList(blob); + if (list != NULL) { + /* don't CFRelease() the list items, or dictionaries! */ + SDL_bool have_ac = SDL_FALSE; + SDL_bool have_battery = SDL_FALSE; + SDL_bool charging = SDL_FALSE; + const CFIndex total = CFArrayGetCount(list); + CFIndex i; + for (i = 0; i < total; i++) { + CFTypeRef ps = (CFTypeRef) CFArrayGetValueAtIndex(list, i); + CFDictionaryRef dict = IOPSGetPowerSourceDescription(blob, ps); + if (dict != NULL) { + checkps(dict, &have_ac, &have_battery, &charging, + seconds, percent); + } + } + + if (!have_battery) { + *state = SDL_POWERSTATE_NO_BATTERY; + } else if (charging) { + *state = SDL_POWERSTATE_CHARGING; + } else if (have_ac) { + *state = SDL_POWERSTATE_CHARGED; + } else { + *state = SDL_POWERSTATE_ON_BATTERY; + } + + CFRelease(list); + } + CFRelease(blob); + } + + return SDL_TRUE; /* always the definitive answer on Mac OS X. */ +} + +#endif /* SDL_POWER_MACOSX */ +#endif /* SDL_POWER_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/power/nds/SDL_syspower.c b/src/power/nds/SDL_syspower.c new file mode 100644 index 000000000..87b53a35b --- /dev/null +++ b/src/power/nds/SDL_syspower.c @@ -0,0 +1,45 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef SDL_POWER_DISABLED +#ifdef SDL_POWER_NINTENDODS + +#include "SDL_power.h" + +SDL_bool +SDL_GetPowerInfo_NintendoDS(SDL_PowerState *state, int *seconds, int *percent) +{ + /* !!! FIXME: write me. */ + + *state = SDL_POWERSTATE_UNKNOWN; + *percent = -1; + *seconds = -1; + + return SDL_TRUE; /* always the definitive answer on Nintendo DS. */ +} + +#endif /* SDL_POWER_NINTENDODS */ +#endif /* SDL_POWER_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/power/os2/SDL_syspower.c b/src/power/os2/SDL_syspower.c new file mode 100644 index 000000000..cc19ed138 --- /dev/null +++ b/src/power/os2/SDL_syspower.c @@ -0,0 +1,135 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* !!! FIXME: + * Please note that this code has not been tested (or even compiled!). It + * should, in theory, run on any version of OS/2, and work with any system + * that has APM.SYS loaded. I don't know if ACPI.SYS works. + */ + +#ifndef SDL_POWER_DISABLED +#ifdef SDL_POWER_OS2 + +#define INCL_DOSFILEMGR +#define INCL_DOSDEVICES +#define INCL_DOSDEVIOCTL +#define INCL_DOSERRORS +#include + +#include "SDL_power.h" + +typedef struct { + USHORT len; + USHORT flags; + UCHAR ac_status; + UCHAR battery_status; + UCHAR battery_life; + UCHAR battery_time_form; + USHORT battery_time; + UCHAR battery_flags; +} PowerStatus; +extern int CompilerAssertPowerStatus[(sizeof (PowerStatus) == 10) ? 1 : -1]; + + +SDL_bool +SDL_GetPowerInfo_OS2(SDL_PowerState *state, int *seconds, int *percent) +{ + PowerStatus status; + HFILE hfile = 0; + ULONG action = 0; + APIRET rc = 0; + + *state = SDL_POWERSTATE_UNKNOWN; + *percent = -1; + *seconds = -1; + + /* open the power management device */ + rc = DosOpen("APM$", &hfile, &action, 0, FILE_NORMAL, FILE_OPEN, + OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0); + + if (rc == NO_ERROR) { + USHORT iorc = 0; + ULONG iorclen = sizeof (iorc); + ULONG statuslen = sizeof (status); + + SDL_memset(&status, '\0', sizeof (status)); + status.len = sizeof (status); + + rc = DosDevIOCtl(hfile, IOCTL_POWER, POWER_GETPOWERSTATUS, &status, + statuslen, &statuslen, &iorc, iorclen, &iorclen); + DosClose(hfile); + + /* (status.flags & 0x1) == power subsystem enabled. */ + if ((rc == NO_ERROR) && (status.flags & 0x1)) { + if (statuslen == 7) { /* older OS/2 APM driver? Less fields. */ + status.battery_time_form = 0xFF; + status.battery_time = 0; + if (status.battery_status == 0xFF) { + status.battery_flags = 0xFF; + } else { + status.battery_flags = (1 << status.battery_status); + } + } + + if (status.battery_flags == 0xFF) { /* unknown state */ + *state = SDL_POWERSTATE_UNKNOWN; + } else if (status.battery_flags & (1 << 7)) { /* no battery */ + *state = SDL_POWERSTATE_NO_BATTERY; + } else if (status.battery_flags & (1 << 3)) { /* charging */ + *state = SDL_POWERSTATE_CHARGING; + need_details = SDL_TRUE; + } else if (status.ac_status == 1) { + *state = SDL_POWERSTATE_CHARGED; /* on AC, not charging. */ + need_details = SDL_TRUE; + } else { + *state = SDL_POWERSTATE_ON_BATTERY; /* not on AC. */ + need_details = SDL_TRUE; + } + + if (need_details) { + const int pct = (int) status.battery_life; + const int secs = (int) status.battery_time; + + if (pct != 0xFF) { /* 255 == unknown */ + *percent = (pct > 100) ? 100 : pct; + } + + if (status.battery_time_form == 0xFF) { /* unknown */ + *seconds = -1; + } else if (status.battery_time_form == 1) { /* minutes */ + *seconds = secs * 60; + } else { + *seconds = secs; + } + } + } + } + + return SDL_TRUE; /* always the definitive answer on OS/2. */ +} + +#endif /* SDL_POWER_OS2 */ +#endif /* SDL_POWER_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/power/windows/SDL_syspower.c b/src/power/windows/SDL_syspower.c new file mode 100644 index 000000000..99057e868 --- /dev/null +++ b/src/power/windows/SDL_syspower.c @@ -0,0 +1,78 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef SDL_POWER_DISABLED +#ifdef SDL_POWER_WINDOWS + +#define WIN32_LEAN_AND_MEAN +#include + +#include "SDL_power.h" + +SDL_bool +SDL_GetPowerInfo_Windows(SDL_PowerState *state, int *seconds, int *percent) +{ + SYSTEM_POWER_STATUS status; + SDL_bool need_details = SDL_FALSE; + + /* This API should exist back to Win95 and Windows CE. */ + if (!GetSystemPowerStatus(&status)) { + /* !!! FIXME: push GetLastError() into SDL_GetError() */ + *state = SDL_POWERSTATE_UNKNOWN; + } else if (status.BatteryFlag == 0xFF) { /* unknown state */ + *state = SDL_POWERSTATE_UNKNOWN; + } else if (status.BatteryFlag & (1 << 7)) { /* no battery */ + *state = SDL_POWERSTATE_NO_BATTERY; + } else if (status.BatteryFlag & (1 << 3)) { /* charging */ + *state = SDL_POWERSTATE_CHARGING; + need_details = SDL_TRUE; + } else if (status.ACLineStatus == 1) { + *state = SDL_POWERSTATE_CHARGED; /* on AC, not charging. */ + need_details = SDL_TRUE; + } else { + *state = SDL_POWERSTATE_ON_BATTERY; /* not on AC. */ + need_details = SDL_TRUE; + } + + *percent = -1; + *seconds = -1; + if (need_details) { + const int pct = (int) status.BatteryLifePercent; + const int secs = (int) status.BatteryLifeTime; + + if (pct != 255) { /* 255 == unknown */ + *percent = (pct > 100) ? 100 : pct; /* clamp between 0%, 100% */ + } + if (secs != 0xFFFFFFFF) { /* ((DWORD)-1) == unknown */ + *seconds = secs; + } + } + + return SDL_TRUE; /* always the definitive answer on Windows. */ +} + +#endif /* SDL_POWER_WINDOWS */ +#endif /* SDL_POWER_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/test/Makefile.in b/test/Makefile.in index 7ba98c190..c3b8ff953 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -7,7 +7,7 @@ EXE = @EXE@ CFLAGS = @CFLAGS@ LIBS = @LIBS@ -TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testresample$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testintersections$(EXE) testdraw2$(EXE) testdyngl$(EXE) testdyngles$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testgles$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE) +TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testresample$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testpower$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testintersections$(EXE) testdraw2$(EXE) testdyngl$(EXE) testdyngles$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testgles$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE) all: Makefile $(TARGETS) @@ -32,6 +32,9 @@ testaudioinfo$(EXE): $(srcdir)/testaudioinfo.c testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c $(CC) -o $@ $? $(CFLAGS) $(LIBS) +testpower$(EXE): $(srcdir)/testpower.c + $(CC) -o $@ $? $(CFLAGS) $(LIBS) + testalpha$(EXE): $(srcdir)/testalpha.c $(CC) -o $@ $? $(CFLAGS) $(LIBS) @MATHLIB@ diff --git a/test/testpower.c b/test/testpower.c new file mode 100644 index 000000000..5abb016fe --- /dev/null +++ b/test/testpower.c @@ -0,0 +1,65 @@ +/* Simple test of power subsystem. */ + +#include +#include "SDL.h" + +static void report_power(void) +{ + int seconds, percent; + const SDL_PowerState state = SDL_GetPowerInfo(&seconds, &percent); + char *statestr = NULL; + + printf("SDL-reported power info...\n"); + switch(state) + { + case SDL_POWERSTATE_UNKNOWN: + statestr = "Unknown"; + break; + case SDL_POWERSTATE_ON_BATTERY: + statestr = "On battery"; + break; + case SDL_POWERSTATE_NO_BATTERY: + statestr = "No battery"; + break; + case SDL_POWERSTATE_CHARGING: + statestr = "Charging"; + break; + case SDL_POWERSTATE_CHARGED: + statestr = "Charged"; + break; + default: + statestr = "!!API ERROR!!"; + break; + } + + printf("State: %s\n", statestr); + + if (percent == -1) { + printf("Percent left: unknown\n"); + } else { + printf("Percent left: %d%%\n", percent); + } + + if (seconds == -1) { + printf("Time left: unknown\n"); + } else { + printf("Time left: %d minutes, %d seconds\n", (int) (seconds / 60), (int) (seconds % 60)); + } +} + + +int main(int argc, char *argv[]) +{ + if (SDL_Init(SDL_INIT_VIDEO) == -1) { + fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError()); + return 1; + } + + report_power(); + + SDL_Quit(); + return 0; +} + +/* end of testpower.c ... */ +