├── .gitattributes ├── .gitignore ├── README.md ├── devhelp ├── README.md ├── appinfo.json ├── build.all.sh ├── build.sh ├── ide │ └── codeblocks │ │ ├── PLocalSim.cbp │ │ └── build.all.sh ├── openShell.bat ├── run.sh └── src │ └── sampleProject.c ├── include └── pls_unwarn_unsupported_functions.h ├── install.sh ├── openShell.bat ├── scripts ├── build.library.sh ├── build.resCompiler.sh └── envvars.sh ├── sdkdata ├── common │ ├── build.local.sh │ └── run.local.sh ├── standalone │ ├── PLocalSim │ │ └── projectTemplate │ │ │ ├── appinfo.json │ │ │ └── src │ │ │ └── sampleProject.c │ └── create.project.sh ├── unix │ └── PLocalSim │ │ ├── appjs_header.js │ │ └── envvars.sh └── windows │ ├── PLocalSim │ └── envvars.sh │ └── openShell.bat ├── simdata ├── common │ ├── LICENSE.freetype.txt │ ├── LICENSE.png.txt │ ├── LICENSE.zlib.txt │ ├── images │ │ ├── backlight.png │ │ ├── body.png │ │ ├── screenshadow.png │ │ ├── scrollshadow.png │ │ ├── statusbar.png │ │ └── vibe.png │ └── systemFonts │ │ ├── Google Android License.txt │ │ ├── bitham-black.ttf │ │ ├── bitham-bold.ttf │ │ ├── bitham-light-subset.ttf │ │ ├── bitham-light.ttf │ │ ├── bitham-medium-numbers.ttf │ │ ├── droid-serif-bold.ttf │ │ ├── gothic-bold.ttf │ │ ├── gothic.ttf │ │ ├── roboto-bold.ttf │ │ └── roboto-condensed.ttf ├── unix │ ├── XMLHttpRequest.js │ └── server.js └── windows │ ├── SDL2.dll │ ├── SDL2_image.dll │ ├── SDL2_ttf.dll │ ├── libfreetype-6.dll │ ├── libpng16-16.dll │ └── zlib1.dll └── src ├── SDL_gfx ├── SDL_gfxBlitFunc.c ├── SDL_gfxBlitFunc.h ├── SDL_gfxPrimitives.c ├── SDL_gfxPrimitives.h ├── SDL_gfxPrimitives_font.h ├── SDL_rotozoom.c ├── SDL_rotozoom.h └── disclaimer.txt ├── additional └── strftime.c ├── js_server ├── lib │ ├── XMLHttpRequest.js │ └── localStorage.js └── server.js ├── jsmn ├── jsmn.c └── jsmn.h ├── local ├── accel_tap.c ├── actionbar.c ├── animation.c ├── app_message.c ├── app_sync.c ├── battery.c ├── bitmap.c ├── bluetooth.c ├── buttons.c ├── dictionary.c ├── draw.c ├── dummy │ └── src │ │ └── resource_ids.auto.h ├── font.c ├── globals.h ├── hardwareOutput.c ├── impl_pebble.h ├── layer.c ├── main.c ├── math.c ├── pebble_os.c ├── persistent_storage.c ├── render.c ├── scrolllayer.c ├── simdata.c ├── timer.c ├── watchinfo.c └── window.c └── resourceCompiler ├── main.c └── resCompiler.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | sdkdata/windows/PLocalSim/MinGW/ 2 | sdkdata/windows/PLocalSim/SDL2/ 3 | devhelp/build/ 4 | test/ 5 | testsdk/ 6 | obj/ 7 | bin/ 8 | backups/ 9 | include/pebble* 10 | *~ 11 | *.zip 12 | *.layout -------------------------------------------------------------------------------- /devhelp/README.md: -------------------------------------------------------------------------------- 1 | # Developer Helper 2 | 3 | ## Overview 4 | This is a small tool to make the development of the library easier. It essentially is a small stand-alone SDK that is ready-to-work-with when you could install a SDK (means all compilers and libraries are there). Also there are few optimizations (especially the library compilation caching) to speed up the work with this tool instead of rebuilding and reinstalling an entire SDK for one development iteration. 5 | As this is not intended to be used externally, please don't try to use it other as intended (for example from another folder than devhelp/ ), doing otherwise could have undefined behaviour. 6 | 7 | ## Usage 8 | This tool only works if a call to install.sh would also work (compiler and libraries are installed). If it does you navigate with a shell to the `devhelp` folder (for Windows you can just open `openShell.bat`). Then you can use: 9 | 10 | * `build.sh` - for building just the example project located in the `devhelp` folder 11 | * `build.all.sh` - for building the library, the resource compiler (c version) and the example projec 12 | * `build.all.sh --rebuild` - to delete the cache and make sure that everything will be compiled from the ground up 13 | * `run.sh` - for starting the built project 14 | * `run.sh --debug` - for starting the project within gdb 15 | -------------------------------------------------------------------------------- /devhelp/appinfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "uuid": "79a0f865-22da-415d-9764-6012a07a1bd6", 3 | "shortName": "sampleProject", 4 | "longName": "sampleProject", 5 | "companyName": "MakeAwesomeHappen", 6 | "versionCode": 1, 7 | "versionLabel": "1.0.0", 8 | "watchapp": { 9 | "watchface": false 10 | }, 11 | "appKeys": { 12 | "dummy": 0 13 | }, 14 | "resources": { 15 | "media": [] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /devhelp/build.all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # As this environment is basically a small standalone sdk, we have to use the c resource compiler 4 | 5 | # Disable unicode (should speed up everything) 6 | LC_ALL_BACKUP=$LC_ALL 7 | export LC_ALL=C 8 | 9 | # Prepare cache 10 | if [ "$1" == "--rebuild" ]; then 11 | echo "[INFO] Remove library cache" 12 | rm -f ./build/tempLocal/libCache/* 13 | else 14 | mkdir -p ./build/tempLocal/libCache 15 | fi 16 | 17 | # Building 18 | cd .. 19 | echo "[INFO] Building libray" 20 | if ./scripts/build.library.sh --debug ./devhelp/build/tempLocal/libCache ; then 21 | echo "[INFO] Building resource compiler" 22 | if ./scripts/build.resCompiler.sh -c --debug ; then 23 | cd devhelp 24 | echo "[INFO] Building project" 25 | if ./build.sh ; then # no --debug needed 26 | echo "[INFO] Everything built" 27 | else 28 | echo "[FAIL] Project compilation failed" 29 | fi 30 | else 31 | echo "[FAIL] Resource compiler compilation failed" 32 | fi 33 | else 34 | echo "[FAIL] Library compilation failed" 35 | fi 36 | 37 | # Reenable unicode 38 | export LC_ALL=$LC_ALL_BACKUP 39 | -------------------------------------------------------------------------------- /devhelp/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This is basically a hacked build.local.sh 4 | # don't expect anything fancy in here 5 | 6 | # Load (and fix) envvars 7 | if [ ! -e '../scripts/envvars.sh' ] ; then 8 | echo "[FAIL] Could not load envvars.sh" 9 | exit 1 10 | fi 11 | PLS_ENV_PREFIX='.' 12 | source '../scripts/envvars.sh' 13 | 14 | # Check for gcc 15 | if hash $PLS_GCC 2>/dev/null; then 16 | : # no-op 17 | else 18 | echo "[FAIL] Could not find required program gcc" 19 | exit 1 20 | fi 21 | 22 | # Check if we are in a project 23 | while [ ! -e "appinfo.json" ] 24 | do 25 | if [ `pwd` == '/' ] 26 | then 27 | echo "[FAIL] Could not find 'appinfo.json' in this directory or any parent" 1>&2 28 | exit 1 29 | fi 30 | cd .. 31 | done 32 | 33 | # Copy resources and app info 34 | PLS_OS_NAME='unix' 35 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 36 | PLS_OS_NAME='windows' 37 | fi 38 | 39 | mkdir -p ./build/local/ 40 | cp -u ./appinfo.json ./build/local/ 41 | cp -u -r ../simdata/common/* ./build/local/ 42 | cp -u -r ../simdata/$PLS_OS_NAME/* ./build/local/ 43 | 44 | # Check for and copy JS 45 | if [ -e './src/js/pebble-js-app.js' ] ; then 46 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 47 | echo "[WARNING] Windows does not support javascript apps yet" 48 | else 49 | cat $PLS_SDK_DIR/header.js > ./build/local/pebble-js-app-local.js 50 | cat ./src/js/pebble-js-app.js >> ./build/local/pebble-js-app-local.js 51 | fi 52 | fi 53 | 54 | # Compile resources 55 | PLS_RSC='../bin/resCompiler' 56 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 57 | PLS_RSC=$PLS_RSC'.exe' 58 | fi # No virualenv because this is not a pebble-installed sdk 59 | 60 | if [ ! -e $PLS_RSC ] ; then 61 | echo "[FAIL] Could not start resource compiler" 62 | elif $PLS_RSC ; then 63 | : # no-op 64 | else 65 | echo "[FAIL] Could not compile resources" 66 | exit 1 67 | fi 68 | 69 | # Prepare compile variables 70 | PLS_APP_INCLUDES='-I ./build/tempLocal/ -I ./build/tempLocal/src/ -isystem ../include ' 71 | PLS_APP_LIB_INCLUDES='-L ../bin' 72 | PLS_APP_LIBS='-lPLocalSim -lSDL2 -lSDL2_ttf -lSDL2_image -lm -lpthread' 73 | PLS_APP_ARGS='-c -x c -O2 -Wall -std=c99 -DLOCALSIM -ggdb' 74 | PLS_APP_NAME='testapp' 75 | PLS_APP_OUT='./build/local/'$PLS_APP_NAME 76 | 77 | # Special values 78 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 79 | # Windows/MinGW 80 | PLS_APP_INCLUDES=$PLS_APP_INCLUDES 81 | PLS_APP_LIB_INCLUDES=$PLS_APP_LIB_INCLUDES' -L '$PLS_DIR_SDL'/lib' 82 | PLS_APP_LIBS='-lmingw32 -lSDL2main '$PLS_APP_LIBS 83 | PLS_APP_ARGS=$PLS_APP_ARGS' -mconsole -DWIN32 -D_WIN32' 84 | PLS_APP_OUT=$PLS_APP_OUT'.exe' 85 | fi 86 | 87 | # Compile object files 88 | mkdir -p ./build/tempLocal 89 | rm -f ./build/tempLocal/*.o 90 | filelist='./src/*.c' 91 | PLS_APP_OBJECTS=" " 92 | for file in `ls $filelist` ; do 93 | filename=${file##*/} # without the directory 94 | echo 'Compiling '$filename 95 | objectFile=./build/tempLocal/${filename%.*}'.o' 96 | if $PLS_GCC $PLS_APP_ARGS $PLS_APP_INCLUDES $file -o $objectFile ; then 97 | PLS_APP_OBJECTS=$PLS_APP_OBJECTS' '$objectFile 98 | else 99 | exit 1 100 | fi 101 | done 102 | 103 | echo Linking 104 | $PLS_GCC $PLS_APP_OBJECTS $PLS_APP_LIB_INCLUDES $PLS_APP_LIBS -o $PLS_APP_OUT 105 | 106 | -------------------------------------------------------------------------------- /devhelp/ide/codeblocks/PLocalSim.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 118 | 119 | -------------------------------------------------------------------------------- /devhelp/ide/codeblocks/build.all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # A small script to call build.all.sh in the right working directory 4 | PWD_BACKUP=`pwd` 5 | 6 | cd .. # up to ide 7 | cd .. # up to devhelp 8 | 9 | ./build.all.sh $@ 10 | 11 | cd $PWD_BACKUP 12 | -------------------------------------------------------------------------------- /devhelp/openShell.bat: -------------------------------------------------------------------------------- 1 | @REM This is just a small file to start bash in the current directory 2 | @PATH=%PATH%;%~dp0\..\sdkdata\windows\PLocalSim\MinGW\bin\ 3 | @%~dp0\..\sdkdata\windows\PLocalSim\MinGW\msys\1.0\msys.bat %~dp0 -------------------------------------------------------------------------------- /devhelp/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This is basically a hacked run.local.sh 4 | # don't expect anything fancy in here 5 | 6 | PLS_MY_DIR=`pwd` 7 | 8 | # Load (and fix) envvars 9 | if [ ! -e '../scripts/envvars.sh' ] ; then 10 | echo "[FAIL] Could not load envvars.sh" 11 | exit 1 12 | fi 13 | PLS_ENV_PREFIX=$PLS_MY_DIR'/.' 14 | source '../scripts/envvars.sh' 15 | 16 | # Check for gdb 17 | if hash $PLS_GDB 2>/dev/null; then 18 | : # no-op 19 | else 20 | echo "[FAIL] Could not find required program gdb" 21 | exit 1 22 | fi 23 | 24 | 25 | PLS_DIR_BACKUP=`pwd` 26 | 27 | # Check if we are in a project 28 | while [ ! -e "appinfo.json" ] 29 | do 30 | if [ `pwd` == '/' ] 31 | then 32 | echo "[FAIL] Could not find 'appinfo.json' in this directory or any parent" 1>&2 33 | exit 1 34 | fi 35 | cd .. 36 | done 37 | 38 | # Run the simulator if we find it 39 | PLS_APP_PATH=`pwd` 40 | PLS_APP_NAME='testapp' 41 | PLS_APP_EXEC='./build/local/'$PLS_APP_NAME 42 | if [ -e "$PLS_APP_EXEC" ] ; then 43 | cd build/local 44 | 45 | if [ "$1" == "--debug" ] ; then 46 | $PLS_GDB ./$PLS_APP_NAME 47 | else 48 | ./$PLS_APP_NAME 49 | fi 50 | else 51 | echo "[FAIL] Could not find simulator, maybe it is not compiled yet?" 52 | fi 53 | 54 | cd $PLS_DIR_BACKUP 55 | -------------------------------------------------------------------------------- /devhelp/src/sampleProject.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static Window *window; 4 | static TextLayer *text_layer; 5 | 6 | static void select_click_handler(ClickRecognizerRef recognizer, void *context) { 7 | text_layer_set_text(text_layer, "Select"); 8 | } 9 | 10 | static void up_click_handler(ClickRecognizerRef recognizer, void *context) { 11 | text_layer_set_text(text_layer, "Up"); 12 | } 13 | 14 | static void down_click_handler(ClickRecognizerRef recognizer, void *context) { 15 | text_layer_set_text(text_layer, "Down"); 16 | } 17 | 18 | static void click_config_provider(void *context) { 19 | window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler); 20 | window_single_click_subscribe(BUTTON_ID_UP, up_click_handler); 21 | window_single_click_subscribe(BUTTON_ID_DOWN, down_click_handler); 22 | } 23 | 24 | static void window_load(Window *window) { 25 | Layer *window_layer = window_get_root_layer(window); 26 | GRect bounds = layer_get_bounds(window_layer); 27 | 28 | text_layer = text_layer_create((GRect) { .origin = { 0, 72 }, .size = { bounds.size.w, 20 } }); 29 | text_layer_set_text(text_layer, "Press a button"); 30 | text_layer_set_text_alignment(text_layer, GTextAlignmentCenter); 31 | layer_add_child(window_layer, text_layer_get_layer(text_layer)); 32 | } 33 | 34 | static void window_unload(Window *window) { 35 | text_layer_destroy(text_layer); 36 | } 37 | 38 | static void init(void) { 39 | window = window_create(); 40 | window_set_click_config_provider(window, click_config_provider); 41 | window_set_window_handlers(window, (WindowHandlers) { 42 | .load = window_load, 43 | .unload = window_unload, 44 | }); 45 | const bool animated = true; 46 | window_stack_push(window, animated); 47 | } 48 | 49 | static void deinit(void) { 50 | window_destroy(window); 51 | } 52 | 53 | int main(void) { 54 | init(); 55 | 56 | APP_LOG(APP_LOG_LEVEL_DEBUG, "Done initializing, pushed window: %p", window); 57 | 58 | app_event_loop(); 59 | deinit(); 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /include/pls_unwarn_unsupported_functions.h: -------------------------------------------------------------------------------- 1 | /* This file unwarns all functions that are unsupported by the pebble sdk 2 | * In addition to that, we all hope that the clib did not defined these functions as macros :( 3 | */ 4 | 5 | #undef printf 6 | #undef fopen 7 | #undef fclose 8 | #undef fread 9 | #undef fwrite 10 | #undef fseek 11 | #undef ftell 12 | #undef fsetpos 13 | #undef fscanf 14 | #undef fgetc 15 | #undef fgets 16 | #undef fputc 17 | #undef fputs 18 | #undef fprintf 19 | #undef sprintf 20 | #undef vfprintf 21 | #undef vsprintf 22 | #undef vsnprintf 23 | #undef open 24 | #undef close 25 | #undef creat 26 | #undef read 27 | #undef write 28 | #undef stat 29 | #undef alloca 30 | #undef mmap 31 | #undef brk 32 | #undef sbrk 33 | 34 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PLS_MY_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 4 | 5 | if [ ! -e $PLS_MY_DIR'/scripts/envvars.sh' ] ; then 6 | echo "[FAIL] Could not load envvars.sh" 7 | exit 1 8 | fi 9 | source $PLS_MY_DIR'/scripts/envvars.sh' 10 | 11 | # Find target path 12 | PLS_TARGET_PATH=$1 13 | PLS_IS_STANDALONE='true' 14 | if [ -z "$PLS_TARGET_PATH" ] ; then 15 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ] ; then 16 | echo "[FAIL] PLocalSim does need a specific directory on windows" 17 | exit 1 18 | else 19 | # try to find the pebble sdk 20 | PLS_PATH_PEBBLE=`which pebble` 21 | if [ $? -eq 0 ] ; then 22 | PLS_TARGET_PATH=`dirname $PLS_PATH_PEBBLE` 23 | PLS_IS_STANDALONE='false' 24 | else 25 | echo "[FAIL] PLocalSim could not locate the pebble sdk" 26 | exit 1 27 | fi 28 | fi 29 | fi 30 | 31 | # Check if the sdk is built already 32 | PLS_SIM_LIB=$PLS_MY_DIR'/bin/libPLocalSim.a' 33 | PLS_RSC_EXE=$PLS_MY_DIR'/bin/resCompiler' 34 | PLS_RECOMPILE_RSC='false' 35 | PLS_RSC_BUILD_ARGS=' ' 36 | PLS_OS_NAME='unix' 37 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 38 | PLS_RSC_EXE=$PLS_RSC_EXE'.exe' 39 | PLS_OS_NAME='windows' 40 | elif [ "$PLS_IS_STANDALONE" == "true" ] ; then 41 | # Unix systems must use the c resourceCompiler because the python requires 42 | # the pebble libraries we don't have on stand-alone installations 43 | PLS_RECOMPILE_RSC='true' 44 | PLS_RSC_BUILD_ARGS='-c' 45 | fi 46 | 47 | if [ ! -e $PLS_SIM_LIB ] ; then 48 | echo "[INFO] PLocalSim library is not built yet, compiling..." 49 | if ./scripts/build.library.sh ; then 50 | echo "[INFO] Sucessfully compiled PLocalSim library" 51 | else 52 | echo "[FAIL] Could not compile PLocalSim library" 53 | exit 1 54 | fi 55 | fi 56 | 57 | if [ ! -e $PLS_RSC_EXE ] ; then 58 | PLS_RECOMPILE_RSC='true' 59 | fi 60 | if [ "$PLS_RECOMPILE_RSC" == "true" ] ; then 61 | echo "[INFO] PLocalSim resource compiler is not built yet, compiling..." 62 | if ./scripts/build.resCompiler.sh $PLS_RSC_BUILD_ARGS ; then 63 | echo "[INFO] Sucessfully compiled PLocalSim resource compiler" 64 | else 65 | echo "[FAIL] Could not compile PLocalSim resource compiler" 66 | exit 1 67 | fi 68 | fi 69 | 70 | # Create/Test directory 71 | mkdir -p $PLS_TARGET_PATH'/PLocalSim/simdata' 72 | if [ ! -d "$PLS_TARGET_PATH" ] ; then 73 | echo "[FAIL] Invalid directory: $PLS_TARGET_PATH" 74 | exit 1 75 | fi 76 | 77 | # Copy all of the sdk 78 | echo "[INFO] Copy common sdk data" 79 | cp -f -r $PLS_MY_DIR/bin/* $PLS_TARGET_PATH'/PLocalSim/' 80 | cp -f -r $PLS_MY_DIR/sdkdata/common/* $PLS_TARGET_PATH'/' 81 | cp -f -r $PLS_MY_DIR/simdata/common/* $PLS_TARGET_PATH'/PLocalSim/simdata/' 82 | 83 | echo "[INFO] Copy OS specific data (may take a few minutes)" 84 | cp -f -r $PLS_MY_DIR/sdkdata/$PLS_OS_NAME/* $PLS_TARGET_PATH'/' 85 | cp -f -r $PLS_MY_DIR/simdata/$PLS_OS_NAME/* $PLS_TARGET_PATH'/PLocalSim/simdata/' 86 | 87 | if [ "$PLS_IS_STANDALONE" == 'true' ]; then 88 | echo "[INFO] Copy data for stand-alone installations" 89 | mkdir -p $PLS_TARGET_PATH'/PLocalSim/include' 90 | cp -f -r $PLS_MY_DIR/include/* $PLS_TARGET_PATH'/PLocalSim/include/' 91 | cp -f -r $PLS_MY_DIR/sdkdata/standalone/* $PLS_TARGET_PATH'/' 92 | fi 93 | -------------------------------------------------------------------------------- /openShell.bat: -------------------------------------------------------------------------------- 1 | @REM This is just a small file to start bash in the current directory 2 | @PATH=%PATH%;%~dp0\sdkdata\windows\PLocalSim\MinGW\bin\ 3 | @%~dp0\sdkdata\windows\PLocalSim\MinGW\msys\1.0\msys.bat %~dp0 -------------------------------------------------------------------------------- /scripts/build.library.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PLS_MY_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 4 | PLS_LIB_CACHE=$2 5 | 6 | if [ ! -e $PLS_MY_DIR'/envvars.sh' ] ; then 7 | echo "[FAIL] Could not load envvars.sh" 8 | exit 1 9 | fi 10 | source $PLS_MY_DIR'/envvars.sh' 11 | 12 | # check if we have gcc and ar 13 | if hash $PLS_GCC 2>/dev/null; then 14 | if hash $PLS_AR 2>/dev/null; then 15 | 16 | # prepare some variables 17 | PLS_SIM_INCLUDES='-isystem ./include -I ./src/local -I ./src/local/dummy -I ./src/SDL_gfx -I ./src/jsmn' 18 | 19 | PLS_SIM_OUTPUT='./bin/libPLocalSim.a' 20 | PLS_SIM_TMP_OUT='./obj' 21 | PLS_SIM_GCC_ARGS='-c -std=c99 ' 22 | 23 | if [ "$1" == "--debug" ]; then 24 | PLS_SIM_GCC_ARGS=$PLS_SIM_GCC_ARGS' -ggdb' 25 | else 26 | PLS_SIM_GCC_ARGS=$PLS_SIM_GCC_ARGS' -O2' 27 | fi 28 | 29 | # MinGW specific values 30 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 31 | PLS_SIM_GCC_ARGS='-DWIN32 -D_WIN32 -mconsole '$PLS_SIM_GCC_ARGS 32 | PLS_SIM_INCLUDES='-I '$PLS_DIR_SDL'/include -isystem '$PLS_DIR_SDL'/include/SDL2 '$PLS_SIM_INCLUDES 33 | fi 34 | 35 | # create directories and delete old object files 36 | mkdir -p ./bin 37 | mkdir -p $PLS_SIM_TMP_OUT 38 | filelist=$PLS_SIM_TMP_OUT'/*.o' 39 | 40 | # how to compile a directory, params: 41 | # directory to compile 42 | # 'silent' if you don't want to output every filename 43 | # extra compile options 44 | function compileDirectory { 45 | filelist=$1'/*.c' 46 | for file in `ls $filelist` ; do 47 | filename=${file##*/} # without the directory 48 | objectFile=$PLS_SIM_TMP_OUT'/'${filename%.*}'.o' 49 | hashFile=$PLS_LIB_CACHE'/'${filename%.*}'.md5' 50 | 51 | dobuildfile='true' 52 | error='true' 53 | 54 | # Check cache 55 | if [ ! -z "$PLS_LIB_CACHE" ] ; then 56 | if [ -e "$objectFile" ] ; then 57 | if [ -e "$hashFile" ] ; then 58 | savedhash=$(<$hashFile) 59 | calcedhash=`date -r $file +%s``date -r $objectFile +%s` 60 | if [ "$savedhash" == "$calcedhash" ] ; then 61 | dobuildfile='false' 62 | if [ ! 'silent' = "$2" ] ; then 63 | echo Using cached $filename 64 | fi 65 | if $PLS_AR rcs $PLS_SIM_OUTPUT $objectFile ; then 66 | error='false' 67 | fi 68 | fi 69 | fi 70 | fi 71 | fi 72 | 73 | # Compile file 74 | if [ "$dobuildfile" == "true" ]; then 75 | if [ ! 'silent' = "$2" ] ; then 76 | echo Compiling $filename 77 | fi 78 | if $PLS_GCC $PLS_SIM_GCC_ARGS $3 $PLS_SIM_INCLUDES $file -o $objectFile ; then 79 | if $PLS_AR rcs $PLS_SIM_OUTPUT $objectFile ; then 80 | error='false' 81 | 82 | # Update cache 83 | if [ ! -z "$PLS_LIB_CACHE" ] ; then 84 | newhash=`date -r $file +%s``date -r $objectFile +%s` 85 | touch "$hashFile" 86 | echo "$newhash" > "$hashFile" 87 | fi 88 | fi 89 | fi 90 | fi 91 | 92 | if [ 'true' = "$error" ] ; then 93 | echo Compilation failed 94 | rm -f $PLS_SIM_OUTPUT 95 | exit 1 96 | fi 97 | 98 | done 99 | return 1 100 | } 101 | 102 | # Compile the library 103 | compileDirectory ./src/local 'no' '-Wall -Wno-format' 104 | 105 | echo Compiling SDL_gfx 106 | compileDirectory './src/SDL_gfx' 'silent' '-Wall' 107 | 108 | echo Compiling jsmn 109 | compileDirectory './src/jsmn' 'silent' '-w' 110 | 111 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 112 | echo Compiling additional source 113 | compileDirectory './src/additional' 'silent' '-w' 114 | fi 115 | 116 | exit 0 117 | 118 | else 119 | echo "Could not find required program ar" 120 | exit 1 121 | fi 122 | else 123 | echo "Could not find required program gcc" 124 | exit 1 125 | fi 126 | -------------------------------------------------------------------------------- /scripts/build.resCompiler.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PLS_MY_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 4 | 5 | if [ ! -e $PLS_MY_DIR'/envvars.sh' ] ; then 6 | echo "[FAIL] Could not load envvars.sh" 7 | exit 1 8 | fi 9 | source $PLS_MY_DIR'/envvars.sh' 10 | 11 | # The compilation process of the c program is cross-platform but 12 | # at the moment we use the python version on unix systems 13 | PLS_RSC_OUTPUT='./bin/resCompiler' 14 | 15 | PLS_USE_C='false' 16 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ] ; then 17 | PLS_USE_C='true' 18 | elif [ "$1" == "-c" ] ; then 19 | PLS_USE_C='true' 20 | fi 21 | 22 | if [ "$PLS_USE_C" == "true" ]; then 23 | # check if we have gcc 24 | if hash $PLS_GCC 2>/dev/null; then 25 | mkdir -p ./bin 26 | 27 | # prepare some variables 28 | PLS_RSC_INCLUDES='-I ./src/resourceCompiler -I ./src/jsmn' 29 | PLS_RSC_SOURCE=`ls ./src/resourceCompiler/*.c`' '`ls ./src/jsmn/*.c` 30 | PLS_RSC_GCC_ARGS='-O2 -std=c99 -Wno-unused-result' 31 | PLS_RSC_LIBS='-lSDL2main -lSDL2 -lSDL2_image' 32 | 33 | # MinGW specific values 34 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 35 | PLS_RSC_GCC_ARGS='-DWIN32 -D_WIN32 -mconsole -L '$PLS_DIR_SDL'/lib '$PLS_RSC_GCC_ARGS 36 | PLS_RSC_INCLUDES='-I '$PLS_DIR_SDL'/include -I '$PLS_DIR_SDL'/include/SDL2 '$PLS_RSC_INCLUDES 37 | PLS_RSC_LIBS='-lmingw32 '$PLS_RSC_LIBS 38 | PLS_RSC_OUTPUT=$PLS_RSC_OUTPUT'.exe' 39 | 40 | cp -u -r $PLS_DIR_SDL/bin/* ./bin/ 41 | fi 42 | 43 | # Compile the resource compiler 44 | if $PLS_GCC $PLS_RSC_GCC_ARGS $PLS_RSC_INCLUDES $PLS_RSC_SOURCE $PLS_RSC_LIBS -o $PLS_RSC_OUTPUT ; then 45 | exit 0 46 | else 47 | echo "[FAIL] Compilation failed" 48 | exit 1 49 | fi 50 | 51 | else 52 | echo "Could not find required program gcc" 53 | exit 1 54 | fi 55 | 56 | else # if the python version shall be used 57 | cp -f './src/resourceCompiler/resCompiler.py' $PLS_RSC_OUTPUT 58 | fi 59 | -------------------------------------------------------------------------------- /scripts/envvars.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # PLS_ENV_PREFIX is currently only used by devhelp 4 | # If you use custom variables, don't use PLS_ENV_PREFIX 5 | 6 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 7 | PLS_GCC=$PLS_ENV_PREFIX'./sdkdata/windows/PLocalSim/MinGW/bin/gcc.exe' 8 | PLS_AR=$PLS_ENV_PREFIX'./sdkdata/windows/PLocalSim/MinGW/bin/ar.exe' 9 | PLS_GDB=$PLS_ENV_PREFIX'./sdkdata/windows/PLocalSim/MinGW/bin/gdb.exe' 10 | PLS_DIR_SDL=$PLS_ENV_PREFIX'./sdkdata/windows/PLocalSim/SDL2' 11 | else 12 | PLS_GCC='gcc' 13 | PLS_AR='ar' 14 | PLS_GDB='gdb' 15 | fi 16 | -------------------------------------------------------------------------------- /sdkdata/common/build.local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if we have access to gcc 4 | PLS_SDK_ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | PLS_SDK_DIR=$PLS_SDK_ROOT_DIR'/PLocalSim' 6 | 7 | if [ ! -e $PLS_SDK_DIR'/envvars.sh' ] ; then 8 | echo "[FAIL] Could not load envvars.sh" 9 | exit 1 10 | fi 11 | source $PLS_SDK_DIR'/envvars.sh' 12 | 13 | PLS_COMPILE_MODE='release' 14 | if [ "$1" == "--debug" ] ; then 15 | PLS_COMPILE_MODE='debug' 16 | fi 17 | if hash $PLS_GCC 2>/dev/null; then 18 | echo "[INFO] Compile app as "$PLS_COMPILE_MODE 19 | else 20 | echo "[FAIL] Could not find required program gcc" 21 | exit 1 22 | fi 23 | 24 | # Check if we are in a project 25 | while [ ! -e "appinfo.json" ] 26 | do 27 | if [ `pwd` == '/' ] 28 | then 29 | echo "[FAIL] Could not find 'appinfo.json' in this directory or any parent" 1>&2 30 | exit 1 31 | fi 32 | cd .. 33 | done 34 | 35 | # Copy resources and app info 36 | mkdir -p ./build/local/ 37 | cp -f ./appinfo.json ./build/local/ 38 | cp -f -r $PLS_SDK_DIR/simdata/* ./build/local/ 39 | 40 | # Check for and copy JS 41 | if [ -e './src/js/pebble-js-app.js' ] ; then 42 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 43 | echo "[WARNING] Windows does not support javascript apps yet" 44 | else 45 | cat $PLS_SDK_DIR/header.js > ./build/local/pebble-js-app-local.js 46 | cat ./src/js/pebble-js-app.js >> ./build/local/pebble-js-app-local.js 47 | fi 48 | fi 49 | 50 | # Compile resources 51 | PLS_RSC=$PLS_SDK_DIR'/resCompiler' 52 | PLS_POST_COMMAND=' ' 53 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 54 | PLS_RSC=$PLS_RSC'.exe' 55 | elif [ -e $PLS_SDK_DIR/../../.env/bin/activate ] ; then 56 | # use the virtual environment to access the required python libs 57 | source $PLS_SDK_DIR'/../../.env/bin/activate' 58 | PLS_POST_COMMAND='deactivate' 59 | fi 60 | 61 | error='true' 62 | if $PLS_RSC ; then 63 | error='false' 64 | fi 65 | 66 | $PLS_POST_COMMAND 67 | 68 | if [ "$error" == 'true' ] ; then 69 | echo "[FAIL] Could not compile resources" 70 | exit 1 71 | fi 72 | 73 | # Prepare compile variables 74 | PLS_APP_INCLUDES='-I ./build/tempLocal/ -I ./build/tempLocal/src/' 75 | PLS_APP_LIB_INCLUDES='-L '$PLS_SDK_DIR 76 | PLS_APP_LIBS='-lPLocalSim -lSDL2 -lSDL2_ttf -lSDL2_image -lm -lpthread' 77 | PLS_APP_ARGS='-c -x c -O2 -Wall -std=c99 -DLOCALSIM' 78 | PLS_APP_PATH=`pwd` 79 | PLS_APP_NAME=`basename $PLS_APP_PATH` 80 | PLS_APP_OUT='./build/local/'$PLS_APP_NAME 81 | PLS_SDK_HEADERS=$PLS_SDK_DIR'/include' 82 | 83 | # Special values 84 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 85 | # Windows/MinGW 86 | # ' -I '$PLS_SDK_DIR$PLS_DIR_SDL'/include ' 87 | PLS_APP_INCLUDES=$PLS_APP_INCLUDES 88 | PLS_APP_LIB_INCLUDES=$PLS_APP_LIB_INCLUDES' -L '$PLS_DIR_SDL'/lib' 89 | PLS_APP_LIBS='-lmingw32 -lSDL2main '$PLS_APP_LIBS 90 | PLS_APP_ARGS=$PLS_APP_ARGS' -mconsole -DWIN32 -D_WIN32' 91 | PLS_APP_OUT=$PLS_APP_OUT'.exe' 92 | else 93 | # Unix 94 | if [ -e $PLS_SDK_ROOT_DIR/pebble ] ; then 95 | PLS_SDK_HEADERS=$PLS_SDK_DIR'/../../Pebble/include' 96 | fi 97 | fi 98 | PLS_APP_INCLUDES=$PLS_APP_INCLUDES' -isystem '$PLS_SDK_HEADERS 99 | 100 | # Debug flag 101 | if [ "$1" == "--debug" ] ; then 102 | PLS_APP_ARGS=$PLS_APP_ARGS' -ggdb' 103 | fi 104 | 105 | # Compile object files 106 | mkdir -p ./build/tempLocal 107 | rm -f ./build/tempLocal/*.o 108 | filelist='./src/*.c' 109 | PLS_APP_OBJECTS=" " 110 | for file in `ls $filelist` ; do 111 | filename=${file##*/} # without the directory 112 | echo 'Compiling '$filename 113 | objectFile=./build/tempLocal/${filename%.*}'.o' 114 | if $PLS_GCC $PLS_APP_ARGS $PLS_APP_INCLUDES $file -o $objectFile ; then 115 | PLS_APP_OBJECTS=$PLS_APP_OBJECTS' '$objectFile 116 | else 117 | exit 1 118 | fi 119 | done 120 | 121 | echo Linking 122 | $PLS_GCC $PLS_APP_OBJECTS $PLS_APP_LIB_INCLUDES $PLS_APP_LIBS -o $PLS_APP_OUT 123 | 124 | -------------------------------------------------------------------------------- /sdkdata/common/run.local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if we have access to gcc 4 | PLS_SDK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | PLS_SDK_DIR=$PLS_SDK_DIR'/PLocalSim' 6 | 7 | if [ ! -e $PLS_SDK_DIR'/envvars.sh' ] ; then 8 | echo "[FAIL] Could not load envvars.sh" 9 | exit 1 10 | fi 11 | source $PLS_SDK_DIR'/envvars.sh' 12 | 13 | if hash $PLS_GDB 2>/dev/null; then 14 | echo "[INFO] Compile app as local simulator" 15 | else 16 | echo "[FAIL] Could not find required program gdb" 17 | exit 1 18 | fi 19 | 20 | PLS_DIR_BACKUP=`pwd` 21 | 22 | # Check if we are in a project 23 | while [ ! -e "appinfo.json" ] 24 | do 25 | if [ `pwd` == '/' ] 26 | then 27 | echo "[FAIL] Could not find 'appinfo.json' in this directory or any parent" 1>&2 28 | exit 1 29 | fi 30 | cd .. 31 | done 32 | 33 | # Run the simulator if we find it 34 | PLS_APP_PATH=`pwd` 35 | PLS_APP_NAME=`basename $PLS_APP_PATH` 36 | PLS_APP_EXEC='./build/local/'$PLS_APP_NAME 37 | if [ -e "$PLS_APP_EXEC" ] ; then 38 | cd build/local 39 | 40 | if [ "$1" == "--debug" ] ; then 41 | $PLS_GDB ./$PLS_APP_NAME 42 | else 43 | ./$PLS_APP_NAME 44 | fi 45 | else 46 | echo "[FAIL] Could not find simulator, maybe it is not compiled yet?" 47 | fi 48 | 49 | cd $PLS_DIR_BACKUP 50 | -------------------------------------------------------------------------------- /sdkdata/standalone/PLocalSim/projectTemplate/appinfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "uuid": "79a0f865-22da-415d-9764-6012a07a1bd6", 3 | "shortName": "sampleProject", 4 | "longName": "sampleProject", 5 | "companyName": "MakeAwesomeHappen", 6 | "versionCode": 1, 7 | "versionLabel": "1.0.0", 8 | "watchapp": { 9 | "watchface": false 10 | }, 11 | "appKeys": { 12 | "dummy": 0 13 | }, 14 | "resources": { 15 | "media": [] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sdkdata/standalone/PLocalSim/projectTemplate/src/sampleProject.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static Window *window; 4 | static TextLayer *text_layer; 5 | 6 | static void select_click_handler(ClickRecognizerRef recognizer, void *context) { 7 | text_layer_set_text(text_layer, "Select"); 8 | } 9 | 10 | static void up_click_handler(ClickRecognizerRef recognizer, void *context) { 11 | text_layer_set_text(text_layer, "Up"); 12 | } 13 | 14 | static void down_click_handler(ClickRecognizerRef recognizer, void *context) { 15 | text_layer_set_text(text_layer, "Down"); 16 | } 17 | 18 | static void click_config_provider(void *context) { 19 | window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler); 20 | window_single_click_subscribe(BUTTON_ID_UP, up_click_handler); 21 | window_single_click_subscribe(BUTTON_ID_DOWN, down_click_handler); 22 | } 23 | 24 | static void window_load(Window *window) { 25 | Layer *window_layer = window_get_root_layer(window); 26 | GRect bounds = layer_get_bounds(window_layer); 27 | 28 | text_layer = text_layer_create((GRect) { .origin = { 0, 72 }, .size = { bounds.size.w, 20 } }); 29 | text_layer_set_text(text_layer, "Press a button"); 30 | text_layer_set_text_alignment(text_layer, GTextAlignmentCenter); 31 | layer_add_child(window_layer, text_layer_get_layer(text_layer)); 32 | } 33 | 34 | static void window_unload(Window *window) { 35 | text_layer_destroy(text_layer); 36 | } 37 | 38 | static void init(void) { 39 | window = window_create(); 40 | window_set_click_config_provider(window, click_config_provider); 41 | window_set_window_handlers(window, (WindowHandlers) { 42 | .load = window_load, 43 | .unload = window_unload, 44 | }); 45 | const bool animated = true; 46 | window_stack_push(window, animated); 47 | } 48 | 49 | static void deinit(void) { 50 | window_destroy(window); 51 | } 52 | 53 | int main(void) { 54 | init(); 55 | 56 | APP_LOG(APP_LOG_LEVEL_DEBUG, "Done initializing, pushed window: %p", window); 57 | 58 | app_event_loop(); 59 | deinit(); 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /sdkdata/standalone/create.project.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PLS_SDK_ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | PLS_SDK_DIR=$PLS_SDK_ROOT_DIR'/PLocalSim' 5 | 6 | if [ ! -e $PLS_SDK_DIR'/envvars.sh' ] ; then 7 | echo "[FAIL] Could not load envvars.sh" 8 | exit 1 9 | fi 10 | source $PLS_SDK_DIR'/envvars.sh' 11 | 12 | # Create/Test directory 13 | PLS_TARGET_PATH=$1 14 | if [ -z "$PLS_TARGET_PATH" ] ; then 15 | echo "[FAIL] correct usage: create.project.sh " 16 | exit 1 17 | fi 18 | 19 | mkdir -p $PLS_TARGET_PATH 20 | if [ ! -d "$PLS_TARGET_PATH" ] ; then 21 | echo "[FAIL] Invalid directory: $PLS_TARGET_PATH" 22 | exit 1 23 | fi 24 | 25 | # Copy project template 26 | cp -f -r $PLS_SDK_DIR/projectTemplate/* $PLS_TARGET_PATH'/' 27 | 28 | PLS_EOL='\n' 29 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then 30 | PLS_EOL='\r\n' 31 | 32 | # Get the sdk path in windows style 33 | PLS_DIR_BACKUP=`pwd` 34 | cd $PLS_SDK_ROOT_DIR 35 | PLS_SDK_DIR_WIN=`pwd -W` 36 | cd $PLS_DIR_BACKUP 37 | 38 | # Generate openShell.bat 39 | PLS_OPEN_SHELL_BAT='@"'$PLS_SDK_DIR_WIN'/openShell.bat' 40 | echo $PLS_OPEN_SHELL_BAT > $PLS_TARGET_PATH'/openShell.bat' 41 | fi 42 | 43 | # Generate build.local.bat 44 | echo -e "#!/bin/bash$PLS_EOL" > $PLS_TARGET_PATH'/build.local.sh' 45 | echo '"'$PLS_SDK_ROOT_DIR'/build.local.sh" $@' >> $PLS_TARGET_PATH'/build.local.sh' 46 | 47 | # Generate run.local.bat 48 | echo -e "#!/bin/bash$PLS_EOL" > $PLS_TARGET_PATH'/run.local.sh' 49 | echo '"'$PLS_SDK_ROOT_DIR'/run.local.sh" $@' >> $PLS_TARGET_PATH'/run.local.sh' 50 | -------------------------------------------------------------------------------- /sdkdata/unix/PLocalSim/appjs_header.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////// 2 | // Standard header to setup Pebble environment 3 | 4 | var Pebble = require('./simdata/server'); 5 | 6 | var window = window || {}; 7 | window.navigator = { }; 8 | window.navigator.geolocation = Pebble.geolocation; 9 | 10 | var localStorage = new (require('./simdata/localStorage').Storage)("localStorage.dat"); 11 | 12 | var XMLHttpRequest = require('./simdata/XMLHttpRequest').XMLHttpRequest; 13 | 14 | console.log = ((function() { 15 | var orig_log = console.log; 16 | return function() { 17 | if ((arguments.length > 0) && 18 | (typeof(arguments[0]) === 'string')) 19 | arguments[0] = "[JS App] " + arguments[0]; 20 | 21 | orig_log.apply(console, arguments); 22 | }; 23 | })()); 24 | 25 | ///////////////////////////////////////////////// 26 | 27 | 28 | -------------------------------------------------------------------------------- /sdkdata/unix/PLocalSim/envvars.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PLS_GCC="gcc" 4 | PLS_AR="ar" 5 | PLS_GDB="gdb" 6 | -------------------------------------------------------------------------------- /sdkdata/windows/PLocalSim/envvars.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PLS_GCC=$PLS_SDK_DIR'/MinGW/bin/gcc.exe' 4 | PLS_AR=$PLS_SDK_DIR'/MinGW/bin/ar.exe' 5 | PLS_GDB=$PLS_SDK_DIR'/MinGW/bin/gdb.exe' 6 | PLS_DIR_SDL=$PLS_SDK_DIR'/SDL2' 7 | -------------------------------------------------------------------------------- /sdkdata/windows/openShell.bat: -------------------------------------------------------------------------------- 1 | @REM This is just a small file to start bash in the current directory 2 | @PATH=%PATH%;%~dp0\PLocalSim\MinGW\bin\ 3 | @%~dp0\PLocalSim\MinGW\msys\1.0\msys.bat %~dp0 -------------------------------------------------------------------------------- /simdata/common/LICENSE.freetype.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/LICENSE.freetype.txt -------------------------------------------------------------------------------- /simdata/common/LICENSE.png.txt: -------------------------------------------------------------------------------- 1 | The source code to this library used with SDL_image can be found here: 2 | http://www.libsdl.org/projects/SDL_image/libs/ 3 | --- 4 | 5 | This copy of the libpng notices is provided for your convenience. In case of 6 | any discrepancy between this copy and the notices in the file png.h that is 7 | included in the libpng distribution, the latter shall prevail. 8 | 9 | COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: 10 | 11 | If you modify libpng you may insert additional notices immediately following 12 | this sentence. 13 | 14 | This code is released under the libpng license. 15 | 16 | libpng versions 1.2.6, August 15, 2004, through 1.5.7, December 15, 2011, are 17 | Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are 18 | distributed according to the same disclaimer and license as libpng-1.2.5 19 | with the following individual added to the list of Contributing Authors 20 | 21 | Cosmin Truta 22 | 23 | libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are 24 | Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are 25 | distributed according to the same disclaimer and license as libpng-1.0.6 26 | with the following individuals added to the list of Contributing Authors 27 | 28 | Simon-Pierre Cadieux 29 | Eric S. Raymond 30 | Gilles Vollant 31 | 32 | and with the following additions to the disclaimer: 33 | 34 | There is no warranty against interference with your enjoyment of the 35 | library or against infringement. There is no warranty that our 36 | efforts or the library will fulfill any of your particular purposes 37 | or needs. This library is provided with all faults, and the entire 38 | risk of satisfactory quality, performance, accuracy, and effort is with 39 | the user. 40 | 41 | libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are 42 | Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are 43 | distributed according to the same disclaimer and license as libpng-0.96, 44 | with the following individuals added to the list of Contributing Authors: 45 | 46 | Tom Lane 47 | Glenn Randers-Pehrson 48 | Willem van Schaik 49 | 50 | libpng versions 0.89, June 1996, through 0.96, May 1997, are 51 | Copyright (c) 1996, 1997 Andreas Dilger 52 | Distributed according to the same disclaimer and license as libpng-0.88, 53 | with the following individuals added to the list of Contributing Authors: 54 | 55 | John Bowler 56 | Kevin Bracey 57 | Sam Bushell 58 | Magnus Holmgren 59 | Greg Roelofs 60 | Tom Tanner 61 | 62 | libpng versions 0.5, May 1995, through 0.88, January 1996, are 63 | Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. 64 | 65 | For the purposes of this copyright and license, "Contributing Authors" 66 | is defined as the following set of individuals: 67 | 68 | Andreas Dilger 69 | Dave Martindale 70 | Guy Eric Schalnat 71 | Paul Schmidt 72 | Tim Wegner 73 | 74 | The PNG Reference Library is supplied "AS IS". The Contributing Authors 75 | and Group 42, Inc. disclaim all warranties, expressed or implied, 76 | including, without limitation, the warranties of merchantability and of 77 | fitness for any purpose. The Contributing Authors and Group 42, Inc. 78 | assume no liability for direct, indirect, incidental, special, exemplary, 79 | or consequential damages, which may result from the use of the PNG 80 | Reference Library, even if advised of the possibility of such damage. 81 | 82 | Permission is hereby granted to use, copy, modify, and distribute this 83 | source code, or portions hereof, for any purpose, without fee, subject 84 | to the following restrictions: 85 | 86 | 1. The origin of this source code must not be misrepresented. 87 | 88 | 2. Altered versions must be plainly marked as such and must not 89 | be misrepresented as being the original source. 90 | 91 | 3. This Copyright notice may not be removed or altered from any 92 | source or altered source distribution. 93 | 94 | The Contributing Authors and Group 42, Inc. specifically permit, without 95 | fee, and encourage the use of this source code as a component to 96 | supporting the PNG file format in commercial products. If you use this 97 | source code in a product, acknowledgment is not required but would be 98 | appreciated. 99 | 100 | 101 | A "png_get_copyright" function is available, for convenient use in "about" 102 | boxes and the like: 103 | 104 | printf("%s",png_get_copyright(NULL)); 105 | 106 | Also, the PNG logo (in PNG format, of course) is supplied in the 107 | files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). 108 | 109 | Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a 110 | certification mark of the Open Source Initiative. 111 | 112 | Glenn Randers-Pehrson 113 | glennrp at users.sourceforge.net 114 | December 15, 2011 115 | -------------------------------------------------------------------------------- /simdata/common/LICENSE.zlib.txt: -------------------------------------------------------------------------------- 1 | The source code to this library used with SDL_ttf can be found here: 2 | http://www.libsdl.org/projects/SDL_ttf/libs/ 3 | --- 4 | 5 | Copyright notice: 6 | 7 | (C) 1995-2010 Jean-loup Gailly and Mark Adler 8 | 9 | This software is provided 'as-is', without any express or implied 10 | warranty. In no event will the authors be held liable for any damages 11 | arising from the use of this software. 12 | 13 | Permission is granted to anyone to use this software for any purpose, 14 | including commercial applications, and to alter it and redistribute it 15 | freely, subject to the following restrictions: 16 | 17 | 1. The origin of this software must not be misrepresented; you must not 18 | claim that you wrote the original software. If you use this software 19 | in a product, an acknowledgment in the product documentation would be 20 | appreciated but is not required. 21 | 2. Altered source versions must be plainly marked as such, and must not be 22 | misrepresented as being the original software. 23 | 3. This notice may not be removed or altered from any source distribution. 24 | 25 | Jean-loup Gailly Mark Adler 26 | jloup@gzip.org madler@alumni.caltech.edu 27 | 28 | If you use the zlib library in a product, we would appreciate *not* receiving 29 | lengthy legal documents to sign. The sources are provided for free but without 30 | warranty of any kind. The library has been entirely written by Jean-loup 31 | Gailly and Mark Adler; it does not include third-party code. 32 | -------------------------------------------------------------------------------- /simdata/common/images/backlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/images/backlight.png -------------------------------------------------------------------------------- /simdata/common/images/body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/images/body.png -------------------------------------------------------------------------------- /simdata/common/images/screenshadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/images/screenshadow.png -------------------------------------------------------------------------------- /simdata/common/images/scrollshadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/images/scrollshadow.png -------------------------------------------------------------------------------- /simdata/common/images/statusbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/images/statusbar.png -------------------------------------------------------------------------------- /simdata/common/images/vibe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/images/vibe.png -------------------------------------------------------------------------------- /simdata/common/systemFonts/Google Android License.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2008 The Android Open Source Project 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ########## 16 | 17 | This directory contains the fonts for the platform. They are licensed 18 | under the Apache 2 license. 19 | 20 | ########## 21 | 22 | A note from Helco: 23 | 24 | All other fonts whose names begin with "gothic" or "bitham" are 25 | "droidserif-regular.ttf" or "droidserif-bold.ttf". This has to be done 26 | because gothic and bitham (gotham?) are commercial fonts and therefore 27 | can not be used in this free simulator. 28 | If you have these fonts you can replace them without changing a single 29 | character in the source code of this simulator. -------------------------------------------------------------------------------- /simdata/common/systemFonts/bitham-black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/bitham-black.ttf -------------------------------------------------------------------------------- /simdata/common/systemFonts/bitham-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/bitham-bold.ttf -------------------------------------------------------------------------------- /simdata/common/systemFonts/bitham-light-subset.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/bitham-light-subset.ttf -------------------------------------------------------------------------------- /simdata/common/systemFonts/bitham-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/bitham-light.ttf -------------------------------------------------------------------------------- /simdata/common/systemFonts/bitham-medium-numbers.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/bitham-medium-numbers.ttf -------------------------------------------------------------------------------- /simdata/common/systemFonts/droid-serif-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/droid-serif-bold.ttf -------------------------------------------------------------------------------- /simdata/common/systemFonts/gothic-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/gothic-bold.ttf -------------------------------------------------------------------------------- /simdata/common/systemFonts/gothic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/gothic.ttf -------------------------------------------------------------------------------- /simdata/common/systemFonts/roboto-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/roboto-bold.ttf -------------------------------------------------------------------------------- /simdata/common/systemFonts/roboto-condensed.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/common/systemFonts/roboto-condensed.ttf -------------------------------------------------------------------------------- /simdata/unix/server.js: -------------------------------------------------------------------------------- 1 | var net = require("net"); 2 | var fs = require("fs"); 3 | 4 | // event listener callbacks 5 | var readyFunc = null; 6 | var messageFunc = null; 7 | 8 | // part of Pebble API 9 | module.exports.addEventListener = function(event, fn) { 10 | if (typeof(fn) !== 'function') 11 | return; 12 | 13 | if (event === "ready") 14 | readyFunc = fn; 15 | else if (event == "appmessage") 16 | messageFunc = fn; 17 | else if (event == "webviewclosed") 18 | ; 19 | else 20 | throw "Invalid Event"; 21 | 22 | console.log("[INFO] Added event listener for: " + event); 23 | }; 24 | 25 | // helper class to translate keys to friendly name and vice versa 26 | function KeyTranslator(filename) { 27 | this.nameToKey = null; 28 | this.keyToName = null; 29 | 30 | // pull out friendly names from appKeys section of appinfo.json 31 | try { 32 | var contents = fs.readFileSync("appinfo.json"); 33 | contents = JSON.parse(contents); 34 | if (contents.appKeys) { 35 | this.nameToKey = contents.appKeys; 36 | this.keyToName = { }; 37 | for (var n in contents.appKeys) { 38 | if (contents.appKeys.hasOwnProperty(n)) { 39 | this.keyToName[contents.appKeys[n]] = n; 40 | } 41 | } 42 | } 43 | } 44 | catch(e) { 45 | // appinfo.json should be there but swallow error if it isnt 46 | console.log("[WARN] appinfo.json could not be read"); 47 | } 48 | } 49 | 50 | // name --> key (integer) 51 | KeyTranslator.prototype.translateName = function(name) { 52 | if (!this.nameToKey || (this.nameToKey[name]==undefined)) { 53 | var ikey = parseInt(name); 54 | if (isNaN(ikey)) 55 | throw "Invalid Key"; 56 | return ikey; 57 | } 58 | 59 | return this.nameToKey[name]; 60 | }; 61 | 62 | // key --> name (string) 63 | // non-translated name is just key cast to string 64 | KeyTranslator.prototype.translateKey = function(key) { 65 | if (!this.keyToName) 66 | return new String(key); 67 | 68 | if (!this.keyToName[key]) 69 | return new String(key); 70 | 71 | return this.keyToName[key]; 72 | }; 73 | 74 | // helper class for paring buffer to JSON 75 | function MessageParser(keyTranslator) { 76 | this.keyTranslator = keyTranslator; 77 | } 78 | 79 | // type map 80 | MessageParser.prototype.TupleTypes = { 81 | BYTE_ARRAY: 0, 82 | CSTRING: 1, 83 | UINT: 2, 84 | INT: 3 85 | }; 86 | 87 | // buffer --> JSON 88 | MessageParser.prototype.parse = function(buffer) { 89 | var msg = { }; 90 | 91 | for (var i = 0; i < buffer.length; ) { 92 | var key = this.keyTranslator.translateKey(buffer.readUInt32LE(i)); 93 | var type = buffer.readUInt8(i + 4); 94 | var length = buffer.readUInt16LE(i + 5); 95 | 96 | var value; 97 | if (type == this.TupleTypes.BYTE_ARRAY) { 98 | value = []; 99 | for (var x = i+7; x < (i+length+7); ++x) 100 | value.push(buffer.readUInt8(x)); 101 | } 102 | else if (type == this.TupleTypes.CSTRING) { 103 | value = buffer.toString("utf8", i+7, i+length+7-1); 104 | } 105 | else if (type == this.TupleTypes.UINT) { 106 | if (length == 1) 107 | value = buffer.readUInt8(i+7); 108 | else if (length == 2) 109 | value = buffer.readUInt16LE(i+7); 110 | else if (length == 4) 111 | value = buffer.readUInt32LE(i+7); 112 | } 113 | else if (type == this.TupleTypes.INT) { 114 | if (length == 1) 115 | value = buffer.readInt8(i+7); 116 | else if (length == 2) 117 | value = buffer.readInt16LE(i+7); 118 | else if (length == 4) 119 | value = buffer.readInt32LE(i+7); 120 | } 121 | else { 122 | console.log("[ERROR] Corrupt Message"); 123 | throw "Corrupt Message"; 124 | } 125 | 126 | msg[key] = value; 127 | i += 7 + length; 128 | } 129 | 130 | return msg; 131 | }; 132 | 133 | MessageParser.prototype.serializeMsg = function(msg) { 134 | // compute size 135 | var size = 0; 136 | for (var k in msg) { 137 | if (msg.hasOwnProperty(k)) { 138 | size += 7; 139 | 140 | if (typeof(msg[k]) == "string") 141 | size += msg[k].length+1; 142 | else if (typeof(msg[k]) == "number") 143 | size += 4; // assume 32-bit 144 | else if (typeof(msg[k]) == "array") 145 | size += msg[k].length; 146 | else 147 | throw "Unable to serialize message"; 148 | } 149 | } 150 | 151 | // allocate buffer 152 | var buffer = new Buffer(size+2); 153 | 154 | // serialize 155 | var offset = 0; 156 | buffer.writeUInt16LE(size, offset); 157 | offset += 2; 158 | for (var k in msg) { 159 | if (msg.hasOwnProperty(k)) { 160 | // key 161 | buffer.writeUInt32LE(this.keyTranslator.translateName(k), offset); 162 | 163 | // type, length, and data 164 | var dataSize = 0 165 | if (typeof(msg[k]) == "string") { 166 | buffer.writeUInt8(this.TupleTypes.CSTRING, offset+4); 167 | dataSize = msg[k].length+1; 168 | buffer.writeUInt16LE(dataSize, offset+5); 169 | buffer.write(msg[k], offset+7, dataSize-1); 170 | buffer.writeUInt8(0, offset+7+dataSize-1); 171 | } 172 | else if (typeof(msg[k]) == "number") { 173 | buffer.writeUInt8(this.TupleTypes.INT, offset+4); // assume signed 174 | dataSize = 4; // assume 32-bit 175 | buffer.writeUInt16LE(dataSize, offset+5); 176 | buffer.writeInt32LE(msg[k], offset+7); 177 | } 178 | else if (typeof(msg[k]) == "array") { 179 | buffer.writeUInt8(this.TupleTypes.BYTE_ARRAY, offset+4); 180 | dataSize = msg[k].length; 181 | buffer.writeUInt16LE(dataSize, offset+5); 182 | for (var x = 0; x < dataSize; ++x) { 183 | if (typeof(msg[k]) !== "number") 184 | throw "Invalid Byte Array"; 185 | buffer.writeUInt8(msg[k][x], offset+7+x); 186 | } 187 | } 188 | 189 | offset += 7 + dataSize; 190 | } 191 | } 192 | 193 | return buffer; 194 | }; 195 | 196 | // parser to be used by server 197 | var msgParser = new MessageParser(new KeyTranslator("appinfo.json")); 198 | 199 | // the receiving server 200 | var server = net.createServer(function(c) { 201 | var States = { 202 | ReadingSize: 1, // expecting size 203 | ReadingData: 2 // expecting data 204 | }; 205 | 206 | var currentState = States.ReadingSize; 207 | var firstRead = true; // no handshake yet 208 | var bytesToRead; 209 | 210 | // will be called when there is some data to read 211 | var attemptRead = function(c) { 212 | if (currentState == States.ReadingSize) { 213 | // attempt to read 16-bit size 214 | var r = c.read(2); 215 | if (!r) // 2-bytes not available yet 216 | return false; 217 | 218 | bytesToRead = (new Buffer(r)).readUInt16LE(0); 219 | currentState = States.ReadingData; 220 | } 221 | else { 222 | // attempt to read actual data 223 | // if bytesToRead isn't available null is returned 224 | // we want to wait until the entire message is available 225 | var raw = c.read(bytesToRead); 226 | if (!raw) 227 | return false; 228 | 229 | var buffer = new Buffer(raw); 230 | currentState = States.ReadingSize; 231 | if (firstRead) { 232 | // handshake 233 | firstRead = false; 234 | if (buffer.toString() === "READY") { 235 | console.log("[INFO] Handshake Completed - ready event called") 236 | if (readyFunc) 237 | readyFunc({ ready: true, type: "ready" }); 238 | } 239 | else { 240 | console.log("[ERROR] Handshake Failed"); 241 | throw "Hanshake Failed"; 242 | } 243 | } 244 | else { 245 | // have whole message, so now parse and notify on appmessage event 246 | var msg = msgParser.parse(buffer); 247 | if (messageFunc) 248 | messageFunc({ type: "appmessage", payload: msg }); 249 | } 250 | } 251 | 252 | return true; 253 | }; 254 | 255 | console.log("[INFO] Server Connected"); 256 | 257 | // called when there is data to read 258 | c.on("readable", function() { 259 | // keep trying while there is data to read 260 | while (attemptRead(c)) { } 261 | }); 262 | }); 263 | 264 | // start the actual server 265 | server.listen(8321, function() { 266 | console.log("[INFO] Server Started"); 267 | }) 268 | 269 | // part of Pebble API 270 | module.exports.sendAppMessage = function(msg, fnAck, fnNack) { 271 | var buffer = msgParser.serializeMsg(msg); 272 | 273 | var client = net.connect({ port: 8322 }, function() { 274 | client.write(buffer); 275 | 276 | if (fnAck) 277 | fnAck(msg); 278 | }); 279 | }; 280 | 281 | // part of Pebble API 282 | module.exports.getAccountToken = function() { 283 | return "A1B2C3D4E5F6G7H8I9J0"; // obviously a dummy value 284 | }; 285 | 286 | // mock Geolocation API 287 | module.exports.geolocation = { 288 | watchPosition: function() { 289 | // do nothing 290 | }, 291 | getCurrentPosition: function(fnSuccess, fnFailure, options) { 292 | fnSuccess({ 293 | coords: { 294 | latitude: 40.75907, 295 | longitude: -73.98507 296 | } 297 | }); 298 | } 299 | }; 300 | -------------------------------------------------------------------------------- /simdata/windows/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/windows/SDL2.dll -------------------------------------------------------------------------------- /simdata/windows/SDL2_image.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/windows/SDL2_image.dll -------------------------------------------------------------------------------- /simdata/windows/SDL2_ttf.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/windows/SDL2_ttf.dll -------------------------------------------------------------------------------- /simdata/windows/libfreetype-6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/windows/libfreetype-6.dll -------------------------------------------------------------------------------- /simdata/windows/libpng16-16.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/windows/libpng16-16.dll -------------------------------------------------------------------------------- /simdata/windows/zlib1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/simdata/windows/zlib1.dll -------------------------------------------------------------------------------- /src/SDL_gfx/SDL_gfxBlitFunc.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SDL_gfxBlitFunc.h: custom blitters 4 | 5 | Copyright (C) 2001-2012 Andreas Schiffler 6 | 7 | This software is provided 'as-is', without any express or implied 8 | warranty. In no event will the authors be held liable for any damages 9 | arising from the use of this software. 10 | 11 | Permission is granted to anyone to use this software for any purpose, 12 | including commercial applications, and to alter it and redistribute it 13 | freely, subject to the following restrictions: 14 | 15 | 1. The origin of this software must not be misrepresented; you must not 16 | claim that you wrote the original software. If you use this software 17 | in a product, an acknowledgment in the product documentation would be 18 | appreciated but is not required. 19 | 20 | 2. Altered source versions must be plainly marked as such, and must not be 21 | misrepresented as being the original software. 22 | 23 | 3. This notice may not be removed or altered from any source 24 | distribution. 25 | 26 | Andreas Schiffler -- aschiffler at ferzkopp dot net 27 | 28 | */ 29 | 30 | #ifndef _SDL_gfxBlitFunc_h 31 | #define _SDL_gfxBlitFunc_h 32 | 33 | /* Set up for C function definitions, even when using C++ */ 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #include 39 | #include 40 | 41 | //Helco: Use the new headers 42 | #include 43 | #include 44 | 45 | 46 | extern const unsigned int GFX_ALPHA_ADJUST_ARRAY[256]; 47 | 48 | /* ---- Function Prototypes */ 49 | 50 | #ifdef _MSC_VER 51 | # if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT) 52 | # define SDL_GFXBLITFUNC_SCOPE __declspec(dllexport) 53 | # else 54 | # ifdef LIBSDL_GFX_DLL_IMPORT 55 | # define SDL_GFXBLITFUNC_SCOPE __declspec(dllimport) 56 | # endif 57 | # endif 58 | #endif 59 | #ifndef SDL_GFXBLITFUNC_SCOPE 60 | # define SDL_GFXBLITFUNC_SCOPE extern 61 | #endif 62 | 63 | 64 | SDL_GFXBLITFUNC_SCOPE int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); 65 | 66 | SDL_GFXBLITFUNC_SCOPE int SDL_gfxSetAlpha(SDL_Surface * src, Uint8 a); 67 | 68 | SDL_GFXBLITFUNC_SCOPE int SDL_gfxMultiplyAlpha(SDL_Surface * src, Uint8 a); 69 | 70 | /* -------- Macros */ 71 | 72 | /* Define SDL macros locally as a substitute for an #include "SDL_blit.h", */ 73 | /* which doesn't work since the include file doesn't get installed. */ 74 | 75 | /*! 76 | \brief The structure passed to the low level blit functions. 77 | */ 78 | typedef struct { 79 | Uint8 *s_pixels; 80 | int s_width; 81 | int s_height; 82 | int s_skip; 83 | Uint8 *d_pixels; 84 | int d_width; 85 | int d_height; 86 | int d_skip; 87 | void *aux_data; 88 | SDL_PixelFormat *src; 89 | Uint8 *table; 90 | SDL_PixelFormat *dst; 91 | } SDL_gfxBlitInfo; 92 | 93 | /*! 94 | \brief Unwrap RGBA values from a pixel using mask, shift and loss for surface. 95 | */ 96 | #define GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a) \ 97 | { \ 98 | r = ((pixel&fmt->Rmask)>>fmt->Rshift)<Rloss; \ 99 | g = ((pixel&fmt->Gmask)>>fmt->Gshift)<Gloss; \ 100 | b = ((pixel&fmt->Bmask)>>fmt->Bshift)<Bloss; \ 101 | a = ((pixel&fmt->Amask)>>fmt->Ashift)<Aloss; \ 102 | } 103 | 104 | /*! 105 | \brief Disassemble buffer pointer into a pixel and separate RGBA values. 106 | */ 107 | #define GFX_DISASSEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a) \ 108 | do { \ 109 | pixel = *((Uint32 *)(buf)); \ 110 | GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a); \ 111 | pixel &= ~fmt->Amask; \ 112 | } while(0) 113 | 114 | /*! 115 | \brief Wrap a pixel from RGBA values using mask, shift and loss for surface. 116 | */ 117 | #define GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a) \ 118 | { \ 119 | pixel = ((r>>fmt->Rloss)<Rshift)| \ 120 | ((g>>fmt->Gloss)<Gshift)| \ 121 | ((b>>fmt->Bloss)<Bshift)| \ 122 | ((a<Aloss)<Ashift); \ 123 | } 124 | 125 | /*! 126 | \brief Assemble pixel into buffer pointer from separate RGBA values. 127 | */ 128 | #define GFX_ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ 129 | { \ 130 | Uint32 pixel; \ 131 | \ 132 | GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ 133 | *((Uint32 *)(buf)) = pixel; \ 134 | } 135 | 136 | /*! 137 | \brief Blend the RGB values of two pixels based on a source alpha value. 138 | */ 139 | #define GFX_ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \ 140 | do { \ 141 | dR = (((sR-dR)*(A))/255)+dR; \ 142 | dG = (((sG-dG)*(A))/255)+dG; \ 143 | dB = (((sB-dB)*(A))/255)+dB; \ 144 | } while(0) 145 | 146 | /*! 147 | \brief 4-times unrolled DUFFs loop. 148 | 149 | This is a very useful loop for optimizing blitters. 150 | */ 151 | #define GFX_DUFFS_LOOP4(pixel_copy_increment, width) \ 152 | { int n = (width+3)/4; \ 153 | switch (width & 3) { \ 154 | case 0: do { pixel_copy_increment; \ 155 | case 3: pixel_copy_increment; \ 156 | case 2: pixel_copy_increment; \ 157 | case 1: pixel_copy_increment; \ 158 | } while ( --n > 0 ); \ 159 | } \ 160 | } 161 | 162 | 163 | 164 | /* Ends C function definitions when using C++ */ 165 | #ifdef __cplusplus 166 | } 167 | #endif 168 | 169 | #endif /* _SDL_gfxBlitFunc_h */ 170 | -------------------------------------------------------------------------------- /src/SDL_gfx/SDL_gfxPrimitives_font.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helco/PLocalSim/01c8a16d5ff31bc1d3b75a703cc80adfbc9fd221/src/SDL_gfx/SDL_gfxPrimitives_font.h -------------------------------------------------------------------------------- /src/SDL_gfx/SDL_rotozoom.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces 4 | 5 | Copyright (C) 2001-2012 Andreas Schiffler 6 | 7 | This software is provided 'as-is', without any express or implied 8 | warranty. In no event will the authors be held liable for any damages 9 | arising from the use of this software. 10 | 11 | Permission is granted to anyone to use this software for any purpose, 12 | including commercial applications, and to alter it and redistribute it 13 | freely, subject to the following restrictions: 14 | 15 | 1. The origin of this software must not be misrepresented; you must not 16 | claim that you wrote the original software. If you use this software 17 | in a product, an acknowledgment in the product documentation would be 18 | appreciated but is not required. 19 | 20 | 2. Altered source versions must be plainly marked as such, and must not be 21 | misrepresented as being the original software. 22 | 23 | 3. This notice may not be removed or altered from any source 24 | distribution. 25 | 26 | Andreas Schiffler -- aschiffler at ferzkopp dot net 27 | 28 | */ 29 | 30 | #ifndef _SDL_rotozoom_h 31 | #define _SDL_rotozoom_h 32 | 33 | #include 34 | 35 | /* Set up for C function definitions, even when using C++ */ 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | #ifndef M_PI 41 | #define M_PI 3.141592654 42 | #endif 43 | 44 | //Helco: Use the new headers 45 | #include 46 | 47 | /* ---- Defines */ 48 | 49 | /*! 50 | \brief Disable anti-aliasing (no smoothing). 51 | */ 52 | #define SMOOTHING_OFF 0 53 | 54 | /*! 55 | \brief Enable anti-aliasing (smoothing). 56 | */ 57 | #define SMOOTHING_ON 1 58 | 59 | /* ---- Function Prototypes */ 60 | 61 | #ifdef _MSC_VER 62 | # if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT) 63 | # define SDL_ROTOZOOM_SCOPE __declspec(dllexport) 64 | # else 65 | # ifdef LIBSDL_GFX_DLL_IMPORT 66 | # define SDL_ROTOZOOM_SCOPE __declspec(dllimport) 67 | # endif 68 | # endif 69 | #endif 70 | #ifndef SDL_ROTOZOOM_SCOPE 71 | # define SDL_ROTOZOOM_SCOPE extern 72 | #endif 73 | 74 | /* 75 | 76 | Rotozoom functions 77 | 78 | */ 79 | 80 | SDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth); 81 | 82 | SDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurfaceXY 83 | (SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth); 84 | 85 | 86 | SDL_ROTOZOOM_SCOPE void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, 87 | int *dstheight); 88 | 89 | SDL_ROTOZOOM_SCOPE void rotozoomSurfaceSizeXY 90 | (int width, int height, double angle, double zoomx, double zoomy, 91 | int *dstwidth, int *dstheight); 92 | 93 | /* 94 | 95 | Zooming functions 96 | 97 | */ 98 | 99 | SDL_ROTOZOOM_SCOPE SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth); 100 | 101 | SDL_ROTOZOOM_SCOPE void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight); 102 | 103 | /* 104 | 105 | Shrinking functions 106 | 107 | */ 108 | 109 | SDL_ROTOZOOM_SCOPE SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory); 110 | 111 | /* 112 | 113 | Specialized rotation functions 114 | 115 | */ 116 | 117 | SDL_ROTOZOOM_SCOPE SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns); 118 | 119 | /* Ends C function definitions when using C++ */ 120 | #ifdef __cplusplus 121 | } 122 | #endif 123 | 124 | #endif /* _SDL_rotozoom_h */ 125 | -------------------------------------------------------------------------------- /src/SDL_gfx/disclaimer.txt: -------------------------------------------------------------------------------- 1 | These source files are based of the SDL_gfx library written by Andreas Schiffler and 2 | originally stand under the license text you find in every source file. 3 | To be compatible with SDL2 (and still using surfaces instead of renderer/texture ) 4 | I modified following files: 5 | 6 | 1. SDL_gfxBlitFunc.c 7 | 2. SDL_rotozoom.c 8 | 3. SDL_gfxPrimitives.c 9 | 10 | All changes should have been marked with a comment starting with "Helco" 11 | To achieve a full compatibility this modified version of SDL_gfx stands under the same 12 | license as its base -------------------------------------------------------------------------------- /src/js_server/lib/localStorage.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var _ = require('lodash'); 3 | 4 | var storage_to_save = []; // used to store info for saving later 5 | 6 | // helper function to pull out all data keys (which happen to 7 | // be all strings) 8 | function getDataKeys(storage) { 9 | return _.filter(_.keys(storage), function(k) { 10 | return (typeof(storage[k]) === 'string'); 11 | }); 12 | } 13 | 14 | // Storage class 15 | // takes optional filename for backing store 16 | // if left blank storage will not persist 17 | var Storage = function(filename) { 18 | var that = this; 19 | 20 | // compute length on the fly because of direct property access 21 | Object.defineProperty(this, "length", { 22 | get: function() { 23 | return getDataKeys(this).length; 24 | }, 25 | set: function() { } // do nothing 26 | }); 27 | 28 | // load 29 | if (filename) { 30 | try { 31 | var raw = fs.readFileSync(filename); 32 | if (raw) 33 | _.defaults(this, JSON.parse(raw)); 34 | } 35 | catch(e) { 36 | // swallow error if can't read 37 | } 38 | 39 | // add to list to save 40 | storage_to_save.push({ file: filename, storage: this }); 41 | } 42 | }; 43 | 44 | Storage.prototype.setItem = function(key, value) { 45 | this[key.toString()] = value.toString(); 46 | }; 47 | 48 | Storage.prototype.getItem = function(key) { 49 | var skey = key.toString(); 50 | 51 | if (!this[skey]) 52 | return null; 53 | 54 | return this[skey]; 55 | }; 56 | 57 | Storage.prototype.removeItem = function(key) { 58 | var skey = key.toString(); 59 | 60 | if (!this[skey]) 61 | return; 62 | if (typeof(this[skey]) !== 'string') 63 | return; 64 | 65 | delete this[skey]; 66 | }; 67 | 68 | Storage.prototype.clear = function() { 69 | _.forEach(getDataKeys(this), function(k) { 70 | delete this[k]; 71 | }, this); 72 | }; 73 | 74 | Storage.prototype.key = function(n) { 75 | if (typeof(n) !== 'number') 76 | return null; 77 | 78 | if (n < 0) 79 | return null; 80 | 81 | var skeys = getDataKeys(this); 82 | if (n >= skeys.length) 83 | return null; 84 | 85 | return skeys[n]; 86 | }; 87 | 88 | function saveStorageItem(sitem) { 89 | // prepare data 90 | var dataKeys = getDataKeys(sitem.storage); 91 | var data = { }; 92 | _.forEach(dataKeys, function(k) { 93 | data[k] = sitem.storage.getItem(k); 94 | }); 95 | 96 | // actual write 97 | try { 98 | fs.writeFileSync(sitem.file, JSON.stringify(data)); 99 | } 100 | catch (e) { 101 | console.log("[ERROR] Error Saving localStorage (" + sitem.file + "): " + e); 102 | } 103 | } 104 | 105 | // function to force save 106 | // (meant to be used for testing) 107 | module.exports._forceSave = function(storage) { 108 | var sitem = _.where(storage_to_save, { 'storage': storage }); 109 | if (!sitem || !sitem.length) 110 | throw "Can't find Storage in storage_to_save list"; 111 | saveStorageItem(sitem[0]); 112 | }; 113 | 114 | // save on exit 115 | process.on('exit', function() { 116 | _.forEach(storage_to_save, saveStorageItem); 117 | }); 118 | 119 | // save on kill 120 | process.on('SIGTERM', function() { 121 | _.forEach(storage_to_save, saveStorageItem); 122 | process.exit(0); 123 | }); 124 | 125 | module.exports.Storage = Storage; -------------------------------------------------------------------------------- /src/js_server/server.js: -------------------------------------------------------------------------------- 1 | var net = require("net"); 2 | var fs = require("fs"); 3 | 4 | // event listener callbacks 5 | var readyFunc = null; 6 | var messageFunc = null; 7 | 8 | // part of Pebble API 9 | module.exports.addEventListener = function(event, fn) { 10 | if (typeof(fn) !== 'function') 11 | return; 12 | 13 | if (event === "ready") 14 | readyFunc = fn; 15 | else if (event == "appmessage") 16 | messageFunc = fn; 17 | else if (event == "webviewclosed") 18 | ; 19 | else 20 | throw "Invalid Event"; 21 | 22 | console.log("[INFO] Added event listener for: " + event); 23 | }; 24 | 25 | // helper class to translate keys to friendly name and vice versa 26 | function KeyTranslator(filename) { 27 | this.nameToKey = null; 28 | this.keyToName = null; 29 | 30 | // pull out friendly names from appKeys section of appinfo.json 31 | try { 32 | var contents = fs.readFileSync("appinfo.json"); 33 | contents = JSON.parse(contents); 34 | if (contents.appKeys) { 35 | this.nameToKey = contents.appKeys; 36 | this.keyToName = { }; 37 | for (var n in contents.appKeys) { 38 | if (contents.appKeys.hasOwnProperty(n)) { 39 | this.keyToName[contents.appKeys[n]] = n; 40 | } 41 | } 42 | } 43 | } 44 | catch(e) { 45 | // appinfo.json should be there but swallow error if it isnt 46 | console.log("[WARN] appinfo.json could not be read"); 47 | } 48 | } 49 | 50 | // name --> key (integer) 51 | KeyTranslator.prototype.translateName = function(name) { 52 | if (!this.nameToKey || (this.nameToKey[name]==undefined)) { 53 | var ikey = parseInt(name); 54 | if (isNaN(ikey)) 55 | throw "Invalid Key"; 56 | return ikey; 57 | } 58 | 59 | return this.nameToKey[name]; 60 | }; 61 | 62 | // key --> name (string) 63 | // non-translated name is just key cast to string 64 | KeyTranslator.prototype.translateKey = function(key) { 65 | if (!this.keyToName) 66 | return new String(key); 67 | 68 | if (!this.keyToName[key]) 69 | return new String(key); 70 | 71 | return this.keyToName[key]; 72 | }; 73 | 74 | // helper class for paring buffer to JSON 75 | function MessageParser(keyTranslator) { 76 | this.keyTranslator = keyTranslator; 77 | } 78 | 79 | // type map 80 | MessageParser.prototype.TupleTypes = { 81 | BYTE_ARRAY: 0, 82 | CSTRING: 1, 83 | UINT: 2, 84 | INT: 3 85 | }; 86 | 87 | // buffer --> JSON 88 | MessageParser.prototype.parse = function(buffer) { 89 | var msg = { }; 90 | 91 | for (var i = 0; i < buffer.length; ) { 92 | var key = this.keyTranslator.translateKey(buffer.readUInt32LE(i)); 93 | var type = buffer.readUInt8(i + 4); 94 | var length = buffer.readUInt16LE(i + 5); 95 | 96 | var value; 97 | if (type == this.TupleTypes.BYTE_ARRAY) { 98 | value = []; 99 | for (var x = i+7; x < (i+length+7); ++x) 100 | value.push(buffer.readUInt8(x)); 101 | } 102 | else if (type == this.TupleTypes.CSTRING) { 103 | value = buffer.toString("utf8", i+7, i+length+7-1); 104 | } 105 | else if (type == this.TupleTypes.UINT) { 106 | if (length == 1) 107 | value = buffer.readUInt8(i+7); 108 | else if (length == 2) 109 | value = buffer.readUInt16LE(i+7); 110 | else if (length == 4) 111 | value = buffer.readUInt32LE(i+7); 112 | } 113 | else if (type == this.TupleTypes.INT) { 114 | if (length == 1) 115 | value = buffer.readInt8(i+7); 116 | else if (length == 2) 117 | value = buffer.readInt16LE(i+7); 118 | else if (length == 4) 119 | value = buffer.readInt32LE(i+7); 120 | } 121 | else { 122 | console.log("[ERROR] Corrupt Message"); 123 | throw "Corrupt Message"; 124 | } 125 | 126 | msg[key] = value; 127 | i += 7 + length; 128 | } 129 | 130 | return msg; 131 | }; 132 | 133 | MessageParser.prototype.serializeMsg = function(msg) { 134 | // compute size 135 | var size = 0; 136 | for (var k in msg) { 137 | if (msg.hasOwnProperty(k)) { 138 | size += 7; 139 | 140 | if (typeof(msg[k]) == "string") 141 | size += msg[k].length+1; 142 | else if (typeof(msg[k]) == "number") 143 | size += 4; // assume 32-bit 144 | else if (typeof(msg[k]) == "array") 145 | size += msg[k].length; 146 | else 147 | throw "Unable to serialize message"; 148 | } 149 | } 150 | 151 | // allocate buffer 152 | var buffer = new Buffer(size+2); 153 | 154 | // serialize 155 | var offset = 0; 156 | buffer.writeUInt16LE(size, offset); 157 | offset += 2; 158 | for (var k in msg) { 159 | if (msg.hasOwnProperty(k)) { 160 | // key 161 | buffer.writeUInt32LE(this.keyTranslator.translateName(k), offset); 162 | 163 | // type, length, and data 164 | var dataSize = 0 165 | if (typeof(msg[k]) == "string") { 166 | buffer.writeUInt8(this.TupleTypes.CSTRING, offset+4); 167 | dataSize = msg[k].length+1; 168 | buffer.writeUInt16LE(dataSize, offset+5); 169 | buffer.write(msg[k], offset+7, dataSize-1); 170 | buffer.writeUInt8(0, offset+7+dataSize-1); 171 | } 172 | else if (typeof(msg[k]) == "number") { 173 | buffer.writeUInt8(this.TupleTypes.INT, offset+4); // assume signed 174 | dataSize = 4; // assume 32-bit 175 | buffer.writeUInt16LE(dataSize, offset+5); 176 | buffer.writeInt32LE(msg[k], offset+7); 177 | } 178 | else if (typeof(msg[k]) == "array") { 179 | buffer.writeUInt8(this.TupleTypes.BYTE_ARRAY, offset+4); 180 | dataSize = msg[k].length; 181 | buffer.writeUInt16LE(dataSize, offset+5); 182 | for (var x = 0; x < dataSize; ++x) { 183 | if (typeof(msg[k]) !== "number") 184 | throw "Invalid Byte Array"; 185 | buffer.writeUInt8(msg[k][x], offset+7+x); 186 | } 187 | } 188 | 189 | offset += 7 + dataSize; 190 | } 191 | } 192 | 193 | return buffer; 194 | }; 195 | 196 | // parser to be used by server 197 | var msgParser = new MessageParser(new KeyTranslator("appinfo.json")); 198 | 199 | // the receiving server 200 | var server = net.createServer(function(c) { 201 | var States = { 202 | ReadingSize: 1, // expecting size 203 | ReadingData: 2 // expecting data 204 | }; 205 | 206 | var currentState = States.ReadingSize; 207 | var firstRead = true; // no handshake yet 208 | var bytesToRead; 209 | 210 | // will be called when there is some data to read 211 | var attemptRead = function(c) { 212 | if (currentState == States.ReadingSize) { 213 | // attempt to read 16-bit size 214 | var r = c.read(2); 215 | if (!r) // 2-bytes not available yet 216 | return false; 217 | 218 | bytesToRead = (new Buffer(r)).readUInt16LE(0); 219 | currentState = States.ReadingData; 220 | } 221 | else { 222 | // attempt to read actual data 223 | // if bytesToRead isn't available null is returned 224 | // we want to wait until the entire message is available 225 | var raw = c.read(bytesToRead); 226 | if (!raw) 227 | return false; 228 | 229 | var buffer = new Buffer(raw); 230 | currentState = States.ReadingSize; 231 | if (firstRead) { 232 | // handshake 233 | firstRead = false; 234 | if (buffer.toString() === "READY") { 235 | console.log("[INFO] Handshake Completed - ready event called") 236 | if (readyFunc) 237 | readyFunc({ ready: true, type: "ready" }); 238 | } 239 | else { 240 | console.log("[ERROR] Handshake Failed"); 241 | throw "Hanshake Failed"; 242 | } 243 | } 244 | else { 245 | // have whole message, so now parse and notify on appmessage event 246 | var msg = msgParser.parse(buffer); 247 | if (messageFunc) 248 | messageFunc({ type: "appmessage", payload: msg }); 249 | } 250 | } 251 | 252 | return true; 253 | }; 254 | 255 | console.log("[INFO] Server Connected"); 256 | 257 | // called when there is data to read 258 | c.on("readable", function() { 259 | // keep trying while there is data to read 260 | while (attemptRead(c)) { } 261 | }); 262 | }); 263 | 264 | // start the actual server 265 | server.listen(8321, function() { 266 | console.log("[INFO] Server Started"); 267 | }) 268 | 269 | // part of Pebble API 270 | module.exports.sendAppMessage = function(msg, fnAck, fnNack) { 271 | var buffer = msgParser.serializeMsg(msg); 272 | 273 | var client = net.connect({ port: 8322 }, function() { 274 | client.write(buffer); 275 | 276 | if (fnAck) 277 | fnAck(msg); 278 | }); 279 | }; 280 | 281 | // part of Pebble API 282 | module.exports.getAccountToken = function() { 283 | return "A1B2C3D4E5F6G7H8I9J0"; // obviously a dummy value 284 | }; 285 | 286 | // mock Geolocation API 287 | module.exports.geolocation = { 288 | watchPosition: function() { 289 | // do nothing 290 | }, 291 | getCurrentPosition: function(fnSuccess, fnFailure, options) { 292 | fnSuccess({ 293 | coords: { 294 | latitude: 40.75907, 295 | longitude: -73.98507 296 | } 297 | }); 298 | } 299 | }; 300 | -------------------------------------------------------------------------------- /src/jsmn/jsmn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "jsmn.h" 4 | 5 | /** 6 | * Allocates a fresh unused token from the token pull. 7 | */ 8 | static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 9 | jsmntok_t *tokens, size_t num_tokens) { 10 | jsmntok_t *tok; 11 | if (parser->toknext >= num_tokens) { 12 | return NULL; 13 | } 14 | tok = &tokens[parser->toknext++]; 15 | tok->start = tok->end = -1; 16 | tok->size = 0; 17 | #ifdef JSMN_PARENT_LINKS 18 | tok->parent = -1; 19 | #endif 20 | return tok; 21 | } 22 | 23 | /** 24 | * Fills token type and boundaries. 25 | */ 26 | static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 27 | int start, int end) { 28 | token->type = type; 29 | token->start = start; 30 | token->end = end; 31 | token->size = 0; 32 | } 33 | 34 | /** 35 | * Fills next available token with JSON primitive. 36 | */ 37 | static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, 38 | jsmntok_t *tokens, size_t num_tokens) { 39 | jsmntok_t *token; 40 | int start; 41 | 42 | start = parser->pos; 43 | 44 | for (; js[parser->pos] != '\0'; parser->pos++) { 45 | switch (js[parser->pos]) { 46 | #ifndef JSMN_STRICT 47 | /* In strict mode primitive must be followed by "," or "}" or "]" */ 48 | case ':': 49 | #endif 50 | case '\t' : case '\r' : case '\n' : case ' ' : 51 | case ',' : case ']' : case '}' : 52 | goto found; 53 | } 54 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 55 | parser->pos = start; 56 | return JSMN_ERROR_INVAL; 57 | } 58 | } 59 | #ifdef JSMN_STRICT 60 | /* In strict mode primitive must be followed by a comma/object/array */ 61 | parser->pos = start; 62 | return JSMN_ERROR_PART; 63 | #endif 64 | 65 | found: 66 | token = jsmn_alloc_token(parser, tokens, num_tokens); 67 | if (token == NULL) { 68 | parser->pos = start; 69 | return JSMN_ERROR_NOMEM; 70 | } 71 | jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 72 | #ifdef JSMN_PARENT_LINKS 73 | token->parent = parser->toksuper; 74 | #endif 75 | parser->pos--; 76 | return JSMN_SUCCESS; 77 | } 78 | 79 | /** 80 | * Filsl next token with JSON string. 81 | */ 82 | static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, 83 | jsmntok_t *tokens, size_t num_tokens) { 84 | jsmntok_t *token; 85 | 86 | int start = parser->pos; 87 | 88 | parser->pos++; 89 | 90 | /* Skip starting quote */ 91 | for (; js[parser->pos] != '\0'; parser->pos++) { 92 | char c = js[parser->pos]; 93 | 94 | /* Quote: end of string */ 95 | if (c == '\"') { 96 | token = jsmn_alloc_token(parser, tokens, num_tokens); 97 | if (token == NULL) { 98 | parser->pos = start; 99 | return JSMN_ERROR_NOMEM; 100 | } 101 | jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 102 | #ifdef JSMN_PARENT_LINKS 103 | token->parent = parser->toksuper; 104 | #endif 105 | return JSMN_SUCCESS; 106 | } 107 | 108 | /* Backslash: Quoted symbol expected */ 109 | if (c == '\\') { 110 | parser->pos++; 111 | switch (js[parser->pos]) { 112 | /* Allowed escaped symbols */ 113 | case '\"': case '/' : case '\\' : case 'b' : 114 | case 'f' : case 'r' : case 'n' : case 't' : 115 | break; 116 | /* Allows escaped symbol \uXXXX */ 117 | case 'u': 118 | /* TODO */ 119 | break; 120 | /* Unexpected symbol */ 121 | default: 122 | parser->pos = start; 123 | return JSMN_ERROR_INVAL; 124 | } 125 | } 126 | } 127 | parser->pos = start; 128 | return JSMN_ERROR_PART; 129 | } 130 | 131 | /** 132 | * Parse JSON string and fill tokens. 133 | */ 134 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens, 135 | unsigned int num_tokens) { 136 | jsmnerr_t r; 137 | int i; 138 | jsmntok_t *token; 139 | 140 | for (; js[parser->pos] != '\0'; parser->pos++) { 141 | char c; 142 | jsmntype_t type; 143 | 144 | c = js[parser->pos]; 145 | switch (c) { 146 | case '{': case '[': 147 | token = jsmn_alloc_token(parser, tokens, num_tokens); 148 | if (token == NULL) 149 | return JSMN_ERROR_NOMEM; 150 | if (parser->toksuper != -1) { 151 | tokens[parser->toksuper].size++; 152 | #ifdef JSMN_PARENT_LINKS 153 | token->parent = parser->toksuper; 154 | #endif 155 | } 156 | token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 157 | token->start = parser->pos; 158 | parser->toksuper = parser->toknext - 1; 159 | break; 160 | case '}': case ']': 161 | type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 162 | #ifdef JSMN_PARENT_LINKS 163 | if (parser->toknext < 1) { 164 | return JSMN_ERROR_INVAL; 165 | } 166 | token = &tokens[parser->toknext - 1]; 167 | for (;;) { 168 | if (token->start != -1 && token->end == -1) { 169 | if (token->type != type) { 170 | return JSMN_ERROR_INVAL; 171 | } 172 | token->end = parser->pos + 1; 173 | parser->toksuper = token->parent; 174 | break; 175 | } 176 | if (token->parent == -1) { 177 | break; 178 | } 179 | token = &tokens[token->parent]; 180 | } 181 | #else 182 | for (i = parser->toknext - 1; i >= 0; i--) { 183 | token = &tokens[i]; 184 | if (token->start != -1 && token->end == -1) { 185 | if (token->type != type) { 186 | return JSMN_ERROR_INVAL; 187 | } 188 | parser->toksuper = -1; 189 | token->end = parser->pos + 1; 190 | break; 191 | } 192 | } 193 | /* Error if unmatched closing bracket */ 194 | if (i == -1) return JSMN_ERROR_INVAL; 195 | for (; i >= 0; i--) { 196 | token = &tokens[i]; 197 | if (token->start != -1 && token->end == -1) { 198 | parser->toksuper = i; 199 | break; 200 | } 201 | } 202 | #endif 203 | break; 204 | case '\"': 205 | r = jsmn_parse_string(parser, js, tokens, num_tokens); 206 | if (r < 0) return r; 207 | if (parser->toksuper != -1) 208 | tokens[parser->toksuper].size++; 209 | break; 210 | case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ': 211 | break; 212 | #ifdef JSMN_STRICT 213 | /* In strict mode primitives are: numbers and booleans */ 214 | case '-': case '0': case '1' : case '2': case '3' : case '4': 215 | case '5': case '6': case '7' : case '8': case '9': 216 | case 't': case 'f': case 'n' : 217 | #else 218 | /* In non-strict mode every unquoted value is a primitive */ 219 | default: 220 | #endif 221 | r = jsmn_parse_primitive(parser, js, tokens, num_tokens); 222 | if (r < 0) return r; 223 | if (parser->toksuper != -1) 224 | tokens[parser->toksuper].size++; 225 | break; 226 | 227 | #ifdef JSMN_STRICT 228 | /* Unexpected char in strict mode */ 229 | default: 230 | return JSMN_ERROR_INVAL; 231 | #endif 232 | 233 | } 234 | } 235 | 236 | for (i = parser->toknext - 1; i >= 0; i--) { 237 | /* Unmatched opened object or array */ 238 | if (tokens[i].start != -1 && tokens[i].end == -1) { 239 | return JSMN_ERROR_PART; 240 | } 241 | } 242 | 243 | return JSMN_SUCCESS; 244 | } 245 | 246 | /** 247 | * Creates a new parser based over a given buffer with an array of tokens 248 | * available. 249 | */ 250 | void jsmn_init(jsmn_parser *parser) { 251 | parser->pos = 0; 252 | parser->toknext = 0; 253 | parser->toksuper = -1; 254 | } 255 | -------------------------------------------------------------------------------- /src/jsmn/jsmn.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSMN_H_ 2 | #define __JSMN_H_ 3 | 4 | /** 5 | * JSON type identifier. Basic types are: 6 | * o Object 7 | * o Array 8 | * o String 9 | * o Other primitive: number, boolean (true/false) or null 10 | */ 11 | typedef enum { 12 | JSMN_PRIMITIVE = 0, 13 | JSMN_OBJECT = 1, 14 | JSMN_ARRAY = 2, 15 | JSMN_STRING = 3 16 | } jsmntype_t; 17 | 18 | typedef enum { 19 | /* Not enough tokens were provided */ 20 | JSMN_ERROR_NOMEM = -1, 21 | /* Invalid character inside JSON string */ 22 | JSMN_ERROR_INVAL = -2, 23 | /* The string is not a full JSON packet, more bytes expected */ 24 | JSMN_ERROR_PART = -3, 25 | /* Everything was fine */ 26 | JSMN_SUCCESS = 0 27 | } jsmnerr_t; 28 | 29 | /** 30 | * JSON token description. 31 | * @param type type (object, array, string etc.) 32 | * @param start start position in JSON data string 33 | * @param end end position in JSON data string 34 | */ 35 | typedef struct { 36 | jsmntype_t type; 37 | int start; 38 | int end; 39 | int size; 40 | #ifdef JSMN_PARENT_LINKS 41 | int parent; 42 | #endif 43 | } jsmntok_t; 44 | 45 | /** 46 | * JSON parser. Contains an array of token blocks available. Also stores 47 | * the string being parsed now and current position in that string 48 | */ 49 | typedef struct { 50 | unsigned int pos; /* offset in the JSON string */ 51 | int toknext; /* next token to allocate */ 52 | int toksuper; /* superior token node, e.g parent object or array */ 53 | } jsmn_parser; 54 | 55 | /** 56 | * Create JSON parser over an array of tokens 57 | */ 58 | void jsmn_init(jsmn_parser *parser); 59 | 60 | /** 61 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 62 | * a single JSON object. 63 | */ 64 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, 65 | jsmntok_t *tokens, unsigned int num_tokens); 66 | 67 | #endif /* __JSMN_H_ */ 68 | -------------------------------------------------------------------------------- /src/local/accel_tap.c: -------------------------------------------------------------------------------- 1 | #include "globals.h" 2 | 3 | // 4 | // This file implements the accel_tap_service part of AccelerometerService 5 | // 6 | // Thrust can be simulated in X/Y/Z axis with +/- direction 7 | // 8 | 9 | static AccelTapHandler tap_handler = NULL; 10 | static AccelAxisType tap_axis = ACCEL_AXIS_X; 11 | static int32_t tap_direction = 0; 12 | static bool tap_notify = false; 13 | 14 | // simulator access 15 | 16 | void accel_do_tap_on_axis(AccelAxisType axis, int32_t direction) { 17 | tap_axis = axis; 18 | if(direction >= 1) { 19 | tap_direction = 1; 20 | } 21 | else { 22 | if(direction <= -1) { 23 | tap_direction = -1; 24 | } 25 | else { 26 | tap_direction = 0; 27 | } 28 | } 29 | tap_notify = true; 30 | } 31 | 32 | // pebble API part 33 | 34 | void accel_tap_service_subscribe(AccelTapHandler handler) { 35 | tap_handler = handler; 36 | } 37 | 38 | void accel_tap_service_unsubscribe(void) { 39 | tap_handler = NULL; 40 | tap_notify = false; 41 | } 42 | 43 | void service_accel_tap() { 44 | if(tap_notify && tap_handler != NULL) { 45 | tap_handler(tap_axis, tap_direction); 46 | tap_axis = ACCEL_AXIS_X; 47 | tap_direction = 0; 48 | tap_notify = false; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/local/actionbar.c: -------------------------------------------------------------------------------- 1 | #include "globals.h" 2 | 3 | #define ACTION_BAR_SPACING 3 4 | #define ACTION_BAR_LAYER_GET Layer* action_bar_layer=(Layer*)l 5 | #define ACTION_BAR_GET ACTION_BAR_LAYER_GET;ActionBarLayerData* action_bar=((ActionBarLayerData*)layer_get_data(action_bar_layer)) 6 | 7 | void action_bar_click_config_provider (void* context); 8 | void action_bar_click_handler_up (ClickRecognizerRef recognizer,void* context); 9 | void action_bar_click_handler_down (ClickRecognizerRef recognizer,void* context); 10 | void action_bar_update_handler (Layer* me,GContext* ctx); 11 | 12 | ActionBarLayer* action_bar_layer_create(void) { 13 | Layer* layer=layer_create_with_data(GRect(0,0,PBL_SCREEN_WIDTH,PBL_SCREEN_HEIGHT),sizeof(ActionBarLayerData)); 14 | ActionBarLayerData* action_bar=(ActionBarLayerData*)layer_get_data(layer); 15 | layer_set_update_proc (layer,action_bar_update_handler); 16 | action_bar->icons[0]=0; 17 | action_bar->icons[1]=0; 18 | action_bar->icons[2]=0; 19 | action_bar->context=0; 20 | action_bar->click_config_provider=0; 21 | action_bar->is_highlighted=0; 22 | action_bar->background_color=GColorBlack; 23 | return (ActionBarLayer*)layer; 24 | } 25 | 26 | void action_bar_layer_destroy (ActionBarLayer* layer) { 27 | if (layer) 28 | layer_destroy((Layer*)layer); 29 | } 30 | 31 | void action_bar_layer_set_context(ActionBarLayer *l, void *context) { 32 | ACTION_BAR_GET; 33 | action_bar->context=context; 34 | } 35 | 36 | void action_bar_layer_set_click_config_provider(ActionBarLayer *l, ClickConfigProvider click_config_provider) { 37 | ACTION_BAR_GET; 38 | action_bar->click_config_provider=click_config_provider; 39 | if (click_config_provider!=0 && //there IS a config provider 40 | action_bar_layer->window!=0 && //the action bar is added to a window 41 | window_stack_get_top_window()==action_bar_layer->window) //this window is currently visible 42 | click_config_provider (action_bar->context); 43 | } 44 | 45 | void action_bar_layer_set_icon(ActionBarLayer *l, ButtonId button_id, const GBitmap *icon) { 46 | ACTION_BAR_GET; 47 | bool hasSet=true; 48 | switch (button_id) { 49 | case(BUTTON_ID_UP):{action_bar->icons[0]=icon;}break; 50 | case(BUTTON_ID_SELECT):{action_bar->icons[1]=icon;}break; 51 | case(BUTTON_ID_DOWN):{action_bar->icons[2]=icon;}break; 52 | default:{hasSet=false;}break; 53 | } 54 | if (hasSet && //button_id is valid 55 | action_bar->click_config_provider!=0 && //there is a click config provider 56 | action_bar_layer->window!=0 && //the action bar is added to a window 57 | window_stack_get_top_window()==action_bar_layer->window) //this window is currently visible 58 | action_bar->click_config_provider (action_bar->context); 59 | } 60 | 61 | void action_bar_layer_clear_icon(ActionBarLayer *l, ButtonId button_id) { 62 | action_bar_layer_set_icon (l,button_id,0); 63 | } 64 | 65 | void action_bar_layer_set_background_color(ActionBarLayer *l, GColor background_color) { 66 | ACTION_BAR_GET; 67 | action_bar->background_color=background_color; 68 | layer_mark_dirty (action_bar_layer); 69 | } 70 | 71 | void action_bar_layer_add_to_window(ActionBarLayer *l, struct Window *window) { 72 | ACTION_BAR_LAYER_GET; 73 | GRect p=window->layer->frame; 74 | layer_insert_below_sibling(action_bar_layer,window->layer); 75 | layer_set_frame (action_bar_layer,GRect(p.size.w-ACTION_BAR_WIDTH, 76 | ACTION_BAR_SPACING, 77 | ACTION_BAR_WIDTH, 78 | p.size.h-2*ACTION_BAR_SPACING)); 79 | window_set_click_config_provider_with_context (window,action_bar_click_config_provider,l); 80 | //action_bar_layer->window=window; //is already set in layer_insert_below_sibling 81 | } 82 | 83 | void action_bar_layer_remove_from_window(ActionBarLayer *l) { 84 | ACTION_BAR_GET; 85 | if (action_bar_layer->window!=0) { 86 | Layer* cursor=action_bar_layer->window->layer; 87 | while (cursor->next_sibling!=0) { 88 | if (cursor->next_sibling==((Layer*)action_bar)) { 89 | cursor->next_sibling=action_bar_layer->next_sibling; 90 | break; 91 | } 92 | cursor=cursor->next_sibling; 93 | } 94 | if (cursor->next_sibling==0) 95 | return; 96 | window_set_click_config_provider_with_context(action_bar_layer->window,0,0); 97 | if (window_stack_get_top_window()==action_bar_layer->window) { 98 | ClickConfig** clickConfig=getClickConfig (); 99 | int i; 100 | for (i=BUTTON_ID_UP;i<=BUTTON_ID_DOWN;i++) { 101 | if (clickConfig[i]->raw.up_handler==action_bar_click_handler_up) 102 | clickConfig[i]->raw.up_handler=0; 103 | if (clickConfig[i]->raw.down_handler==action_bar_click_handler_down) 104 | clickConfig[i]->raw.down_handler=0; 105 | } 106 | } 107 | action_bar_layer->window=0; 108 | } 109 | } 110 | 111 | void action_bar_click_config_provider (void* l) { 112 | ACTION_BAR_GET; 113 | for (ButtonId id=BUTTON_ID_UP;id<=BUTTON_ID_DOWN;id++) 114 | window_raw_click_subscribe(BUTTON_ID_UP,action_bar_click_handler_down,action_bar_click_handler_up,l); 115 | if (action_bar->click_config_provider) 116 | action_bar->click_config_provider(action_bar->context); 117 | } 118 | 119 | void action_bar_click_handler_up (ClickRecognizerRef rec,void* l) { 120 | ACTION_BAR_GET; 121 | uint16_t mask; 122 | switch (click_recognizer_get_button_id (rec)) 123 | { 124 | case(BUTTON_ID_UP):{mask=0;}break; 125 | case(BUTTON_ID_SELECT):{mask=1;}break; 126 | case(BUTTON_ID_DOWN):{mask=2;}break; 127 | default:{return;}break; 128 | } 129 | mask=(1<is_highlighted&=mask; 131 | layer_mark_dirty(action_bar_layer); 132 | } 133 | 134 | void action_bar_click_handler_down (ClickRecognizerRef rec,void* l) { 135 | ACTION_BAR_GET; 136 | uint16_t mask; 137 | switch (click_recognizer_get_button_id (rec)) 138 | { 139 | case(BUTTON_ID_UP):{mask=0;}break; 140 | case(BUTTON_ID_SELECT):{mask=1;}break; 141 | case(BUTTON_ID_DOWN):{mask=2;}break; 142 | default:{return;}break; 143 | } 144 | action_bar->is_highlighted|=1<background_color); 154 | graphics_fill_rect (ctx,GRect(0,0,l->frame.size.w+3,l->frame.size.h),3,0); 155 | if (bar->icons[0]!=0) { 156 | if (bar->is_highlighted&(1<<0)) 157 | compOp=GCompOpAssignInverted; 158 | else 159 | compOp=GCompOpAssign; 160 | graphics_context_set_compositing_mode(ctx,compOp); 161 | graphics_draw_bitmap_in_rect (ctx,bar->icons[0],GRect(11-bar->icons[0]->bounds.size.w/2,20+11-bar->icons[0]->bounds.size.h,bar->icons[0]->bounds.size.w,bar->icons[0]->bounds.size.h)); 162 | } 163 | if (bar->icons[1]!=0) { 164 | if (bar->is_highlighted&(1<<1)) 165 | compOp=GCompOpAssignInverted; 166 | else 167 | compOp=GCompOpAssign; 168 | graphics_context_set_compositing_mode(ctx,compOp); 169 | graphics_draw_bitmap_in_rect (ctx,bar->icons[1],GRect(11-bar->icons[1]->bounds.size.w/2,l->frame.size.h/2-bar->icons[1]->bounds.size.h/2,bar->icons[1]->bounds.size.w,bar->icons[1]->bounds.size.h)); 170 | } 171 | if (bar->icons[2]!=0) { 172 | if (bar->is_highlighted&(1<<2)) 173 | compOp=GCompOpAssignInverted; 174 | else 175 | compOp=GCompOpAssign; 176 | graphics_context_set_compositing_mode(ctx,compOp); 177 | graphics_draw_bitmap_in_rect (ctx,bar->icons[2],GRect(11-bar->icons[2]->bounds.size.w/2,l->frame.size.h-20-11-bar->icons[2]->bounds.size.h,bar->icons[2]->bounds.size.w,bar->icons[2]->bounds.size.h)); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/local/animation.c: -------------------------------------------------------------------------------- 1 | #include "globals.h" 2 | 3 | static Animation* firstScheduledAnimation=0; 4 | 5 | struct Animation* animation_create() { 6 | Animation* animation=(Animation*)malloc(sizeof(Animation)); 7 | if (!animation) { 8 | printf ("[ERROR] Memory allocation failed!\n"); 9 | return 0; 10 | } 11 | animation->list_node.next=0; 12 | animation->list_node.prev=0; 13 | animation->abs_start_time_ms=0; 14 | animation->is_completed=true; 15 | //SDK defaults 16 | animation->duration_ms=250; 17 | animation->curve= AnimationCurveEaseInOut; 18 | animation->delay_ms=0; 19 | animation->handlers.started=0; 20 | animation->handlers.stopped=0; 21 | animation->context=0; 22 | animation->implementation=0; 23 | return animation; 24 | } 25 | 26 | void animation_destroy (struct Animation* animation) { 27 | if (animation_is_scheduled(animation)) 28 | animation_unschedule(animation); 29 | if (animation) 30 | free(animation); 31 | } 32 | 33 | void animation_set_delay(struct Animation *animation, uint32_t delay_ms) { 34 | animation->delay_ms=delay_ms; 35 | } 36 | 37 | void animation_set_duration(struct Animation *animation, uint32_t duration_ms) { 38 | animation->duration_ms=duration_ms; 39 | } 40 | 41 | void animation_set_curve(struct Animation *animation, AnimationCurve curve) { 42 | animation->curve=curve; 43 | } 44 | 45 | void animation_set_handlers(struct Animation *animation, AnimationHandlers callbacks, void *context) { 46 | animation->handlers=callbacks; 47 | animation->context=context; 48 | } 49 | 50 | void animation_set_implementation(struct Animation *animation, const AnimationImplementation *implementation) { 51 | animation->implementation=implementation; 52 | } 53 | 54 | void *animation_get_context(struct Animation *animation) { 55 | return animation->context; 56 | } 57 | 58 | void animation_schedule(struct Animation *animation) { 59 | if (animation->implementation==0) 60 | return; 61 | if (animation_is_scheduled(animation)) 62 | animation_unschedule(animation); 63 | animation->is_completed=true; //Yes this is meant to be true! That is how the engine determines if a animation is in "delay" state 64 | animation->abs_start_time_ms=SDL_GetTicks(); 65 | animation->list_node.next=(ListNode*)firstScheduledAnimation; 66 | animation->list_node.prev=0; 67 | if (firstScheduledAnimation!=0) 68 | firstScheduledAnimation->list_node.prev=(ListNode*)animation; 69 | firstScheduledAnimation=animation; 70 | if (animation->implementation->setup!=0) 71 | animation->implementation->setup (animation); 72 | } 73 | 74 | void animation_unschedule(struct Animation *animation) { 75 | if (animation->implementation==0) 76 | return; 77 | animation->is_completed=true; 78 | animation->abs_start_time_ms=0; 79 | if (animation==firstScheduledAnimation) { 80 | firstScheduledAnimation=(Animation*)animation->list_node.next; 81 | if (firstScheduledAnimation!=0) 82 | firstScheduledAnimation->list_node.prev=0; 83 | } 84 | else { 85 | animation->list_node.prev->next=animation->list_node.next; 86 | if (animation->list_node.next!=0) 87 | animation->list_node.next->prev=animation->list_node.prev; 88 | } 89 | animation->list_node.next=0; 90 | animation->list_node.prev=0; 91 | if (animation->handlers.stopped!=0) 92 | animation->handlers.stopped(animation,animation->is_completed,animation->context); 93 | if (animation->implementation->teardown!=0) 94 | animation->implementation->teardown(animation); 95 | } 96 | 97 | void animation_unschedule_all(void) { 98 | while (firstScheduledAnimation!=0) 99 | animation_unschedule(firstScheduledAnimation); 100 | } 101 | 102 | bool animation_is_scheduled(struct Animation *animation) { 103 | Animation* cursor=firstScheduledAnimation; 104 | while (cursor!=0) { 105 | if (cursor==animation) 106 | return true; 107 | cursor=(Animation*)cursor->list_node.next; 108 | } 109 | return false; 110 | } 111 | 112 | void service_animations () { 113 | Animation* cursor=firstScheduledAnimation,* tempCursor; 114 | bool isDirty=false; 115 | uint32_t time=0; 116 | while (cursor!=0) { 117 | if (cursor->is_completed) { //"delay" state 118 | if (SDL_GetTicks()-cursor->abs_start_time_ms>=cursor->delay_ms) { 119 | cursor->abs_start_time_ms=SDL_GetTicks(); 120 | cursor->is_completed=false; 121 | if (cursor->handlers.started!=0) 122 | cursor->handlers.started(cursor,cursor->context); 123 | } 124 | } 125 | else { 126 | if (cursor->duration_ms==ANIMATION_DURATION_INFINITE) 127 | time=ANIMATION_DURATION_INFINITE; 128 | else if (SDL_GetTicks()-cursor->abs_start_time_ms>=cursor->duration_ms) { 129 | //the simulator runs on 60 fps. to ensure the maximal value is reached, this has to be done 130 | cursor->implementation->update (cursor,ANIMATION_NORMALIZED_MAX); 131 | 132 | isDirty=true; 133 | cursor->is_completed=true; 134 | tempCursor=cursor; 135 | cursor=(Animation*)cursor->list_node.next; 136 | animation_unschedule(tempCursor); 137 | continue; 138 | } 139 | else 140 | time=(ANIMATION_NORMALIZED_MIN + (((ANIMATION_NORMALIZED_MAX - ANIMATION_NORMALIZED_MIN) * (SDL_GetTicks()-cursor->abs_start_time_ms)) / cursor->duration_ms)); 141 | cursor->implementation->update (cursor,time); 142 | isDirty=true; 143 | } 144 | cursor=(Animation*)cursor->list_node.next; 145 | } 146 | if (isDirty==true) 147 | markDirty (true); 148 | } 149 | 150 | struct PropertyAnimation* property_animation_create(const struct PropertyAnimationImplementation* implementation,void* subject,void* from_value,void* to_value) 151 | { 152 | PropertyAnimation* animation=(PropertyAnimation*)malloc(sizeof(PropertyAnimation)); 153 | if (!animation) { 154 | printf ("[ERROR] Memory allocation failed!\n"); 155 | return 0; 156 | } 157 | memset(animation, 0, sizeof(PropertyAnimation)); 158 | animation->animation.implementation=(AnimationImplementation*)implementation; 159 | animation->subject=subject; 160 | if (implementation->base.update==(AnimationUpdateImplementation)property_animation_update_int16) { 161 | if (from_value==0) 162 | animation->values.from.int16=implementation->accessors.getter.int16 (subject); 163 | else 164 | animation->values.from.int16=*(int16_t*)from_value; 165 | if (to_value==0) 166 | animation->values.to.int16=implementation->accessors.getter.int16 (subject); 167 | else 168 | animation->values.to.int16=*(int16_t*)to_value; 169 | } 170 | else if (implementation->base.update==(AnimationUpdateImplementation)property_animation_update_gpoint) { 171 | if (from_value==0) 172 | animation->values.from.gpoint=implementation->accessors.getter.gpoint (subject); 173 | else 174 | animation->values.from.gpoint=*(GPoint*)from_value; 175 | if (to_value==0) 176 | animation->values.to.gpoint=implementation->accessors.getter.gpoint (subject); 177 | else 178 | animation->values.to.gpoint=*(GPoint*)to_value; 179 | } 180 | else if (implementation->base.update==(AnimationUpdateImplementation)property_animation_update_grect) { 181 | if (from_value==0) 182 | animation->values.from.grect=implementation->accessors.getter.grect (subject); 183 | else 184 | animation->values.from.grect=*(GRect*)from_value; 185 | if (to_value==0) 186 | animation->values.to.grect=implementation->accessors.getter.grect (subject); 187 | else 188 | animation->values.to.grect=*(GRect*)to_value; 189 | } 190 | else 191 | printf ("[WARN] Invalid property animation implementation!\n"); 192 | return animation; 193 | } 194 | 195 | void property_animation_destroy (struct PropertyAnimation* animation) { 196 | if (animation_is_scheduled((Animation*)animation)) 197 | animation_unschedule((Animation*)animation); 198 | if (animation) 199 | free(animation); 200 | } 201 | 202 | #define PROPERTY_ANIMATION_INT16_VALUE(from,to,time) from+(int16_t)((to-from)*((float)time/ANIMATION_NORMALIZED_MAX)); 203 | 204 | void property_animation_update_int16 (PropertyAnimation* animation,const uint32_t time) 205 | { 206 | int16_t value=PROPERTY_ANIMATION_INT16_VALUE(animation->values.from.int16,animation->values.to.int16,time); 207 | PropertyAnimationImplementation* implementation=(PropertyAnimationImplementation*)animation->animation.implementation; 208 | implementation->accessors.setter.int16(animation->subject,value); 209 | } 210 | 211 | void property_animation_update_gpoint (PropertyAnimation* animation,const uint32_t time) 212 | { 213 | GPoint value; 214 | PropertyAnimationImplementation* implementation=(PropertyAnimationImplementation*)animation->animation.implementation; 215 | value.x=PROPERTY_ANIMATION_INT16_VALUE(animation->values.from.gpoint.x,animation->values.to.gpoint.x,time); 216 | value.y=PROPERTY_ANIMATION_INT16_VALUE(animation->values.from.gpoint.y,animation->values.to.gpoint.y,time); 217 | implementation->accessors.setter.gpoint(animation->subject,value); 218 | } 219 | 220 | void property_animation_update_grect (PropertyAnimation* animation,const uint32_t time) 221 | { 222 | GRect value; 223 | PropertyAnimationImplementation* implementation=(PropertyAnimationImplementation*)animation->animation.implementation; 224 | value.origin.x=PROPERTY_ANIMATION_INT16_VALUE(animation->values.from.grect.origin.x,animation->values.to.grect.origin.x,time); 225 | value.origin.y=PROPERTY_ANIMATION_INT16_VALUE(animation->values.from.grect.origin.y,animation->values.to.grect.origin.y,time); 226 | value.size.w=PROPERTY_ANIMATION_INT16_VALUE(animation->values.from.grect.size.w,animation->values.to.grect.size.w,time); 227 | value.size.h=PROPERTY_ANIMATION_INT16_VALUE(animation->values.from.grect.size.h,animation->values.to.grect.size.h,time); 228 | implementation->accessors.setter.grect(animation->subject,value); 229 | } 230 | 231 | GRectReturn layerFrameGetter (void* subject) 232 | { 233 | return ((Layer*)subject)->frame; 234 | } 235 | 236 | void layerFrameSetter (void* subject,GRect rect) 237 | { 238 | ((Layer*)subject)->frame=rect; 239 | layer_mark_dirty((Layer*)subject); 240 | } 241 | 242 | static PropertyAnimationImplementation layer_property_animation_implementation={ 243 | .base={ 244 | .update=(AnimationUpdateImplementation)property_animation_update_grect 245 | }, 246 | .accessors={ 247 | .getter={ .grect=layerFrameGetter}, 248 | .setter={ .grect=layerFrameSetter} 249 | } 250 | }; 251 | 252 | PropertyAnimation* property_animation_create_layer_frame (Layer* layer,GRect* from,GRect* to) 253 | { 254 | return property_animation_create (&layer_property_animation_implementation,layer,from,to); 255 | } 256 | -------------------------------------------------------------------------------- /src/local/app_sync.c: -------------------------------------------------------------------------------- 1 | #ifndef WIN32 2 | #include "globals.h" 3 | #include 4 | 5 | struct AppSyncList { 6 | struct AppSync* s; 7 | struct AppSyncList* next; 8 | }; 9 | static struct AppSyncList* g_pAppSyncList = NULL; 10 | pthread_mutex_t g_mxAppSyncList = PTHREAD_MUTEX_INITIALIZER; 11 | 12 | void app_sync_init(struct AppSync *s, 13 | uint8_t *buffer, 14 | const uint16_t buffer_size, 15 | const Tuplet * const keys_and_initial_values, 16 | const uint8_t count, 17 | AppSyncTupleChangedCallback tuple_changed_callback, 18 | AppSyncErrorCallback error_callback, 19 | void *context) { 20 | 21 | uint32_t final_buffer_size = buffer_size; 22 | if (dict_serialize_tuplets_to_buffer(keys_and_initial_values, count, buffer, &final_buffer_size) != DICT_OK) 23 | return; 24 | 25 | s->buffer = buffer; 26 | s->buffer_size = buffer_size; 27 | 28 | if (dict_write_begin(&s->current_iter, buffer, final_buffer_size) != DICT_OK) 29 | return; 30 | 31 | s->callback.context = context; 32 | s->callback.error = error_callback; 33 | s->callback.value_changed = tuple_changed_callback; 34 | 35 | // insert into list of regiested AppSync 36 | struct AppSyncList* pNode = (struct AppSyncList*) malloc(sizeof(struct AppSyncList)); 37 | pthread_mutex_lock(&g_mxAppSyncList); 38 | pNode->s = s; 39 | pNode->next = g_pAppSyncList; 40 | g_pAppSyncList = pNode; 41 | pthread_mutex_unlock(&g_mxAppSyncList); 42 | 43 | // send to client 44 | DictionaryIterator* iter; 45 | app_message_outbox_begin(&iter); 46 | for (int i = 0; i < count; ++i) { 47 | dict_write_tuplet(iter, &(keys_and_initial_values[i])); 48 | } 49 | dict_write_end(iter); 50 | app_message_outbox_send(); 51 | 52 | // notify 53 | Tuple* p = dict_read_first(&s->current_iter); 54 | while (p) { 55 | tuple_changed_callback(p->key, p, NULL, context); 56 | 57 | p = dict_read_next(&s->current_iter); 58 | } 59 | } 60 | 61 | void app_sync_deinit(struct AppSync *s) { 62 | pthread_mutex_lock(&g_mxAppSyncList); 63 | if (!g_pAppSyncList) 64 | return; 65 | 66 | if (g_pAppSyncList->s == s) { 67 | struct AppSyncList* next = g_pAppSyncList->next; 68 | free(g_pAppSyncList); 69 | g_pAppSyncList = next; 70 | } 71 | else { 72 | struct AppSyncList* prev = g_pAppSyncList; 73 | struct AppSyncList* curr = g_pAppSyncList->next; 74 | while (curr) { 75 | if (curr->s == s) { 76 | prev->next = curr->next; 77 | free(curr); 78 | break; 79 | } 80 | curr = curr->next; 81 | } 82 | } 83 | pthread_mutex_unlock(&g_mxAppSyncList); 84 | 85 | } 86 | 87 | AppMessageResult app_sync_set(struct AppSync *s, 88 | const Tuplet * const keys_and_values_to_update, 89 | const uint8_t count) { 90 | 91 | // update state on this side 92 | uint32_t in_size = dict_calc_buffer_size_from_tuplets(keys_and_values_to_update, count); 93 | uint8_t* buffer = (uint8_t*) malloc(in_size); 94 | DictionaryIterator iter; 95 | if (dict_serialize_tuplets_to_buffer_with_iter(&iter, keys_and_values_to_update, count, buffer, &in_size) != DICT_OK) 96 | return APP_MSG_BUFFER_OVERFLOW; 97 | 98 | uint32_t size = s->buffer_size; 99 | dict_merge(&(s->current_iter), &size, &iter, true, s->callback.value_changed, s->callback.context); 100 | 101 | free(buffer); 102 | 103 | // prepare data & send 104 | DictionaryIterator* iter_out; 105 | app_message_outbox_begin(&iter_out); 106 | uint32_t out_size = iter_out->end - (void*)iter_out->dictionary; 107 | if (dict_serialize_tuplets_to_buffer_with_iter(iter_out, keys_and_values_to_update, count, (uint8_t*)iter_out->dictionary, &out_size) != DICT_OK) 108 | return APP_MSG_BUFFER_OVERFLOW; 109 | return app_message_outbox_send(); 110 | } 111 | 112 | const Tuple * app_sync_get(const struct AppSync *s, const uint32_t key) { 113 | return dict_find(&(s->current_iter), key); 114 | } 115 | 116 | void service_app_sync(DictionaryIterator* iter) { 117 | pthread_mutex_lock(&g_mxAppSyncList); 118 | struct AppSyncList* pAS = g_pAppSyncList; 119 | while (pAS) { 120 | uint32_t size = pAS->s->buffer_size; 121 | dict_merge(&(pAS->s->current_iter), &size, iter, true, pAS->s->callback.value_changed, pAS->s->callback.context); 122 | 123 | pAS = pAS->next; 124 | } 125 | 126 | pthread_mutex_unlock(&g_mxAppSyncList); 127 | } 128 | #endif 129 | -------------------------------------------------------------------------------- /src/local/battery.c: -------------------------------------------------------------------------------- 1 | #include "globals.h" 2 | 3 | // 4 | // This file implements the BatteryStateService 5 | // 6 | // The battery acts like a real one would with this semantics: 7 | // 8 | // .charge_percent | .is_charging | .is_plugged | 9 | // 10 ... 90 | false | false | 10 | // <90 | true | true | 11 | // 90 | false | true | 12 | // 13 | // Basically if "plugged in" is_charging will be true unless we reach 90%. 14 | // In all other cases it will be false. 15 | // 16 | 17 | static BatteryChargeState battery_state = { 18 | .charge_percent = 90, 19 | .is_charging = false, 20 | .is_plugged = false 21 | }; 22 | 23 | static BatteryStateHandler battery_callback = NULL; 24 | static bool battery_notify = false; 25 | 26 | // simulator access 27 | // note that the SDK up to the current beta3 only reports 10-90, never 100 or 0 28 | 29 | uint8_t battery_charge_increase(void) { 30 | if(battery_state.charge_percent < 90) { 31 | battery_state.charge_percent += 10; 32 | battery_notify = true; 33 | } 34 | else { 35 | battery_state.is_charging = false; 36 | } 37 | return battery_state.charge_percent; 38 | } 39 | 40 | uint8_t battery_charge_decrease(void) { 41 | if(battery_state.charge_percent > 10) { 42 | battery_state.charge_percent -= 10; 43 | battery_notify = true; 44 | } 45 | if(battery_state.is_plugged) { 46 | battery_state.is_charging = true; 47 | } 48 | return battery_state.charge_percent; 49 | } 50 | 51 | void toggle_battery_charger_plugged(void) { 52 | battery_state.is_plugged = !battery_state.is_plugged; 53 | 54 | if(battery_state.is_plugged) { 55 | battery_state.is_charging = (battery_state.charge_percent < 90); 56 | } 57 | else { 58 | battery_state.is_charging = false; 59 | } 60 | 61 | battery_notify = true; 62 | } 63 | 64 | // pebble API part 65 | 66 | BatteryChargeState battery_state_service_peek(void) { 67 | return battery_state; 68 | } 69 | 70 | void battery_state_service_subscribe(BatteryStateHandler handler) { 71 | battery_callback = handler; 72 | battery_notify = true; 73 | } 74 | 75 | void battery_state_service_unsubscribe() { 76 | battery_callback = NULL; 77 | battery_notify = false; 78 | } 79 | 80 | void service_battery() { 81 | if(battery_notify && battery_callback != NULL) { 82 | battery_callback(battery_state); 83 | battery_notify = false; 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/local/bitmap.c: -------------------------------------------------------------------------------- 1 | #include "globals.h" 2 | 3 | typedef struct __attribute__((__packed__)) { 4 | uint16_t pitch; 5 | uint16_t info_flags; 6 | uint32_t type; 7 | uint16_t width; 8 | uint16_t height; 9 | } GBitmapHeader; 10 | 11 | #ifdef WIN32 12 | typedef struct __attribute__ ((__packed__)) { 13 | void *addr; 14 | uint16_t row_size_bytes; 15 | union { 16 | uint16_t flags; 17 | struct { 18 | bool is_heap_allocated:1; 19 | uint16_t reserved:11; 20 | uint8_t version:4; 21 | }data; 22 | }info; 23 | } WIN32_GBitmap; 24 | #define GBITMAP_SET_INFO_FLAGS(bmpPtr,set) ((WIN32_GBitmap*)bmpPtr)->info.flags=set 25 | #define GBITMAP_SET_IS_HEAP_ALLOCATED(bmpPtr,is) ((WIN32_GBitmap*)bmpPtr)->info.data.is_heap_allocated=is 26 | #define GBITMAP_GET_INFO_FLAGS(bmpPtr) (((WIN32_GBitmap*)bmpPtr)->info.flags) 27 | #define GBITMAP_GET_IS_HEAP_ALLOCATED(bmpPtr) (((WIN32_GBitmap*)bmpPtr)->info.data.is_heap_allocated) 28 | #else 29 | #define GBITMAP_SET_INFO_FLAGS(bmpPtr,set) bmpPtr->info_flags=set 30 | #define GBITMAP_SET_IS_HEAP_ALLOCATED(bmpPtr,is) bmpPtr->is_heap_allocated=is 31 | #define GBITMAP_GET_INFO_FLAGS(bmpPtr) (bmpPtr->info_flags) 32 | #define GBITMAP_GET_IS_HEAP_ALLOCATED(bmpPtr) (bmpPtr->is_heap_allocated) 33 | #endif 34 | 35 | GBitmap* gbitmap_create_as_sub_bitmap(const GBitmap *base_bitmap, GRect sub_rect) { 36 | GBitmap* sub_bitmap=(GBitmap*)malloc(sizeof(GBitmap)); 37 | if (!sub_bitmap) { 38 | printf ("Memory allocation failed!\n"); 39 | return 0; 40 | } 41 | grect_clip (&sub_rect,&base_bitmap->bounds); 42 | sub_bitmap->addr=base_bitmap->addr; 43 | GBITMAP_SET_INFO_FLAGS(sub_bitmap,GBITMAP_GET_INFO_FLAGS(base_bitmap)); 44 | GBITMAP_SET_IS_HEAP_ALLOCATED(sub_bitmap,false); 45 | sub_bitmap->row_size_bytes=base_bitmap->row_size_bytes; 46 | sub_bitmap->bounds=sub_rect; 47 | return sub_bitmap; 48 | } 49 | 50 | GBitmap* gbitmap_create_with_data (const uint8_t* data) { 51 | GBitmap* bitmap=(GBitmap*)malloc(sizeof(GBitmap)); 52 | if (!bitmap) { 53 | printf ("Memory allocation failed!\n"); 54 | return 0; 55 | } 56 | GBitmapHeader* header=(GBitmapHeader*)data; 57 | bitmap->addr=malloc(header->pitch*header->height); 58 | if (!bitmap->addr) { 59 | printf ("Memory allocation failed!\n"); 60 | return 0; 61 | } 62 | memcpy(bitmap->addr,((uint8_t*)data)+sizeof(GBitmapHeader),header->pitch*header->height); 63 | bitmap->row_size_bytes=header->pitch; 64 | GBITMAP_SET_INFO_FLAGS(bitmap,header->info_flags); 65 | GBITMAP_SET_IS_HEAP_ALLOCATED(bitmap,true); 66 | bitmap->bounds=GRect(0,0,header->width,header->height); 67 | free((uint8_t*)data); //TODO: Verify this! 68 | return bitmap; 69 | } 70 | 71 | GBitmap* gbitmap_create_with_resource (uint32_t resource_id) { 72 | printf ("[DEBUG] Load resource ID:%d as image\n",resource_id); 73 | char name[MAX_RESOURCE_NAME]; 74 | copyResName(name, RES_ID_TO_HANDLE(resource_id)); 75 | FILE* f=fopen(name,"rb"); 76 | if (!f) { 77 | printf("[ERROR] Couldn't load \"%s\"(%s)!\n",name,SDL_GetError()); 78 | return 0; 79 | } 80 | fseek(f,0,SEEK_END); 81 | size_t len=ftell(f); 82 | fseek(f,0,SEEK_SET); 83 | void* data=malloc(len); 84 | if (!data) { 85 | printf("[ERROR] Couldn't load \"%s\"(Memory allocation failed)!\n",name); 86 | return 0; 87 | } 88 | size_t readLen=fread(data,1,len,f); 89 | fclose(f); 90 | if (len!=readLen) { 91 | printf ("[ERROR] Read error!\n"); 92 | free(data); 93 | return 0; 94 | } 95 | return gbitmap_create_with_data (data); 96 | } 97 | 98 | void gbitmap_destroy(GBitmap* bitmap) { 99 | if (bitmap&&bitmap->addr&&GBITMAP_GET_IS_HEAP_ALLOCATED(bitmap)) { 100 | free(bitmap->addr); 101 | bitmap->addr=0; 102 | } 103 | } 104 | 105 | #define BITMAP_LAYER_GET Layer* bitmap_layer=(Layer*)l 106 | #define BITMAP_GET BITMAP_LAYER_GET;BitmapLayerData* bitmap=(BitmapLayerData*)layer_get_data(bitmap_layer) 107 | #define ROT_BITMAP_LAYER_GET Layer* rotbitmap_layer=(Layer*)l 108 | #define ROT_BITMAP_GET BITMAP_LAYER_GET;RotBitmapLayerData* rotbitmap=(RotBitmapLayerData*)layer_get_data(bitmap_layer) 109 | 110 | void bitmap_layer_update_func (Layer* l,GContext* ctx) { 111 | BITMAP_GET; 112 | GRect rect=GRect(0,0,l->frame.size.w,l->frame.size.h); 113 | graphics_context_set_fill_color(ctx,bitmap->background_color); 114 | graphics_fill_rect (ctx,rect,0,0); 115 | rect.origin=l->frame.origin; 116 | grect_align (&rect,&l->frame,bitmap->alignment,l->clips); 117 | rect.origin.x-=l->frame.origin.x; 118 | rect.origin.y-=l->frame.origin.y; 119 | graphics_context_set_compositing_mode (ctx,bitmap->compositing_mode); 120 | graphics_draw_bitmap_in_rect (ctx,bitmap->bitmap,rect); 121 | } 122 | 123 | BitmapLayer * bitmap_layer_create(GRect frame) { 124 | Layer* layer=layer_create_with_data(frame,sizeof(BitmapLayerData)); 125 | if (!layer) 126 | return 0; 127 | BitmapLayerData* bitmap=(BitmapLayerData*)layer_get_data(layer); 128 | layer_set_update_proc(layer,bitmap_layer_update_func); 129 | bitmap->bitmap=0; 130 | bitmap->background_color=GColorClear; 131 | bitmap->alignment=GAlignCenter; 132 | bitmap->compositing_mode=GCompOpAssign; 133 | return (BitmapLayer*)layer; 134 | } 135 | 136 | void bitmap_layer_destroy (BitmapLayer* layer) { 137 | if (layer) 138 | layer_destroy((Layer*)layer); 139 | } 140 | 141 | Layer* bitmap_layer_get_layer (const BitmapLayer* layer) { 142 | return (Layer*)layer; 143 | } 144 | 145 | void bitmap_layer_set_bitmap(BitmapLayer *l, const GBitmap *image) { 146 | BITMAP_GET; 147 | bitmap->bitmap=image; 148 | } 149 | 150 | void bitmap_layer_set_alignment(BitmapLayer *l, GAlign alignment) { 151 | BITMAP_GET; 152 | bitmap->alignment=alignment; 153 | } 154 | 155 | void bitmap_layer_set_background_color(BitmapLayer *l, GColor color) { 156 | BITMAP_GET; 157 | bitmap->background_color=color; 158 | } 159 | 160 | void bitmap_layer_set_compositing_mode(BitmapLayer *l, GCompOp mode) { 161 | BITMAP_GET; 162 | bitmap->compositing_mode=mode; 163 | } 164 | 165 | void rot_bitmap_layer_update_func (Layer* l,GContext* ctx) { 166 | ROT_BITMAP_GET; 167 | GPoint topOffset=getTopOffset (); 168 | setTopOffset(GPoint(0,0)); 169 | GRect rect=GRect(0,0,l->frame.size.w,l->frame.size.h); 170 | 171 | SDL_Surface* sur=createSurface(rotbitmap->bitmap->bounds.size.w,rotbitmap->bitmap->bounds.size.h); 172 | SDL_FillRect(sur,0,0); 173 | graphics_context_set_compositing_mode (ctx,GCompOpAssign); 174 | graphics_draw_bitmap_in_rect_to (ctx,rotbitmap->bitmap,rect,sur); 175 | double angle=(double)rotbitmap->rotation/TRIG_MAX_ANGLE*360.0; 176 | SDL_Surface* rotated=rotozoomSurface(sur,-angle,1.0,SMOOTHING_OFF); 177 | SDL_FreeSurface(sur); 178 | GPoint offset=getPivotRotationOffset(rotbitmap->bitmap->bounds.size,GSize(rotated->w,rotated->h),rotbitmap->src_ic,angle); 179 | 180 | rotbitmap->dest_ic.x=l->frame.size.w/2; //TODO: Verify this 181 | rotbitmap->dest_ic.y=l->frame.size.h/2; 182 | 183 | setTopOffset(topOffset); 184 | if (rotbitmap->corner_clip_color!=GColorClear) { 185 | graphics_context_set_fill_color(ctx,rotbitmap->corner_clip_color); 186 | graphics_fill_rect(ctx,GRect(0,0,l->frame.size.w,l->frame.size.h),0,0); 187 | } 188 | graphics_context_set_compositing_mode (ctx,rotbitmap->compositing_mode); 189 | graphics_draw_surface_in_rect (ctx,rotated,GRect(rotbitmap->dest_ic.x-offset.x,rotbitmap->dest_ic.y-offset.y,rotated->w,rotated->h)); 190 | SDL_FreeSurface(rotated); 191 | } 192 | 193 | RotBitmapLayer* rot_bitmap_layer_create (GBitmap* bitmap) { 194 | Layer* layer=layer_create_with_data(GRect(0,0,bitmap->bounds.size.w,bitmap->bounds.size.h),sizeof(RotBitmapLayerData)); 195 | RotBitmapLayerData* rotbitmap=(RotBitmapLayerData*)layer_get_data(layer); 196 | layer_set_update_proc(layer,rot_bitmap_layer_update_func); 197 | rotbitmap->bitmap=bitmap; 198 | rotbitmap->corner_clip_color=GColorClear; 199 | rotbitmap->rotation=0; 200 | rotbitmap->src_ic=GPoint(0,0); 201 | rotbitmap->dest_ic=GPoint(bitmap->bounds.size.w/2,bitmap->bounds.size.h/2); 202 | rotbitmap->compositing_mode=GCompOpAssign; 203 | return (RotBitmapLayer*)layer; 204 | } 205 | 206 | void rot_bitmap_layer_destroy (RotBitmapLayer* layer) { 207 | if (layer!=0) 208 | layer_destroy((Layer*)layer); 209 | } 210 | 211 | void rot_bitmap_layer_set_corner_clip_color (RotBitmapLayer* l,GColor color) { 212 | ROT_BITMAP_GET; 213 | rotbitmap->corner_clip_color=color; 214 | } 215 | 216 | void rot_bitmap_layer_set_angle(RotBitmapLayer* l,int32_t angle) { 217 | ROT_BITMAP_GET; 218 | rotbitmap->rotation=angle; 219 | } 220 | 221 | void rot_bitmap_layer_increment_angle (RotBitmapLayer* l,int32_t angle_change) { 222 | ROT_BITMAP_GET; 223 | rotbitmap->rotation+=angle_change; 224 | } 225 | 226 | void rot_bitmap_set_src_ic(RotBitmapLayer* l,GPoint ic) { 227 | ROT_BITMAP_GET; 228 | rotbitmap->src_ic=ic; 229 | } 230 | 231 | void rot_bitmap_set_compositing_mode(RotBitmapLayer* l,GCompOp mode) { 232 | ROT_BITMAP_GET; 233 | rotbitmap->compositing_mode=mode; 234 | } 235 | -------------------------------------------------------------------------------- /src/local/bluetooth.c: -------------------------------------------------------------------------------- 1 | #include "globals.h" 2 | 3 | // 4 | // This file implements the BluetoothConnectionService 5 | // 6 | 7 | static bool bluetooth_state = true; 8 | static bool bluetooth_notify = false; 9 | static BluetoothConnectionHandler bluetooth_callback = NULL; 10 | static SniffInterval currentSniffInterval = SNIFF_INTERVAL_NORMAL; 11 | 12 | void toggle_bluetooth_connection () { 13 | bluetooth_state = !bluetooth_state; 14 | bluetooth_notify = true; 15 | } 16 | 17 | bool bluetooth_connection_service_peek(void) { 18 | return bluetooth_state; 19 | } 20 | 21 | void bluetooth_connection_service_subscribe(BluetoothConnectionHandler handler) { 22 | bluetooth_callback = handler; 23 | bluetooth_notify = true; 24 | } 25 | 26 | void bluetooth_connection_service_unsubscribe(void) { 27 | bluetooth_callback = NULL; 28 | } 29 | 30 | void service_bluetooth() { 31 | if( bluetooth_notify && bluetooth_callback != NULL ) { 32 | bluetooth_callback(bluetooth_state); 33 | bluetooth_notify = false; 34 | } 35 | } 36 | 37 | SniffInterval app_comm_get_sniff_interval () { 38 | return currentSniffInterval; 39 | } 40 | 41 | void app_comm_set_sniff_interval (const SniffInterval interval) { 42 | currentSniffInterval = interval; 43 | } 44 | -------------------------------------------------------------------------------- /src/local/buttons.c: -------------------------------------------------------------------------------- 1 | #include "globals.h" 2 | #include 3 | 4 | #define LONG_CLICK_STD_DELAY 500 // as per documentation 5 | 6 | typedef struct ClickRecognizer 7 | { 8 | ButtonId id; 9 | uint32_t lastDown; 10 | bool isDown; 11 | uint16_t clickCount; //reseted by multi_click.timeout 12 | bool longClick; 13 | } ClickRecognizer; 14 | 15 | static ClickConfig clickConfig [NUM_BUTTONS]; 16 | static ClickConfig* clickConfigPtr [NUM_BUTTONS]; 17 | static ClickRecognizer clickRecognizer [NUM_BUTTONS]; 18 | 19 | ClickConfig** getClickConfig () 20 | { 21 | return clickConfigPtr; 22 | } 23 | 24 | void resetClickConfig () 25 | { 26 | int i; 27 | memset(clickConfig,0,sizeof(ClickConfig)*NUM_BUTTONS); 28 | for (i=0;iisDown) 56 | return; 57 | rec->clickCount++; 58 | rec->lastDown=SDL_GetTicks(); 59 | rec->isDown=true; 60 | if (conf->raw.down_handler!=0) { 61 | conf->raw.down_handler(rec,conf->raw.context); 62 | handled=true; 63 | } 64 | if (conf->multi_click.handler!=0&& 65 | ((rec->clickCount>=conf->multi_click.min&&(conf->multi_click.max==0||rec->clickCount<=conf->multi_click.max)&&!conf->multi_click.last_click_only)|| 66 | (rec->clickCount==conf->multi_click.max&&conf->multi_click.max!=0&&conf->multi_click.last_click_only))) { 67 | conf->multi_click.handler(rec,conf->context); 68 | handled=true; 69 | } 70 | if (!handled&&id==BUTTON_ID_BACK&&getWindowStackSize()>1) 71 | window_stack_pop (true); 72 | } 73 | 74 | void onButtonUp (ButtonId id) 75 | { 76 | ClickRecognizer* rec; 77 | ClickConfig* conf; 78 | rec=clickRecognizer+id; 79 | conf=clickConfig+id; 80 | rec->isDown=false; 81 | if (conf->click.handler!=0&&!rec->longClick) 82 | conf->click.handler(rec,conf->context); 83 | if (conf->raw.up_handler!=0) 84 | conf->raw.up_handler(rec,conf->raw.context); 85 | if (rec->longClick&&conf->long_click.delay_ms>0&&conf->long_click.release_handler!=0) 86 | conf->long_click.release_handler(rec,conf->context); 87 | rec->longClick=false; 88 | } 89 | 90 | void service_buttons () 91 | { 92 | ClickRecognizer* rec; 93 | ClickConfig* conf; 94 | int i; 95 | for (i=0;imulti_click.timeout>0&&rec->lastDown>0&&SDL_GetTicks()-rec->lastDown>conf->multi_click.timeout) 99 | rec->clickCount=0; 100 | if (rec->isDown) { 101 | if (conf->click.handler!=0&&conf->click.repeat_interval_ms>0&&SDL_GetTicks()-rec->lastDown>=conf->click.repeat_interval_ms) { 102 | conf->click.handler(rec,conf->context); 103 | rec->lastDown=SDL_GetTicks(); 104 | rec->clickCount++; 105 | } 106 | if (conf->long_click.delay_ms>0 && SDL_GetTicks()-rec->lastDown>=conf->long_click.delay_ms && 107 | (conf->long_click.handler || conf->long_click.release_handler) && !rec->longClick) { 108 | if (conf->long_click.handler) 109 | conf->long_click.handler(rec,conf->context); 110 | rec->longClick=true; 111 | } 112 | } 113 | } 114 | } 115 | 116 | void buttonsUpdateWindow (Window* w) 117 | { 118 | resetClickConfig (); 119 | if (w!=0&&w->click_config_provider!=0) 120 | w->click_config_provider(w->click_config_context); 121 | } 122 | 123 | uint8_t click_number_of_clicks_counted (ClickRecognizerRef recognizer) { 124 | return ((ClickRecognizer*)recognizer)->clickCount; 125 | } 126 | 127 | ButtonId click_recognizer_get_button_id (ClickRecognizerRef recognizer) { 128 | return ((ClickRecognizer*)recognizer)->id; 129 | } 130 | 131 | void window_single_click_subscribe(ButtonId button_id,ClickHandler handler) { 132 | clickConfig[button_id].click.repeat_interval_ms=0; 133 | clickConfig[button_id].click.handler=handler; 134 | } 135 | 136 | void window_single_repeating_click_subscribe(ButtonId button_id,uint16_t repeat_interval_ms,ClickHandler handler) { 137 | clickConfig[button_id].click.repeat_interval_ms=repeat_interval_ms; 138 | clickConfig[button_id].click.handler=handler; 139 | } 140 | 141 | void window_multi_click_subscribe(ButtonId button_id,uint8_t min_clicks,uint8_t max_clicks,uint16_t timeout,bool last_click_only,ClickHandler handler) { 142 | clickConfig[button_id].multi_click.min=min_clicks; 143 | clickConfig[button_id].multi_click.max=max_clicks; 144 | clickConfig[button_id].multi_click.timeout=timeout; 145 | clickConfig[button_id].multi_click.last_click_only=last_click_only; 146 | clickConfig[button_id].multi_click.handler=handler; 147 | } 148 | 149 | void window_long_click_subscribe(ButtonId button_id,uint16_t delay_ms,ClickHandler down_handler,ClickHandler up_handler) { 150 | clickConfig[button_id].long_click.delay_ms=(delay_ms == 0 ? LONG_CLICK_STD_DELAY : delay_ms); 151 | clickConfig[button_id].long_click.handler=down_handler; 152 | clickConfig[button_id].long_click.release_handler=up_handler; 153 | } 154 | 155 | void window_raw_click_subscribe(ButtonId button_id,ClickHandler down_handler,ClickHandler up_handler,void* context) { 156 | clickConfig[button_id].raw.down_handler=down_handler; 157 | clickConfig[button_id].raw.up_handler=up_handler; 158 | clickConfig[button_id].raw.context=context; 159 | } 160 | 161 | void window_set_click_context (ButtonId button_id,void* context) { 162 | clickConfig[button_id].context=context; 163 | } 164 | -------------------------------------------------------------------------------- /src/local/dummy/src/resource_ids.auto.h: -------------------------------------------------------------------------------- 1 | /* 2 | Because of some reasons (perhaps SDL?) changing the entry point creates crashes, 3 | but because pebble.h includes this file and all your pebble apps include pebble.h 4 | I change the name of your "main" function to "pbl_main" 5 | */ 6 | #ifdef main 7 | #undef main 8 | #endif 9 | 10 | #define main pbl_main 11 | -------------------------------------------------------------------------------- /src/local/font.c: -------------------------------------------------------------------------------- 1 | #include "globals.h" 2 | 3 | enum SystemFontID { 4 | SYSTEM_FONT_GOTHIC_14=0, 5 | SYSTEM_FONT_GOTHIC_14_BOLD, 6 | SYSTEM_FONT_GOTHIC_18, 7 | SYSTEM_FONT_GOTHIC_18_BOLD, 8 | SYSTEM_FONT_GOTHIC_24, 9 | SYSTEM_FONT_GOTHIC_24_BOLD, 10 | SYSTEM_FONT_GOTHIC_28, 11 | SYSTEM_FONT_GOTHIC_28_BOLD, 12 | SYSTEM_FONT_BITHAM_30, 13 | SYSTEM_FONT_BITHAM_42_BOLD, 14 | SYSTEM_FONT_BITHAM_42_LIGHT, 15 | SYSTEM_FONT_BITHAM_42_MEDIUM_NUMBERS, 16 | SYSTEM_FONT_BITHAM_34_MEDIUM_NUMBERS, 17 | SYSTEM_FONT_BITHAM_34_LIGHT_SUBSET, 18 | SYSTEM_FONT_BITHAM_18_LIGHT_SUBSET, 19 | SYSTEM_FONT_ROBOTO_CONDENSED_21, 20 | SYSTEM_FONT_ROBOTO_BOLD_SUBSET_49, 21 | SYSTEM_DROID_SERIF_28_BOLD, 22 | SYSTEM_FONT_COUNT 23 | }; 24 | struct SystemFont { 25 | TTF_Font* font; 26 | const char* key; 27 | const char* file; 28 | int psize; 29 | int lsize; 30 | }; 31 | struct SystemFont systemFonts [SYSTEM_FONT_COUNT]= { 32 | {0,FONT_KEY_GOTHIC_14,"./systemFonts/gothic.ttf",8,14}, 33 | {0,FONT_KEY_GOTHIC_14_BOLD,"./systemFonts/gothic-bold.ttf",8,14}, // 1 bold 34 | {0,FONT_KEY_GOTHIC_18,"./systemFonts/gothic.ttf",10,18}, 35 | {0,FONT_KEY_GOTHIC_18_BOLD,"./systemFonts/gothic-bold.ttf",10,18}, // 3 bold 36 | {0,FONT_KEY_GOTHIC_24,"./systemFonts/gothic.ttf",14,24}, 37 | {0,FONT_KEY_GOTHIC_24_BOLD,"./systemFonts/gothic-bold.ttf",14,24}, // 5 bold 38 | {0,FONT_KEY_GOTHIC_28,"./systemFonts/gothic.ttf",18,28}, 39 | {0,FONT_KEY_GOTHIC_28_BOLD,"./systemFonts/gothic-bold.ttf",18,28}, // 7 bold 40 | {0,FONT_KEY_BITHAM_30_BLACK,"./systemFonts/bitham-black.ttf",30,30}, 41 | {0,FONT_KEY_BITHAM_42_BOLD,"./systemFonts/bitham-bold.ttf",42,42}, // 9 bold 42 | {0,FONT_KEY_BITHAM_42_LIGHT,"./systemFonts/bitham-light.ttf",42,42}, 43 | {0,FONT_KEY_BITHAM_42_MEDIUM_NUMBERS,"./systemFonts/bitham-medium-numbers.ttf",42,42}, 44 | {0,FONT_KEY_BITHAM_34_MEDIUM_NUMBERS,"./systemFonts/bitham-medium-numbers.ttf",34,34}, 45 | {0,FONT_KEY_BITHAM_34_LIGHT_SUBSET,"./systemFonts/bitham-light-subset.ttf",34,34}, 46 | {0,FONT_KEY_BITHAM_18_LIGHT_SUBSET,"./systemFonts/bitham-light-subset.ttf",18,18}, 47 | {0,FONT_KEY_ROBOTO_CONDENSED_21,"./systemFonts/roboto-condensed.ttf",21,21}, 48 | {0,FONT_KEY_ROBOTO_BOLD_SUBSET_49,"./systemFonts/roboto-bold.ttf",49,49}, 49 | {0,FONT_KEY_DROID_SERIF_28_BOLD,"./systemFonts/droid-serif-bold.ttf",28,28}, 50 | }; 51 | 52 | int lineHeightFromFont(GFont font) { 53 | for (int i=0; iframe.size.w,l->frame.size.h); 130 | graphics_context_set_fill_color(ctx,text->background_color); 131 | graphics_fill_rect (ctx,rect,0,0); 132 | graphics_context_set_text_color(ctx,text->text_color); 133 | graphics_draw_text (ctx,text->text,text->font,rect,text->overflow_mode,text->text_alignment,0); 134 | } 135 | 136 | TextLayer* text_layer_create(GRect frame) { 137 | Layer* layer=layer_create_with_data(frame,sizeof(TextLayerData)); 138 | TextLayerData* text_layer=(TextLayerData*)layer_get_data(layer); 139 | layer_set_update_proc (layer,text_layer_update_func); 140 | text_layer->font = fonts_get_system_font(FONT_KEY_GOTHIC_14); 141 | text_layer->text_alignment = GTextAlignmentLeft; 142 | text_layer->text_color = GColorBlack; 143 | text_layer->background_color = GColorWhite; 144 | text_layer->overflow_mode = GTextOverflowModeWordWrap; 145 | text_layer->should_cache_layout = false; 146 | return (TextLayer*)layer; 147 | } 148 | 149 | void text_layer_destroy (TextLayer* layer) { 150 | if (layer) 151 | layer_destroy((Layer*)layer); 152 | } 153 | 154 | const char *text_layer_get_text(TextLayer *l) { 155 | TEXT_GET; 156 | return text->text; 157 | } 158 | 159 | void text_layer_set_text(TextLayer *l, const char *txt) { 160 | TEXT_GET; 161 | text->text = txt; 162 | layer_mark_dirty (text_layer); 163 | } 164 | 165 | void text_layer_set_font(TextLayer *l, GFont font) { 166 | TEXT_GET; 167 | text->font = font; 168 | layer_mark_dirty (text_layer); 169 | } 170 | 171 | void text_layer_set_text_color(TextLayer *l, GColor color) { 172 | TEXT_GET; 173 | text->text_color = color; 174 | layer_mark_dirty (text_layer); 175 | } 176 | 177 | void text_layer_set_background_color(TextLayer *l, GColor color) { 178 | TEXT_GET; 179 | text->background_color = color; 180 | layer_mark_dirty (text_layer); 181 | } 182 | 183 | void text_layer_set_overflow_mode(TextLayer *l, GTextOverflowMode line_mode) { 184 | TEXT_GET 185 | text->overflow_mode = line_mode; 186 | layer_mark_dirty (text_layer); 187 | } 188 | 189 | void text_layer_set_text_alignment(TextLayer *l, GTextAlignment text_alignment) { 190 | TEXT_GET; 191 | text->text_alignment = text_alignment; 192 | layer_mark_dirty (text_layer); 193 | } 194 | 195 | void text_layer_set_size(TextLayer *l, const GSize max_size) { 196 | TEXT_LAYER_GET; 197 | GRect frame=layer_get_frame (text_layer); 198 | frame.size=max_size; 199 | layer_set_frame (text_layer,frame); 200 | layer_mark_dirty (text_layer); 201 | } 202 | 203 | Layer* text_layer_get_layer (TextLayer* l) { 204 | return (Layer*)l; 205 | } 206 | 207 | GSize text_layer_get_content_size (TextLayer *l) { 208 | TEXT_GET; 209 | Layer *ll = (Layer*)l; 210 | GRect rect=GRect(0,0,ll->frame.size.w,ll->frame.size.h); 211 | GSize s = _graphics_draw_text (NULL,text->text,text->font,rect,text->overflow_mode,text->text_alignment,0,1); 212 | return s; 213 | } 214 | -------------------------------------------------------------------------------- /src/local/globals.h: -------------------------------------------------------------------------------- 1 | #ifndef __GLOBALS_H__ 2 | #define __GLOBALS_H__ 3 | #include 4 | #include 5 | #include 6 | 7 | #include "impl_pebble.h" 8 | 9 | #include "SDL_gfxPrimitives.h" 10 | #include "SDL_gfxBlitFunc.h" 11 | #include "SDL_rotozoom.h" 12 | 13 | #ifdef WIN32 14 | #include 15 | #else 16 | #define min(A, B) (((A) < (B) ? (A) : (B))) 17 | #define max(A, B) (((A) > (B) ? (A) : (B))) 18 | #endif 19 | 20 | #define clamp(A, X, B) min(max(A, X), B) 21 | 22 | #define PI 3.14159265 23 | #define DEGtoRAD(deg) ((PI/180.0)*(deg)) 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | //SYSTEM SYSTEM SYSTEM SYSTEM SYSTEM SYSTEM SYSTEM SYSTEM SYSTEM SYSTEM SYSTEM SYSTEM 30 | #define SCROLL_LAYER_CLICK_DELAY 350 31 | #define SCROLL_LAYER_SCROLL_AMOUNT 25 32 | #define SCROLL_LAYER_SCROLL_DELAY 360 33 | #define SCROLL_LAYER_SCROLL_DELAY_MAX 350 34 | #define SCROLL_LAYER_SCROLL_SPEED ((double)SCROLL_LAYER_SCROLL_DELAY/SCROLL_LAYER_SCROLL_AMOUNT) 35 | 36 | extern int pbl_main (void); 37 | 38 | //#define APP_INFO __pbl_app_info 39 | //extern PebbleAppInfo __pbl_app_info; 40 | void toggle_24h_style (); 41 | void toggle_bluetooth_connection (); 42 | void toggle_battery_charger_plugged (); 43 | 44 | uint8_t battery_charge_increase(void); 45 | uint8_t battery_charge_decrease(void); 46 | 47 | void accel_do_tap_on_axis(AccelAxisType axis, int32_t direction); 48 | 49 | bool persistent_storage_load(); 50 | bool persistent_storage_save(); 51 | void persistent_storage_free(); 52 | 53 | bool setup_js_app(); 54 | 55 | //WATCHINFO WATCHINFO WATCHINFO WATCHINFO WATCHINFO WATCHINFO WATCHINFO 56 | 57 | #define WINDOW_WIDTH 390 58 | #define WINDOW_HEIGHT 440 59 | #define BODY_WIDTH 275 60 | #define BODY_HEIGHT 440 61 | #define BODY_OFFSET_X (WINDOW_WIDTH/2 - BODY_WIDTH/2) 62 | #define BODY_OFFSET_Y 0 63 | #define PBL_SCREEN_OFFSET_X (BODY_OFFSET_X + 65) 64 | #define PBL_SCREEN_OFFSET_Y (BODY_OFFSET_Y + 121) 65 | 66 | void drawBody (SDL_Surface* screen, uint8_t buttonState); 67 | void nextBody (); 68 | 69 | //SERVICES SERVICES SERVICES SERVICES SERVICES SERVICES SERVICES SERVICES 70 | typedef void (*ServiceUpdateCallback) (void); 71 | enum SimServices { 72 | SIM_SERVICE_BUTTONS=0, 73 | SIM_SERVICE_HARDWARE_OUTPUT, 74 | SIM_SERVICE_ANIMATIONS, 75 | SIM_SERVICE_TIMERS, 76 | SIM_SERVICE_TICKS, 77 | SIM_SERVICE_BLUETOOTH, 78 | SIM_SERVICE_BATTERY, 79 | SIM_SERVICE_ACCEL_TAP, 80 | SIM_SERVICE_APP_MESSAGE, 81 | SIM_SERVICE_COUNT 82 | }; 83 | typedef struct { 84 | struct { 85 | TimeUnits units; 86 | TickHandler handler; 87 | } ticks; 88 | ServiceUpdateCallback services[SIM_SERVICE_COUNT]; 89 | } ServiceData; 90 | extern ServiceData serviceData; 91 | void service_buttons (); 92 | void service_hardware_output (); 93 | void service_animations (); 94 | void service_timers (); 95 | void service_ticks (); 96 | void service_bluetooth (); 97 | void service_battery (); 98 | void service_accel_tap (); 99 | void service_app_message(); 100 | void service_app_sync(DictionaryIterator*); 101 | 102 | //SIMDATA SIMDATA SIMDATA SIMDATA SIMDATA SIMDATA SIMDATA SIMDATA SIMDATA SIMDATA SIMDATA 103 | enum SimImages 104 | { 105 | SIM_IMG_BODY=0, 106 | SIM_IMG_SCREEN_SHADOW, 107 | SIM_IMG_BACKLIGHT, 108 | SIM_IMG_STATUS_BAR, 109 | SIM_IMG_VIBE, 110 | SIM_IMG_SCROLL_SHADOW, 111 | SIM_IMG_COUNT 112 | }; 113 | bool loadSimulatorImages (); 114 | void freeSimulatorImages (); 115 | SDL_Surface* getSimulatorImage (int imageID); 116 | void unloadSystemFonts (); 117 | extern FILE* logFile; 118 | 119 | //DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW 120 | #define PBL_SCREEN_WIDTH 144 121 | #define PBL_SCREEN_HEIGHT 168 122 | 123 | #define LOCK(X) if(SDL_MUSTLOCK(X)) SDL_LockSurface(X) 124 | #define UNLOCK(X) if(SDL_MUSTLOCK(X)) SDL_UnlockSurface(X) 125 | 126 | struct GContext 127 | { 128 | GColor fill_color; 129 | GColor stroke_color; 130 | GColor text_color; 131 | GCompOp compositing_mode; 132 | }; 133 | 134 | static const uint32_t r_white = 0xffffffff; 135 | static const uint32_t r_black = 0x000000ff; 136 | static const uint32_t r_clear = 0x00000000; 137 | 138 | extern uint32_t getRawColor(uint8_t color); 139 | 140 | extern SDL_Color s_white; 141 | extern SDL_Color s_black; 142 | extern SDL_Color s_clear; 143 | 144 | SDL_Color getColor(uint8_t color); 145 | void sdlrect_clip (SDL_Rect* const rect_to_clip,const SDL_Rect* const clipper); 146 | 147 | void graphics_draw_bitmap_in_rect_to(GContext* ctx,const GBitmap* bitmap,GRect,SDL_Surface* to); 148 | void graphics_draw_surface_in_rect (GContext* ctx,SDL_Surface* sur,GRect rect); 149 | void graphics_draw_surface_in_rect_to (GContext* ctx,SDL_Surface* sur,GRect rect,SDL_Surface* to); 150 | GContext *app_get_current_graphics_context(void); 151 | // Used to either draw or calculate size 152 | GSize _graphics_draw_text(GContext *ctx, const char *text, const GFont font, const GRect box, const GTextOverflowMode overflow_mode, const GTextAlignment alignment, const GTextLayoutCacheRef layout, int getSizeOnly); 153 | int lineHeightFromFont(GFont font); 154 | 155 | //BUTTONS BUTTONS BUTTONS BUTTONS BUTTONS BUTTONS BUTTONS BUTTONS BUTTONS BUTTONS 156 | void onButtonDown (ButtonId id); 157 | void onButtonUp (ButtonId id); 158 | void buttonsUpdateWindow (Window* w); 159 | void initButtons (); 160 | ClickConfig** getClickConfig (); 161 | 162 | //HARDWARE OUTPUT HARDWARE OUTPUT HARDWARE OUTPUT HARDWARE OUTPUT HARDWARE OUTPUT 163 | #define MAX_VIBE_ELEMENTS 32 164 | #define VIBE_SHORT_MS 300 165 | #define VIBE_LONG_MS 500 166 | #define LIGHT_LENGTH 2000 167 | 168 | bool getVibeState (); 169 | bool getLightState (); 170 | 171 | void initHardwareOutput (); 172 | 173 | //RENDER RENDER RENDER RENDER RENDER RENDER RENDER RENDER RENDER RENDER 174 | #define MAX_WINDOWS 8 175 | #define MAX_SCREEN_POOL 8 176 | #define MIN_SCREEN_POOL 4 177 | #define MAX_RENDER_LIST 12 178 | 179 | #define createSurface(w,h) (SDL_CreateRGBSurface (0,w,h,32,0xff000000,0x00ff0000,0x0000ff00,0x000000ff)) 180 | #define createScreen createSurface(PBL_SCREEN_WIDTH,PBL_SCREEN_HEIGHT) 181 | 182 | bool initRender (SDL_Surface* screen); 183 | void quitRender (); 184 | 185 | void pushWindow (Window* w); 186 | void popWindow (); 187 | int getWindowStackSize (); 188 | 189 | SDL_Surface* pushScreen (); 190 | void popScreen (); 191 | SDL_Surface* getTopScreen (); 192 | void meltScreens (); 193 | 194 | void pushLayer (Layer* l); 195 | void popLayer (); 196 | void markDirty (bool toggle); 197 | GPoint getTopOffset (); 198 | void setTopOffset (GPoint set); 199 | 200 | bool render (); 201 | 202 | //TIMERS 203 | void freeTimers(); 204 | 205 | //RESHELPER RESHELPER RESHELPER RESHELPER RESHELPER RESHELPER RESHELPER 206 | #define MAX_RESOURCE_NAME 32 207 | #define RESOURCE_NAME_BASE "./resources/%d" 208 | #ifdef __x86_64__ 209 | # define RES_ID_TO_HANDLE(id) ((ResHandle)(uint64_t)(uint32_t)(id)) 210 | #else 211 | # define RES_ID_TO_HANDLE(id) ((ResHandle)(uint32_t)(id)) 212 | #endif 213 | void copyResName (char* name,ResHandle h); 214 | 215 | //ADDITIONAL PEBBLE OS ADDITIONAL PEBBLE OS ADDITIONAL PEBBLE OS 216 | //functions, the original pebble API might have but doesn't 217 | void gpoint_move_into_rect (GPoint* const point,const GRect* const rect); 218 | 219 | //Helper functions 220 | GPoint getPivotRotationOffset (GSize rectOrig,GSize rectRotated,GPoint pivot,double angle); 221 | 222 | #endif //__GLOBALS_H_ 223 | -------------------------------------------------------------------------------- /src/local/hardwareOutput.c: -------------------------------------------------------------------------------- 1 | #include "globals.h" 2 | 3 | typedef struct VibeElement 4 | { 5 | bool vibe; 6 | uint32_t len; 7 | } VibeElement; 8 | static VibeElement vibes[MAX_VIBE_ELEMENTS]; 9 | static int vibeStart=0; 10 | static int vibeSize=0; 11 | static bool currentVibe=false; 12 | static uint32_t vibesTick=0; 13 | 14 | static int light_length=0; //-1=on 0=off >0=on for light_length ms 15 | static int light_tick=0; 16 | 17 | void initHardwareOutput () 18 | { 19 | } 20 | 21 | void service_hardware_output () { 22 | if (vibeSize>0) { 23 | if (vibesTick==0) { 24 | vibesTick=SDL_GetTicks(); 25 | currentVibe=vibes[vibeStart].vibe; 26 | } 27 | if (SDL_GetTicks()-vibesTick>=vibes[vibeStart].len) { 28 | vibeStart++; 29 | if (vibeStart==MAX_VIBE_ELEMENTS) 30 | vibeStart=0; 31 | vibeSize--; 32 | if (vibeSize==0&¤tVibe) 33 | currentVibe=false; 34 | vibesTick=0; 35 | } 36 | } 37 | if (light_length>0&&SDL_GetTicks()-light_tick>=light_length) 38 | light_length=0; 39 | } 40 | 41 | bool getVibeState() { 42 | return currentVibe; 43 | } 44 | 45 | bool getLightState() { 46 | return (light_length!=0); 47 | } 48 | 49 | void vibes_cancel () 50 | { 51 | vibeStart=0; 52 | vibeSize=0; 53 | } 54 | 55 | void addVibe (uint32_t len,bool vibe) 56 | { 57 | vibes[(vibeStart+vibeSize)%MAX_VIBE_ELEMENTS]=(VibeElement){vibe,len}; 58 | vibeSize++; 59 | } 60 | 61 | void vibes_double_pulse () 62 | { 63 | addVibe(VIBE_SHORT_MS,true); 64 | addVibe(VIBE_SHORT_MS,false); 65 | addVibe(VIBE_SHORT_MS,true); 66 | } 67 | 68 | void vibes_short_pulse () 69 | { 70 | addVibe(VIBE_SHORT_MS,true); 71 | } 72 | 73 | void vibes_long_pulse () 74 | { 75 | addVibe(VIBE_LONG_MS,true); 76 | } 77 | 78 | void vibes_enqueue_custom_pattern (VibePattern pattern) 79 | { 80 | int i; 81 | for (i=0;i