summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
commitc04dcc2e7d834218ef2d4194331e383402495ae1 (patch)
tree7333e38d10d75386e60f336b80c2443c1166031d /tools
parentInitial commit. (diff)
downloadkodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz
kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tools')
-rwxr-xr-xtools/EventClients/Clients/KodiSend/kodi-send.py135
-rwxr-xr-xtools/EventClients/Clients/PS3BDRemote/ps3_remote.py219
-rw-r--r--tools/EventClients/Clients/PS3SixaxisController/README.ubuntu1
-rwxr-xr-xtools/EventClients/Clients/PS3SixaxisController/ps3d.py406
-rw-r--r--tools/EventClients/Clients/WiiRemote/CMakeLists.txt23
-rw-r--r--tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.cpp778
-rw-r--r--tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.h171
-rw-r--r--tools/EventClients/Clients/WiiRemote/Makefile14
-rw-r--r--tools/EventClients/Clients/WiiRemote/WiiUse_README18
-rw-r--r--tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.cpp265
-rw-r--r--tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.h127
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/CHANGELOG208
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE620
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE_noncommercial170
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/Makefile23
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/README155
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/Makefile83
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsp111
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsw29
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.optbin0 -> 48640 bytes
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/sdl.c439
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/Makefile84
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/example.c437
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsp106
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsw29
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.optbin0 -> 48640 bytes
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/Makefile91
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.c190
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.h51
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/definitions.h77
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.c228
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.h54
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.c878
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.h51
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.c172
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.h60
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.c119
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.h54
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_nix.c271
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_win.c247
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.c748
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.h52
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsp191
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsw29
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.optbin0 -> 52736 bytes
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.c210
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.h51
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/os.h53
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.c764
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.h649
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse_internal.h224
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.cbp86
-rw-r--r--tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.layout61
-rw-r--r--tools/EventClients/Clients/Xbox360Controller/Xbox360Controller.cpp172
-rw-r--r--tools/EventClients/Clients/Xbox360Controller/Xbox360Controller.h47
-rw-r--r--tools/EventClients/Clients/Xbox360Controller/Xbox360EventClient.cpp159
-rw-r--r--tools/EventClients/Clients/Xbox360Controller/Xbox360EventClient.vcproj208
-rw-r--r--tools/EventClients/Clients/Xbox360Controller/stdafx.cpp8
-rw-r--r--tools/EventClients/Clients/Xbox360Controller/stdafx.h15
-rw-r--r--tools/EventClients/Clients/Xbox360Controller/targetver.h13
-rw-r--r--tools/EventClients/README.txt90
-rw-r--r--tools/EventClients/examples/c#/XBMCDemoClient1.cs47
-rw-r--r--tools/EventClients/examples/c++/example_button1.cpp65
-rw-r--r--tools/EventClients/examples/c++/example_button2.cpp75
-rw-r--r--tools/EventClients/examples/c++/example_log.cpp39
-rw-r--r--tools/EventClients/examples/c++/example_mouse.cpp63
-rw-r--r--tools/EventClients/examples/c++/example_notification.cpp64
-rw-r--r--tools/EventClients/examples/java/XBMCDemoClient1.java70
-rwxr-xr-xtools/EventClients/examples/python/example_action.py51
-rwxr-xr-xtools/EventClients/examples/python/example_button1.py90
-rwxr-xr-xtools/EventClients/examples/python/example_button2.py84
-rwxr-xr-xtools/EventClients/examples/python/example_mouse.py56
-rwxr-xr-xtools/EventClients/examples/python/example_notification.py49
-rwxr-xr-xtools/EventClients/examples/python/example_simple.py60
-rw-r--r--tools/EventClients/icons/bluetooth.pngbin0 -> 2676 bytes
-rw-r--r--tools/EventClients/icons/mail.pngbin0 -> 1407 bytes
-rw-r--r--tools/EventClients/icons/mouse.pngbin0 -> 2311 bytes
-rw-r--r--tools/EventClients/icons/phone.pngbin0 -> 1733 bytes
-rw-r--r--tools/EventClients/lib/c#/EventClient.cs555
-rw-r--r--tools/EventClients/lib/c++/xbmcclient.h823
-rw-r--r--tools/EventClients/lib/java/build.xml72
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/Packet.java289
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketACTION.java61
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBUTTON.java157
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBYE.java37
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketHELO.java64
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketLOG.java48
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketMOUSE.java45
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketNOTIFICATION.java71
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketPING.java37
-rw-r--r--tools/EventClients/lib/java/src/org/xbmc/eventclient/XBMCClient.java318
-rw-r--r--tools/EventClients/lib/python/__init__.py2
-rw-r--r--tools/EventClients/lib/python/bt/__init__.py2
-rw-r--r--tools/EventClients/lib/python/bt/bt.py82
-rw-r--r--tools/EventClients/lib/python/bt/hid.py81
-rw-r--r--tools/EventClients/lib/python/ps3/__init__.py2
-rw-r--r--tools/EventClients/lib/python/ps3/keymaps.py81
-rw-r--r--tools/EventClients/lib/python/ps3/sixaxis.py372
-rwxr-xr-xtools/EventClients/lib/python/ps3/sixpair.py114
-rwxr-xr-xtools/EventClients/lib/python/ps3/sixwatch.py31
-rw-r--r--tools/EventClients/lib/python/xbmcclient.py639
-rw-r--r--tools/EventClients/lib/python/zeroconf.py160
-rw-r--r--tools/Linux/firewalld-services/kodi-eventserver.xml6
-rw-r--r--tools/Linux/firewalld-services/kodi-http.xml6
-rw-r--r--tools/Linux/firewalld-services/kodi-jsonrpc.xml6
-rw-r--r--tools/Linux/kodi-standalone.sh.in54
-rw-r--r--tools/Linux/kodi-standalone.sh.pulse4
-rw-r--r--tools/Linux/kodi-xsession.desktop.in8
-rw-r--r--tools/Linux/kodi.desktop.in25
-rw-r--r--tools/Linux/kodi.metainfo.xml.in137
-rw-r--r--tools/Linux/kodi.sh.in192
-rw-r--r--tools/Linux/packaging/README.debian31
-rw-r--r--tools/Linux/packaging/media/icon128x128.pngbin0 -> 3825 bytes
-rw-r--r--tools/Linux/packaging/media/icon16x16.pngbin0 -> 690 bytes
-rw-r--r--tools/Linux/packaging/media/icon22x22.pngbin0 -> 929 bytes
-rw-r--r--tools/Linux/packaging/media/icon24x24.pngbin0 -> 979 bytes
-rw-r--r--tools/Linux/packaging/media/icon256x256.pngbin0 -> 6729 bytes
-rw-r--r--tools/Linux/packaging/media/icon32x32.pngbin0 -> 1264 bytes
-rw-r--r--tools/Linux/packaging/media/icon48x48.pngbin0 -> 1698 bytes
-rw-r--r--tools/Linux/packaging/media/icon64x64.pngbin0 -> 2297 bytes
-rwxr-xr-xtools/Linux/packaging/mk-debian-package.sh187
-rwxr-xr-xtools/Linux/packaging/package-kodi-launchpad.sh81
-rw-r--r--tools/buildsteps/README15
-rw-r--r--tools/buildsteps/android-arm64-v8a/configure-depends18
-rw-r--r--tools/buildsteps/android-arm64-v8a/configure-xbmc5
-rw-r--r--tools/buildsteps/android-arm64-v8a/make-binary-addons29
-rw-r--r--tools/buildsteps/android-arm64-v8a/make-depends9
-rw-r--r--tools/buildsteps/android-arm64-v8a/make-native-depends9
-rw-r--r--tools/buildsteps/android-arm64-v8a/make-xbmc5
-rw-r--r--tools/buildsteps/android-arm64-v8a/package14
-rw-r--r--tools/buildsteps/android-arm64-v8a/prepare-depends15
-rw-r--r--tools/buildsteps/android-arm64-v8a/prepare-xbmc9
-rw-r--r--tools/buildsteps/android-x86_64/configure-depends17
-rw-r--r--tools/buildsteps/android-x86_64/configure-xbmc5
-rw-r--r--tools/buildsteps/android-x86_64/make-binary-addons29
-rw-r--r--tools/buildsteps/android-x86_64/make-depends9
-rw-r--r--tools/buildsteps/android-x86_64/make-native-depends9
-rw-r--r--tools/buildsteps/android-x86_64/make-xbmc5
-rw-r--r--tools/buildsteps/android-x86_64/package14
-rw-r--r--tools/buildsteps/android-x86_64/prepare-depends15
-rw-r--r--tools/buildsteps/android-x86_64/prepare-xbmc9
-rw-r--r--tools/buildsteps/android/configure-depends18
-rw-r--r--tools/buildsteps/android/configure-xbmc5
-rw-r--r--tools/buildsteps/android/make-binary-addons29
-rw-r--r--tools/buildsteps/android/make-depends9
-rw-r--r--tools/buildsteps/android/make-native-depends9
-rw-r--r--tools/buildsteps/android/make-xbmc5
-rw-r--r--tools/buildsteps/android/package14
-rw-r--r--tools/buildsteps/android/prepare-depends15
-rw-r--r--tools/buildsteps/android/prepare-xbmc9
-rw-r--r--tools/buildsteps/androidx86/configure-depends17
-rw-r--r--tools/buildsteps/androidx86/configure-xbmc5
-rw-r--r--tools/buildsteps/androidx86/make-binary-addons29
-rw-r--r--tools/buildsteps/androidx86/make-depends9
-rw-r--r--tools/buildsteps/androidx86/make-native-depends9
-rw-r--r--tools/buildsteps/androidx86/make-xbmc5
-rw-r--r--tools/buildsteps/androidx86/package14
-rw-r--r--tools/buildsteps/androidx86/prepare-depends15
-rw-r--r--tools/buildsteps/androidx86/prepare-xbmc9
-rw-r--r--tools/buildsteps/defaultenv183
-rw-r--r--tools/buildsteps/freebsd/configure-depends5
-rw-r--r--tools/buildsteps/freebsd/configure-xbmc7
-rw-r--r--tools/buildsteps/freebsd/make-binary-addons28
-rw-r--r--tools/buildsteps/freebsd/make-depends5
-rw-r--r--tools/buildsteps/freebsd/make-native-depends5
-rw-r--r--tools/buildsteps/freebsd/make-xbmc5
-rw-r--r--tools/buildsteps/freebsd/package5
-rw-r--r--tools/buildsteps/freebsd/prepare-depends8
-rw-r--r--tools/buildsteps/freebsd/prepare-xbmc9
-rw-r--r--tools/buildsteps/freebsd/run-tests14
-rwxr-xr-xtools/buildsteps/ios/configure-depends13
-rwxr-xr-xtools/buildsteps/ios/configure-xbmc5
-rwxr-xr-xtools/buildsteps/ios/make-binary-addons30
-rwxr-xr-xtools/buildsteps/ios/make-depends9
-rwxr-xr-xtools/buildsteps/ios/make-native-depends9
-rwxr-xr-xtools/buildsteps/ios/make-xbmc9
-rwxr-xr-xtools/buildsteps/ios/package11
-rwxr-xr-xtools/buildsteps/ios/prepare-depends15
-rwxr-xr-xtools/buildsteps/ios/prepare-xbmc9
-rw-r--r--tools/buildsteps/jenkins_docs/README.mac100
-rwxr-xr-xtools/buildsteps/linux-debian/configure-depends2
-rwxr-xr-xtools/buildsteps/linux-debian/configure-xbmc2
-rwxr-xr-xtools/buildsteps/linux-debian/make-depends2
-rwxr-xr-xtools/buildsteps/linux-debian/make-xbmc2
-rwxr-xr-xtools/buildsteps/linux-debian/package16
-rwxr-xr-xtools/buildsteps/linux-debian/prepare-depends1
-rwxr-xr-xtools/buildsteps/linux-debian/prepare-xbmc2
-rwxr-xr-xtools/buildsteps/linux/configure-depends9
-rwxr-xr-xtools/buildsteps/linux/configure-xbmc5
-rwxr-xr-xtools/buildsteps/linux/make-binary-addons28
-rwxr-xr-xtools/buildsteps/linux/make-depends9
-rwxr-xr-xtools/buildsteps/linux/make-native-depends9
-rwxr-xr-xtools/buildsteps/linux/make-xbmc5
-rwxr-xr-xtools/buildsteps/linux/package5
-rwxr-xr-xtools/buildsteps/linux/prepare-depends15
-rwxr-xr-xtools/buildsteps/linux/prepare-xbmc9
-rwxr-xr-xtools/buildsteps/linux/run-tests14
-rwxr-xr-xtools/buildsteps/osx-arm64/configure-depends13
-rwxr-xr-xtools/buildsteps/osx-arm64/configure-xbmc5
-rwxr-xr-xtools/buildsteps/osx-arm64/load-env3
-rwxr-xr-xtools/buildsteps/osx-arm64/make-binary-addons30
-rwxr-xr-xtools/buildsteps/osx-arm64/make-depends9
-rwxr-xr-xtools/buildsteps/osx-arm64/make-native-depends9
-rwxr-xr-xtools/buildsteps/osx-arm64/make-xbmc5
-rwxr-xr-xtools/buildsteps/osx-arm64/package11
-rwxr-xr-xtools/buildsteps/osx-arm64/prepare-depends15
-rwxr-xr-xtools/buildsteps/osx-arm64/prepare-xbmc9
-rwxr-xr-xtools/buildsteps/osx64/configure-depends13
-rwxr-xr-xtools/buildsteps/osx64/configure-xbmc5
-rwxr-xr-xtools/buildsteps/osx64/load-env3
-rwxr-xr-xtools/buildsteps/osx64/make-binary-addons30
-rwxr-xr-xtools/buildsteps/osx64/make-depends9
-rwxr-xr-xtools/buildsteps/osx64/make-native-depends9
-rwxr-xr-xtools/buildsteps/osx64/make-xbmc5
-rwxr-xr-xtools/buildsteps/osx64/package11
-rwxr-xr-xtools/buildsteps/osx64/prepare-depends15
-rwxr-xr-xtools/buildsteps/osx64/prepare-xbmc9
-rwxr-xr-xtools/buildsteps/osx64/run-tests10
-rwxr-xr-xtools/buildsteps/tvos/configure-depends13
-rwxr-xr-xtools/buildsteps/tvos/configure-xbmc5
-rwxr-xr-xtools/buildsteps/tvos/make-binary-addons30
-rwxr-xr-xtools/buildsteps/tvos/make-depends8
-rwxr-xr-xtools/buildsteps/tvos/make-native-depends9
-rwxr-xr-xtools/buildsteps/tvos/make-xbmc9
-rwxr-xr-xtools/buildsteps/tvos/package11
-rwxr-xr-xtools/buildsteps/tvos/prepare-depends15
-rwxr-xr-xtools/buildsteps/tvos/prepare-xbmc9
-rw-r--r--tools/buildsteps/windows/BuildSetup.bat300
-rw-r--r--tools/buildsteps/windows/arm-uwp/BuildSetup.bat19
-rw-r--r--tools/buildsteps/windows/arm-uwp/bootstrap-addons.bat11
-rw-r--r--tools/buildsteps/windows/arm-uwp/download-dependencies.bat5
-rw-r--r--tools/buildsteps/windows/arm-uwp/download-msys2.bat5
-rw-r--r--tools/buildsteps/windows/arm-uwp/make-addons.bat11
-rw-r--r--tools/buildsteps/windows/arm-uwp/make-mingwlibs.bat11
-rw-r--r--tools/buildsteps/windows/arm-uwp/prepare-env.bat5
-rw-r--r--tools/buildsteps/windows/bootstrap-addons.bat91
-rw-r--r--tools/buildsteps/windows/buildffmpeg.sh129
-rw-r--r--tools/buildsteps/windows/buildhelpers.sh216
-rw-r--r--tools/buildsteps/windows/download-dependencies.bat72
-rw-r--r--tools/buildsteps/windows/download-msys2.bat406
-rw-r--r--tools/buildsteps/windows/ffmpeg_options.txt19
-rw-r--r--tools/buildsteps/windows/getbranch.bat56
-rw-r--r--tools/buildsteps/windows/make-addons.bat169
-rw-r--r--tools/buildsteps/windows/make-mingwlibs.bat88
-rw-r--r--tools/buildsteps/windows/make-mingwlibs.sh162
-rw-r--r--tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch25
-rw-r--r--tools/buildsteps/windows/patches/0002-ffmpeg-windows-configure-fix-zlib-conflict.patch26
-rw-r--r--tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch34
-rw-r--r--tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch25
-rw-r--r--tools/buildsteps/windows/patches/readme.txt6
-rw-r--r--tools/buildsteps/windows/prepare-env.bat27
-rw-r--r--tools/buildsteps/windows/run-tests.bat70
-rw-r--r--tools/buildsteps/windows/vswhere.bat86
-rw-r--r--tools/buildsteps/windows/win32-uwp/BuildSetup.bat18
-rw-r--r--tools/buildsteps/windows/win32-uwp/bootstrap-addons.bat11
-rw-r--r--tools/buildsteps/windows/win32-uwp/download-dependencies.bat5
-rw-r--r--tools/buildsteps/windows/win32-uwp/download-msys2.bat5
-rw-r--r--tools/buildsteps/windows/win32-uwp/make-addons.bat11
-rw-r--r--tools/buildsteps/windows/win32-uwp/make-mingwlibs.bat11
-rw-r--r--tools/buildsteps/windows/win32-uwp/prepare-env.bat5
-rw-r--r--tools/buildsteps/windows/win32/BuildSetup.bat18
-rw-r--r--tools/buildsteps/windows/win32/bootstrap-addons.bat11
-rw-r--r--tools/buildsteps/windows/win32/download-dependencies.bat5
-rw-r--r--tools/buildsteps/windows/win32/download-msys2.bat5
-rw-r--r--tools/buildsteps/windows/win32/make-addons.bat11
-rw-r--r--tools/buildsteps/windows/win32/make-mingwlibs.bat11
-rw-r--r--tools/buildsteps/windows/win32/prepare-env.bat5
-rw-r--r--tools/buildsteps/windows/win32/run-tests.bat13
-rw-r--r--tools/buildsteps/windows/x64-uwp/BuildSetup.bat18
-rw-r--r--tools/buildsteps/windows/x64-uwp/bootstrap-addons.bat11
-rw-r--r--tools/buildsteps/windows/x64-uwp/download-dependencies.bat5
-rw-r--r--tools/buildsteps/windows/x64-uwp/download-msys2.bat5
-rw-r--r--tools/buildsteps/windows/x64-uwp/make-addons.bat11
-rw-r--r--tools/buildsteps/windows/x64-uwp/make-mingwlibs.bat11
-rw-r--r--tools/buildsteps/windows/x64-uwp/prepare-env.bat5
-rw-r--r--tools/buildsteps/windows/x64/BuildSetup.bat17
-rw-r--r--tools/buildsteps/windows/x64/bootstrap-addons.bat11
-rw-r--r--tools/buildsteps/windows/x64/download-dependencies.bat5
-rw-r--r--tools/buildsteps/windows/x64/download-msys2.bat5
-rw-r--r--tools/buildsteps/windows/x64/make-addons.bat11
-rw-r--r--tools/buildsteps/windows/x64/make-mingwlibs.bat11
-rw-r--r--tools/buildsteps/windows/x64/prepare-env.bat5
-rw-r--r--tools/buildsteps/windows/x64/run-tests.bat13
-rw-r--r--tools/codegenerator/Generator.groovy74
-rw-r--r--tools/codegenerator/Helper.groovy882
-rw-r--r--tools/codegenerator/SwigTypeParser.groovy617
-rw-r--r--tools/codegenerator/example/AddonModuleXbmc.i11
-rw-r--r--tools/codegenerator/example/Example-lval-rval.template18
-rw-r--r--tools/codegenerator/example/Example.call.template48
-rw-r--r--tools/codegenerator/example/Example.intypemap.template31
-rw-r--r--tools/codegenerator/example/Example.returns.template42
-rw-r--r--tools/codegenerator/example/native/ModuleXbmc.h1
-rw-r--r--tools/depends/.gitignore51
-rw-r--r--tools/depends/Makefile25
-rw-r--r--tools/depends/Makefile.include.in127
-rw-r--r--tools/depends/README.md56
-rwxr-xr-xtools/depends/bootstrap12
-rw-r--r--tools/depends/build-aux/config.guess1456
-rw-r--r--tools/depends/build-aux/config.sub1823
-rw-r--r--tools/depends/build-aux/install-sh527
-rw-r--r--tools/depends/configure.ac856
-rw-r--r--tools/depends/download-files.include59
-rw-r--r--tools/depends/m4/ax_compare_version.m4177
-rw-r--r--tools/depends/m4/ax_cxx_compile_stdcxx.m4951
-rw-r--r--tools/depends/m4/xbmc_arch.m484
-rw-r--r--tools/depends/native/JsonSchemaBuilder/CMakeLists.txt10
-rw-r--r--tools/depends/native/JsonSchemaBuilder/LICENSE.GPL287
-rw-r--r--tools/depends/native/JsonSchemaBuilder/Makefile46
-rw-r--r--tools/depends/native/JsonSchemaBuilder/README5
-rw-r--r--tools/depends/native/JsonSchemaBuilder/src/JsonSchemaBuilder.cpp176
-rw-r--r--tools/depends/native/JsonSchemaBuilder/src/Makefile.am4
-rwxr-xr-xtools/depends/native/JsonSchemaBuilder/src/autogen.sh3
-rw-r--r--tools/depends/native/JsonSchemaBuilder/src/configure.ac10
-rw-r--r--tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.sln20
-rw-r--r--tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.vcxproj85
-rw-r--r--tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.vcxproj.filters13
-rw-r--r--tools/depends/native/Makefile105
-rw-r--r--tools/depends/native/Mako/Makefile27
-rw-r--r--tools/depends/native/MarkupSafe/Makefile27
-rw-r--r--tools/depends/native/TexturePacker/CMakeLists.txt54
-rw-r--r--tools/depends/native/TexturePacker/Makefile62
-rw-r--r--tools/depends/native/TexturePacker/src/DecoderManager.cpp88
-rw-r--r--tools/depends/native/TexturePacker/src/DecoderManager.h37
-rw-r--r--tools/depends/native/TexturePacker/src/Makefile.am29
-rw-r--r--tools/depends/native/TexturePacker/src/SimpleFS.h107
-rw-r--r--tools/depends/native/TexturePacker/src/TexturePacker.cpp420
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/TexturePacker.sln22
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj144
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj.filters101
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/dirent.c145
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/dirent.h53
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/version.rcbin0 -> 5582 bytes
-rw-r--r--tools/depends/native/TexturePacker/src/XBTFWriter.cpp164
-rw-r--r--tools/depends/native/TexturePacker/src/XBTFWriter.h48
-rwxr-xr-xtools/depends/native/TexturePacker/src/autogen.sh3
-rw-r--r--tools/depends/native/TexturePacker/src/cmdlineargs.h148
-rw-r--r--tools/depends/native/TexturePacker/src/configure.ac41
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp79
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h36
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp493
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GifHelper.h220
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/IDecoder.h99
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp137
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h36
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp244
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h36
-rw-r--r--tools/depends/native/TexturePacker/src/md5.cpp231
-rw-r--r--tools/depends/native/TexturePacker/src/md5.h38
-rw-r--r--tools/depends/native/Toolchain-Native.cmake.in79
-rw-r--r--tools/depends/native/autoconf-archive/Makefile39
-rw-r--r--tools/depends/native/autoconf/Makefile40
-rw-r--r--tools/depends/native/automake/01-fix-help2man-error.patch11
-rw-r--r--tools/depends/native/automake/Makefile39
-rw-r--r--tools/depends/native/cmake/Makefile50
-rw-r--r--tools/depends/native/config.site.native.in26
-rw-r--r--tools/depends/native/dpkg/01-no-gnu-patch.patch10
-rw-r--r--tools/depends/native/dpkg/02-perl-min-version.patch11
-rw-r--r--tools/depends/native/dpkg/03-lzma-compression.patch11
-rw-r--r--tools/depends/native/dpkg/Makefile45
-rw-r--r--tools/depends/native/expat/EXPAT-VERSION5
-rw-r--r--tools/depends/native/expat/Makefile31
-rw-r--r--tools/depends/native/flatbuffers/Makefile68
-rw-r--r--tools/depends/native/gas-preprocessor/Makefile13
-rw-r--r--tools/depends/native/gas-preprocessor/README13
-rw-r--r--tools/depends/native/gas-preprocessor/VERSION4
-rwxr-xr-xtools/depends/native/gas-preprocessor/gas-preprocessor.pl1213
-rw-r--r--tools/depends/native/gettext/01-gettext-tools-stpncpy.patch11
-rw-r--r--tools/depends/native/gettext/02-disable-test-doc.patch11
-rw-r--r--tools/depends/native/gettext/Makefile62
-rw-r--r--tools/depends/native/giflib/01-static-lib.patch12
-rw-r--r--tools/depends/native/giflib/Makefile40
-rw-r--r--tools/depends/native/heimdal/01-disable-libedit.patch11
-rw-r--r--tools/depends/native/heimdal/02-autoconf-2.70-configure.patch11
-rw-r--r--tools/depends/native/heimdal/Makefile43
-rw-r--r--tools/depends/native/ldid/01-disable-openssl-plist.patch21
-rw-r--r--tools/depends/native/ldid/Makefile37
-rw-r--r--tools/depends/native/libffi/Makefile43
-rw-r--r--tools/depends/native/libjpeg-turbo/01-disable-executables.patch118
-rw-r--r--tools/depends/native/libjpeg-turbo/LIBJPEG-TURBO-VERSION4
-rw-r--r--tools/depends/native/libjpeg-turbo/Makefile38
-rw-r--r--tools/depends/native/liblzo2/Makefile41
-rw-r--r--tools/depends/native/libpng/Makefile41
-rw-r--r--tools/depends/native/libtool/Makefile41
-rw-r--r--tools/depends/native/m4/Makefile38
-rw-r--r--tools/depends/native/meson/Makefile35
-rw-r--r--tools/depends/native/nasm/Makefile39
-rw-r--r--tools/depends/native/ninja/Makefile33
-rw-r--r--tools/depends/native/openssl/Makefile54
-rw-r--r--tools/depends/native/pcre/Makefile44
-rw-r--r--tools/depends/native/perlmodule-parseyapp/Makefile43
-rw-r--r--tools/depends/native/pkg-config/Makefile45
-rw-r--r--tools/depends/native/pugixml/Makefile43
-rw-r--r--tools/depends/native/python3/01-distutil-flags.patch12
-rw-r--r--tools/depends/native/python3/Makefile46
-rw-r--r--tools/depends/native/python3/PYTHON3-VERSION4
-rw-r--r--tools/depends/native/swig/Makefile41
-rw-r--r--tools/depends/native/tar/Makefile45
-rw-r--r--tools/depends/native/wayland-scanner/Makefile39
-rw-r--r--tools/depends/native/waylandpp-scanner/Makefile47
-rw-r--r--tools/depends/native/xz/Makefile30
-rw-r--r--tools/depends/native/xz/XZ-VERSION4
-rw-r--r--tools/depends/native/zlib/Makefile40
-rw-r--r--tools/depends/native/zlib/visibility.patch15
-rw-r--r--tools/depends/pre-depends/autoconf-pre-depends/Makefile43
-rw-r--r--tools/depends/pre-depends/m4-pre-depends/Makefile41
-rw-r--r--tools/depends/target/crossguid/CROSSGUID-VERSION6
-rw-r--r--tools/depends/target/dav1d/DAV1D-VERSION5
-rw-r--r--tools/depends/target/expat/EXPAT-VERSION6
-rw-r--r--tools/depends/target/ffmpeg/FFMPEG-VERSION5
-rw-r--r--tools/depends/target/flatbuffers/FLATBUFFERS-VERSION4
-rw-r--r--tools/depends/target/fmt/FMT-VERSION6
-rw-r--r--tools/depends/target/fontconfig/FONTCONFIG-VERSION7
-rw-r--r--tools/depends/target/freetype2-noharfbuzz/FREETYPE2-NOHARFBUZZ-VERSION5
-rw-r--r--tools/depends/target/freetype2/FREETYPE2-VERSION5
-rw-r--r--tools/depends/target/fribidi/FRIBIDI-VERSION5
-rw-r--r--tools/depends/target/fstrcmp/FSTRCMP-VERSION5
-rw-r--r--tools/depends/target/gtest/GTEST-VERSION5
-rw-r--r--tools/depends/target/libandroidjni/LIBANDROIDJNI-VERSION6
-rw-r--r--tools/depends/target/libbluray/LIBBLURAY-VERSION5
-rw-r--r--tools/depends/target/libdvdcss/LIBDVDCSS-VERSION7
-rw-r--r--tools/depends/target/libdvdnav/LIBDVDNAV-VERSION7
-rw-r--r--tools/depends/target/libdvdread/LIBDVDREAD-VERSION7
-rw-r--r--tools/depends/target/libffi/LIBFFI-VERSION4
-rw-r--r--tools/depends/target/libgcrypt/LIBGCRYPT-VERSION5
-rw-r--r--tools/depends/target/libgpg-error/LIBGPG-ERROR-VERSION5
-rw-r--r--tools/depends/target/libjpeg-turbo/LIBJPEG-TURBO-VERSION4
-rw-r--r--tools/depends/target/liblzo2/LIBLZO2-VERSION6
-rw-r--r--tools/depends/target/libmicrohttpd/LIBMICROHTTPD-VERSION4
-rw-r--r--tools/depends/target/libnfs/LIBNFS-VERSION6
-rw-r--r--tools/depends/target/libpng/LIBPNG-VERSION5
-rw-r--r--tools/depends/target/libxml2/LIBXML2-VERSION5
-rw-r--r--tools/depends/target/libzip/LIBZIP-VERSION5
-rw-r--r--tools/depends/target/mariadb/MARIADB-VERSION4
-rw-r--r--tools/depends/target/nghttp2/NGHTTP2-VERSION5
-rw-r--r--tools/depends/target/pcre/PCRE-VERSION6
-rw-r--r--tools/depends/target/python3/PYTHON3-VERSION4
-rw-r--r--tools/depends/target/pythonmodule-pil/PYTHONMODULE-PIL-VERSION4
-rw-r--r--tools/depends/target/pythonmodule-pycryptodome/PYTHONMODULE-PYCRYPTODOME-VERSION4
-rw-r--r--tools/depends/target/pythonmodule-setuptools/PYTHONMODULE-SETUPTOOLS-VERSION4
-rw-r--r--tools/depends/target/rapidjson/RAPIDJSON-VERSION4
-rw-r--r--tools/depends/target/samba-gplv3/SAMBA-GPLV3-VERSION4
-rw-r--r--tools/depends/target/spdlog/SPDLOG-VERSION6
-rw-r--r--tools/depends/target/sqlite3/SQLITE3-VERSION4
-rw-r--r--tools/depends/target/taglib/TAGLIB-VERSION6
-rw-r--r--tools/depends/target/udfread/UDFREAD-VERSION5
-rw-r--r--tools/depends/target/xz/XZ-VERSION4
-rw-r--r--tools/depends/target/zlib/ZLIB-VERSION5
-rw-r--r--tools/depends/xbmc-addons.include133
-rw-r--r--tools/static-analysis/cppcheck/cppcheck-rules.xml10
-rw-r--r--tools/static-analysis/cppcheck/cppcheck-suppressions.xml19
450 files changed, 36012 insertions, 0 deletions
diff --git a/tools/EventClients/Clients/KodiSend/kodi-send.py b/tools/EventClients/Clients/KodiSend/kodi-send.py
new file mode 100755
index 0000000..2760b11
--- /dev/null
+++ b/tools/EventClients/Clients/KodiSend/kodi-send.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python3
+#
+# XBMC Media Center
+# XBMC Send
+# Copyright (c) 2009 team-xbmc
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import sys, os
+import getopt
+from socket import *
+from time import sleep
+try:
+ from kodi.xbmcclient import *
+except:
+ sys.path.append(os.path.join(os.path.realpath(os.path.dirname(__file__)), '../../lib/python'))
+ from xbmcclient import *
+
+TYPE_MOUSE = 'mouse'
+TYPE_NOTIFICATION = 'notification'
+TYPE_LOG = 'log'
+TYPE_ACTION = 'action'
+TYPE_BUTTON = 'button'
+TYPE_DELAY = 'delay'
+
+log_map = {
+ "LOGDEBUG": LOGDEBUG,
+ "LOGINFO": LOGINFO,
+ "LOGWARNING": LOGWARNING,
+ "LOGERROR": LOGERROR,
+ "LOGFATAL": LOGFATAL,
+}
+
+def usage():
+ print("Usage")
+ print("\tkodi-send [OPTION] --action=ACTION")
+ print("\tkodi-send [OPTION] --button=BUTTON")
+ print('Example')
+ print('\tkodi-send --host=192.168.0.1 --port=9777 --action="Quit"')
+ print("Options")
+ print("\t-?, --help\t\t\tWill bring up this message")
+ print("\t--host=HOST\t\t\tChoose what HOST to connect to (default=localhost)")
+ print("\t--port=PORT\t\t\tChoose what PORT to connect to (default=9777)")
+ print("\t--keymap=KEYMAP\t\t\tChoose which KEYMAP to use for key presses (default=KB)")
+ print('\t--button=BUTTON\t\t\tSends a key press event to Kodi, this option can be added multiple times to create a macro')
+ print('\t--mouse=X,Y\t\t\tSends the mouse position to Kodi')
+ print("\t--log=MESSAGE\t\t\tSends a log message to Kodi")
+ print("\t--loglevel=LEVEL\t\tSets the log level when using --log= (default=LOGDEBUG)")
+ print("\t--notification=MESSAGE\t\tSends a notification to Kodi")
+ print('\t-a ACTION, --action=ACTION\tSends an action to Kodi, this option can be added multiple times to create a macro')
+ print('\t-d T, --delay=T\t\t\tWaits for T ms, this option can be added multiple times to create a macro')
+ pass
+
+def main():
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "?pa:d:v", ["help", "host=", "port=", "keymap=", "button=", "mouse=", "log=", "loglevel=", "notification=", "action=", "delay="])
+ except getopt.GetoptError as err:
+ # print help information and exit:
+ print(str(err)) # will print something like "option -a not recognized"
+ usage()
+ sys.exit(2)
+ ip = "localhost"
+ port = 9777
+ keymap = "KB"
+ loglevel = LOGDEBUG
+ actions = []
+ verbose = False
+ for o, a in opts:
+ if o in ("-?", "--help"):
+ usage()
+ sys.exit()
+ elif o == "--host":
+ ip = a
+ elif o == "--port":
+ port = int(a)
+ elif o == "--keymap":
+ keymap = a
+ elif o == "--button":
+ actions.append({'type': TYPE_BUTTON, 'content': a})
+ elif o == "--mouse":
+ actions.append({'type': TYPE_MOUSE, 'content': a})
+ elif o == "--log":
+ actions.append({'type': TYPE_LOG, 'content': a})
+ elif o == "--loglevel":
+ loglevel = log_map.get(a)
+ elif o == "--notification":
+ actions.append({'type': TYPE_NOTIFICATION, 'content': a})
+ elif o in ("-a", "--action"):
+ actions.append({'type': TYPE_ACTION, 'content': a})
+ elif o in ("-d", "--delay"):
+ actions.append({'type': TYPE_DELAY, 'content': int(a)})
+ else:
+ assert False, "unhandled option"
+
+ addr = (ip, port)
+ sock = socket(AF_INET,SOCK_DGRAM)
+
+ if len(actions) == 0:
+ usage()
+ sys.exit(0)
+
+ for action in actions:
+ print('Sending: %s' % action)
+ if action['type'] == TYPE_ACTION:
+ packet = PacketACTION(actionmessage=action['content'], actiontype=ACTION_BUTTON)
+ elif action['type'] == TYPE_BUTTON:
+ packet = PacketBUTTON(code=0, repeat=0, down=1, queue=1, map_name=keymap, button_name=action['content'], amount=0)
+ elif action['type'] == TYPE_MOUSE:
+ x = int(action['content'].split(',')[0])
+ y = int(action['content'].split(',')[1])
+ packet = PacketMOUSE(x=x, y=y)
+ elif action['type'] == TYPE_DELAY:
+ time.sleep(action['content'] / 1000.0)
+ continue
+ elif action['type'] == TYPE_LOG:
+ packet = PacketLOG(loglevel=loglevel, logmessage=action['content'], autoprint=False)
+ elif action['type'] == TYPE_NOTIFICATION:
+ packet = PacketNOTIFICATION(title='kodi-send', message=action['content'])
+ packet.send(sock, addr, uid=0)
+
+if __name__=="__main__":
+ main()
diff --git a/tools/EventClients/Clients/PS3BDRemote/ps3_remote.py b/tools/EventClients/Clients/PS3BDRemote/ps3_remote.py
new file mode 100755
index 0000000..72ae71a
--- /dev/null
+++ b/tools/EventClients/Clients/PS3BDRemote/ps3_remote.py
@@ -0,0 +1,219 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2008-2013 Team XBMC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# This is a quick port of brandonj's PS3 remote script to use the event server
+# for sending input events.
+#
+# The original script and documentation regarding the remote can be found at:
+# http://forum.kodi.tv/showthread.php?tid=28765
+#
+#
+# TODO:
+# 1. Send keepalive ping at least once every 60 seconds to prevent timeouts
+# 2. Permanent pairing
+# 3. Detect if Kodi has been restarted (non trivial until broadcasting is
+# implemented, until then maybe the HELO packet could be used instead of
+# PING as keepalive
+#
+
+import sys
+
+try:
+ # try loading modules from source directory
+ sys.path.append("../../lib/python")
+ from xbmcclient import *
+ from ps3.keymaps import keymap_remote as g_keymap # look here to change the keymapping
+ from bt.bt import *
+ ICON_PATH = "../../icons/"
+except:
+ # fallback to system wide modules
+ from kodi.xbmcclient import *
+ from kodi.ps3.keymaps import keymap_remote as g_keymap # look here to change the keymapping
+ from kodi.bt.bt import *
+ from kodi.defs import *
+
+import os
+import time
+
+xbmc = None
+bticon = ICON_PATH + "/bluetooth.png"
+
+def get_remote_address(remote, target_name = "BD Remote Control"):
+ global xbmc
+ target_connected = False
+ target_address = None
+ while target_connected is False:
+ xbmc.send_notification("Action Required!",
+ "Hold Start+Enter on your remote.",
+ bticon)
+ print("Searching for %s" % target_name)
+ print("(Hold Start + Enter on remote to make it discoverable)")
+ time.sleep(2)
+
+ if not target_address:
+ try:
+ nearby_devices = bt_discover_devices()
+ except Exception as e:
+ print("Error performing bluetooth discovery")
+ print(str(e))
+ xbmc.send_notification("Error", "Unable to find devices.", bticon)
+ time.sleep(5)
+ continue
+
+ for bdaddr in nearby_devices:
+ bname = bt_lookup_name( bdaddr )
+ addr = bt_lookup_addr ( bdaddr )
+ print("%s (%s) in range" % (bname,addr))
+ if target_name == bname:
+ target_address = addr
+ break
+
+ if target_address is not None:
+ print("Found %s with address %s" % (target_name, target_address))
+ xbmc.send_notification("Found Device",
+ "Pairing %s, please wait." % target_name,
+ bticon)
+ print("Attempting to pair with remote")
+
+ try:
+ remote.connect((target_address,19))
+ target_connected = True
+ print("Remote Paired.\a")
+ xbmc.send_notification("Pairing Successful",
+ "Your remote was successfully "\
+ "paired and is ready to be used.",
+ bticon)
+ except:
+ del remote
+ remote = bt_create_socket()
+ target_address = None
+ xbmc.send_notification("Pairing Failed",
+ "An error occurred while attempting to "\
+ "pair.", bticon)
+ print("ERROR - Could Not Connect. Trying again...")
+ time.sleep(2)
+ else:
+ xbmc.send_notification("Error", "No remotes were found.", bticon)
+ print("Could not find BD Remote Control. Trying again...")
+ time.sleep(2)
+ return (remote,target_address)
+
+
+def usage():
+ print("""
+PS3 Blu-Ray Remote Control Client for XBMC v0.1
+
+Usage: ps3_remote.py <address> [port]
+
+ address => address of system that XBMC is running on
+ ("localhost" if it is this machine)
+
+ port => port to send packets to
+ (default 9777)
+""")
+
+def process_keys(remote, xbmc):
+ """
+ Return codes:
+ 0 - key was processed normally
+ 2 - socket read timeout
+ 3 - PS and then Skip Plus was pressed (sequentially)
+ 4 - PS and then Skip Minus was pressed (sequentially)
+
+ FIXME: move to enums
+ """
+ done = 0
+
+ try:
+ xbmc.previous_key
+ except:
+ xbmc.previous_key = ""
+
+ xbmc.connect()
+ datalen = 0
+ try:
+ data = remote.recv(1024)
+ datalen = len(data)
+ except Exception as e:
+ if str(e)=="timed out":
+ return 2
+ time.sleep(2)
+
+ # some other read exception occurred, so raise it
+ raise e
+
+ if datalen == 13:
+ keycode = data.hex()[10:12]
+ if keycode == "ff":
+ xbmc.release_button()
+ return done
+ try:
+ # if the user presses the PS button followed by skip + or skip -
+ # return different codes.
+ if xbmc.previous_key == "43":
+ xbmc.previous_key = keycode
+ if keycode == "31": # skip +
+ return 3
+ elif keycode == "30": # skip -
+ return 4
+
+ # save previous key press
+ xbmc.previous_key = keycode
+
+ if g_keymap[keycode]:
+ xbmc.send_remote_button(g_keymap[keycode])
+ except Exception as e:
+ print("Unknown data: %s" % str(e))
+ return done
+
+def main():
+ global xbmc, bticon
+
+ host = "127.0.0.1"
+ port = 9777
+
+ if len(sys.argv)>1:
+ try:
+ host = sys.argv[1]
+ port = sys.argv[2]
+ except:
+ pass
+ else:
+ return usage()
+
+ loop_forever = True
+ xbmc = XBMCClient("PS3 Bluetooth Remote",
+ icon_file=bticon)
+
+ while loop_forever is True:
+ target_connected = False
+ remote = bt_create_socket()
+ xbmc.connect(host, port)
+ (remote,target_address) = get_remote_address(remote)
+ while True:
+ if process_keys(remote, xbmc):
+ break
+ print("Disconnected.")
+ try:
+ remote.close()
+ except:
+ print("Cannot close.")
+
+if __name__=="__main__":
+ main()
diff --git a/tools/EventClients/Clients/PS3SixaxisController/README.ubuntu b/tools/EventClients/Clients/PS3SixaxisController/README.ubuntu
new file mode 100644
index 0000000..bf4a5a4
--- /dev/null
+++ b/tools/EventClients/Clients/PS3SixaxisController/README.ubuntu
@@ -0,0 +1 @@
+sudo apt-get install python-usb python-pyudev python-bluez
diff --git a/tools/EventClients/Clients/PS3SixaxisController/ps3d.py b/tools/EventClients/Clients/PS3SixaxisController/ps3d.py
new file mode 100755
index 0000000..32ed361
--- /dev/null
+++ b/tools/EventClients/Clients/PS3SixaxisController/ps3d.py
@@ -0,0 +1,406 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2008-2013 Team XBMC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import sys
+import traceback
+import time
+import struct
+import threading
+import os
+
+if os.path.exists("../../lib/python"):
+ sys.path.append("../PS3BDRemote")
+ sys.path.append("../../lib/python")
+ from bt.hid import HID
+ from bt.bt import bt_lookup_name
+ from xbmcclient import XBMCClient
+ from ps3 import sixaxis
+ from ps3_remote import process_keys as process_remote
+ try:
+ from ps3 import sixwatch
+ except Exception as e:
+ print("Failed to import sixwatch now disabled: " + str(e))
+ sixwatch = None
+
+ try:
+ import zeroconf
+ except:
+ zeroconf = None
+ ICON_PATH = "../../icons/"
+else:
+ # fallback to system wide modules
+ from kodi.bt.hid import HID
+ from kodi.bt.bt import bt_lookup_name
+ from kodi.xbmcclient import XBMCClient
+ from kodi.ps3 import sixaxis
+ from kodi.ps3_remote import process_keys as process_remote
+ from kodi.defs import *
+ try:
+ from kodi.ps3 import sixwatch
+ except Exception as e:
+ print("Failed to import sixwatch now disabled: " + str(e))
+ sixwatch = None
+ try:
+ import kodi.zeroconf as zeroconf
+ except:
+ zeroconf = None
+
+
+event_threads = []
+
+def printerr():
+ trace = ""
+ exception = ""
+ exc_list = traceback.format_exception_only (sys.exc_type, sys.exc_value)
+ for entry in exc_list:
+ exception += entry
+ tb_list = traceback.format_tb(sys.exc_info()[2])
+ for entry in tb_list:
+ trace += entry
+ print("%s\n%s" % (exception, trace), "Script Error")
+
+
+class StoppableThread ( threading.Thread ):
+ def __init__(self):
+ threading.Thread.__init__(self)
+ self._stop = False
+ self.set_timeout(0)
+
+ def stop_thread(self):
+ self._stop = True
+
+ def stop(self):
+ return self._stop
+
+ def close_sockets(self):
+ if self.isock:
+ try:
+ self.isock.close()
+ except:
+ pass
+ self.isock = None
+ if self.csock:
+ try:
+ self.csock.close()
+ except:
+ pass
+ self.csock = None
+ self.last_action = 0
+
+ def set_timeout(self, seconds):
+ self.timeout = seconds
+
+ def reset_timeout(self):
+ self.last_action = time.time()
+
+ def idle_time(self):
+ return time.time() - self.last_action
+
+ def timed_out(self):
+ if (time.time() - self.last_action) > self.timeout:
+ return True
+ else:
+ return False
+
+
+class PS3SixaxisThread ( StoppableThread ):
+ def __init__(self, csock, isock, ipaddr="127.0.0.1"):
+ StoppableThread.__init__(self)
+ self.csock = csock
+ self.isock = isock
+ self.xbmc = XBMCClient(name="PS3 Sixaxis", icon_file=ICON_PATH + "/bluetooth.png", ip=ipaddr)
+ self.set_timeout(600)
+
+ def run(self):
+ six = sixaxis.sixaxis(self.xbmc, self.csock, self.isock)
+ self.xbmc.connect()
+ self.reset_timeout()
+ try:
+ while not self.stop():
+
+ if self.timed_out():
+ raise Exception("PS3 Sixaxis powering off, timed out")
+ if self.idle_time() > 50:
+ self.xbmc.connect()
+ try:
+ if six.process_socket(self.isock):
+ self.reset_timeout()
+ except Exception as e:
+ print(e)
+ break
+
+ except Exception as e:
+ printerr()
+ six.close()
+ self.close_sockets()
+
+
+class PS3RemoteThread ( StoppableThread ):
+ def __init__(self, csock, isock, ipaddr="127.0.0.1"):
+ StoppableThread.__init__(self)
+ self.csock = csock
+ self.isock = isock
+ self.xbmc = XBMCClient(name="PS3 Blu-Ray Remote", icon_file=ICON_PATH + "/bluetooth.png", ip=ipaddr)
+ self.set_timeout(600)
+ self.services = []
+ self.current_xbmc = 0
+
+ def run(self):
+ self.xbmc.connect()
+ try:
+ # start the zeroconf thread if possible
+ try:
+ self.zeroconf_thread = ZeroconfThread()
+ self.zeroconf_thread.add_service('_xbmc-events._udp',
+ self.zeroconf_service_handler)
+ self.zeroconf_thread.start()
+ except Exception as e:
+ print(str(e))
+
+ # main thread loop
+ while not self.stop():
+ status = process_remote(self.isock, self.xbmc)
+
+ if status == 2: # 2 = socket read timeout
+ if self.timed_out():
+ raise Exception("PS3 Blu-Ray Remote powering off, "\
+ "timed out")
+ elif status == 3: # 3 = ps and skip +
+ self.next_xbmc()
+
+ elif status == 4: # 4 = ps and skip -
+ self.previous_xbmc()
+
+ elif not status: # 0 = keys are normally processed
+ self.reset_timeout()
+
+ # process_remote() will raise an exception on read errors
+ except Exception as e:
+ print(str(e))
+
+ self.zeroconf_thread.stop()
+ self.close_sockets()
+
+ def next_xbmc(self):
+ """
+ Connect to the next XBMC instance
+ """
+ self.current_xbmc = (self.current_xbmc + 1) % len( self.services )
+ self.reconnect()
+ return
+
+ def previous_xbmc(self):
+ """
+ Connect to the previous XBMC instance
+ """
+ self.current_xbmc -= 1
+ if self.current_xbmc < 0 :
+ self.current_xbmc = len( self.services ) - 1
+ self.reconnect()
+ return
+
+ def reconnect(self):
+ """
+ Reconnect to an XBMC instance based on self.current_xbmc
+ """
+ try:
+ service = self.services[ self.current_xbmc ]
+ print("Connecting to %s" % service['name'])
+ self.xbmc.connect( service['address'], service['port'] )
+ self.xbmc.send_notification("PS3 Blu-Ray Remote", "New Connection", None)
+ except Exception as e:
+ print(str(e))
+
+ def zeroconf_service_handler(self, event, service):
+ """
+ Zeroconf event handler
+ """
+ if event == zeroconf.SERVICE_FOUND: # new xbmc service detected
+ self.services.append( service )
+
+ elif event == zeroconf.SERVICE_LOST: # xbmc service lost
+ try:
+ # search for the service by name, since IP+port isn't available
+ for s in self.services:
+ # nuke it, if found
+ if service['name'] == s['name']:
+ self.services.remove(s)
+ break
+ except:
+ pass
+ return
+
+class SixWatch(threading.Thread):
+ def __init__(self, mac):
+ threading.Thread.__init__(self)
+ self.mac = mac
+ self.daemon = True
+ self.start()
+ def run(self):
+ while True:
+ try:
+ sixwatch.main(self.mac)
+ except Exception as e:
+ print("Exception caught in sixwatch, restarting: " + str(e))
+
+class ZeroconfThread ( threading.Thread ):
+ """
+
+ """
+ def __init__(self):
+ threading.Thread.__init__(self)
+ self._zbrowser = None
+ self._services = []
+
+ def run(self):
+ if zeroconf:
+ # create zeroconf service browser
+ self._zbrowser = zeroconf.Browser()
+
+ # add the requested services
+ for service in self._services:
+ self._zbrowser.add_service( service[0], service[1] )
+
+ # run the event loop
+ self._zbrowser.run()
+
+ return
+
+
+ def stop(self):
+ """
+ Stop the zeroconf browser
+ """
+ try:
+ self._zbrowser.stop()
+ except:
+ pass
+ return
+
+ def add_service(self, type, handler):
+ """
+ Add a new service to search for.
+ NOTE: Services must be added before thread starts.
+ """
+ self._services.append( [ type, handler ] )
+
+
+def usage():
+ print("""
+PS3 Sixaxis / Blu-Ray Remote HID Server v0.1
+
+Usage: ps3.py [bdaddress] [XBMC host]
+
+ bdaddress => address of local bluetooth device to use (default: auto)
+ (e.g. aa:bb:cc:dd:ee:ff)
+ ip address => IP address or hostname of the XBMC instance (default: localhost)
+ (e.g. 192.168.1.110)
+""")
+
+def start_hidd(bdaddr=None, ipaddr="127.0.0.1"):
+ devices = [ 'PLAYSTATION(R)3 Controller',
+ 'BD Remote Control' ]
+ hid = HID(bdaddr)
+ watch = None
+ if sixwatch:
+ try:
+ print("Starting USB sixwatch")
+ watch = SixWatch(hid.get_local_address())
+ except Exception as e:
+ print("Failed to initialize sixwatch" + str(e))
+ pass
+
+ while True:
+ if hid.listen():
+ (csock, addr) = hid.get_control_socket()
+ device_name = bt_lookup_name(addr[0])
+ if device_name == devices[0]:
+ # handle PS3 controller
+ handle_ps3_controller(hid, ipaddr)
+ elif device_name == devices[1]:
+ # handle the PS3 remote
+ handle_ps3_remote(hid, ipaddr)
+ else:
+ print("Unknown Device: %s" % (device_name))
+
+def handle_ps3_controller(hid, ipaddr):
+ print("Received connection from a Sixaxis PS3 Controller")
+ csock = hid.get_control_socket()[0]
+ isock = hid.get_interrupt_socket()[0]
+ sixaxis = PS3SixaxisThread(csock, isock, ipaddr)
+ add_thread(sixaxis)
+ sixaxis.start()
+ return
+
+def handle_ps3_remote(hid, ipaddr):
+ print("Received connection from a PS3 Blu-Ray Remote")
+ csock = hid.get_control_socket()[0]
+ isock = hid.get_interrupt_socket()[0]
+ isock.settimeout(1)
+ remote = PS3RemoteThread(csock, isock, ipaddr)
+ add_thread(remote)
+ remote.start()
+ return
+
+def add_thread(thread):
+ global event_threads
+ event_threads.append(thread)
+
+def main():
+ if len(sys.argv)>3:
+ return usage()
+ bdaddr = ""
+ ipaddr = "127.0.0.1"
+ try:
+ for addr in sys.argv[1:]:
+ try:
+ # ensure that the addr is of the format 'aa:bb:cc:dd:ee:ff'
+ if "".join([ str(len(a)) for a in addr.split(":") ]) != "222222":
+ raise Exception("Invalid format")
+ bdaddr = addr
+ print("Connecting to Bluetooth device: %s" % bdaddr)
+ except Exception as e:
+ try:
+ ipaddr = addr
+ print("Connecting to : %s" % ipaddr)
+ except:
+ print(str(e))
+ return usage()
+ except Exception as e:
+ pass
+
+ print("Starting HID daemon")
+ start_hidd(bdaddr, ipaddr)
+
+if __name__=="__main__":
+ try:
+ main()
+ finally:
+ for t in event_threads:
+ try:
+ print("Waiting for thread "+str(t)+" to terminate")
+ t.stop_thread()
+ if t.isAlive():
+ t.join()
+ print("Thread "+str(t)+" terminated")
+
+ except Exception as e:
+ print(str(e))
+ pass
+
diff --git a/tools/EventClients/Clients/WiiRemote/CMakeLists.txt b/tools/EventClients/Clients/WiiRemote/CMakeLists.txt
new file mode 100644
index 0000000..8c797b2
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/CMakeLists.txt
@@ -0,0 +1,23 @@
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
+
+find_package(Bluetooth REQUIRED)
+find_package(CWiid REQUIRED)
+find_package(GLU REQUIRED)
+
+set(SOURCES CWIID_WiiRemote.cpp)
+
+set(HEADERS CWIID_WiiRemote.h)
+
+add_executable(${APP_NAME_LC}-wiiremote ${SOURCES} ${HEADERS})
+
+target_include_directories(${APP_NAME_LC}-wiiremote
+ PRIVATE ${BLUETOOTH_INCLUDE_DIRS}
+ ${CWIID_INCLUDE_DIRS})
+
+target_link_libraries(${APP_NAME_LC}-wiiremote
+ PRIVATE ${SYSTEM_LDFLAGS}
+ ${BLUETOOTH_LIBRARIES}
+ ${CWIID_LIBRARIES})
+
+target_compile_options(${APP_NAME_LC}-wiiremote PRIVATE ${ARCH_DEFINES})
+
diff --git a/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.cpp b/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.cpp
new file mode 100644
index 0000000..19ff811
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.cpp
@@ -0,0 +1,778 @@
+/*
+ * Copyright (C) 2007 by Tobias Arrskog
+ * topfs@tobias
+ *
+ * Copyright (C) 2007-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+// Compiles with g++ WiiRemote.cpp -lcwiid -o WiiRemote
+// Preferably with libcwiid >= 6.0
+
+#include "CWIID_WiiRemote.h"
+
+#include <unistd.h>
+
+bool g_AllowReconnect = true;
+bool g_AllowMouse = true;
+bool g_AllowNunchuck = true;
+
+CPacketHELO *g_Ping = NULL;
+
+#ifndef ICON_PATH
+#define ICON_PATH "../../"
+#endif
+std::string g_BluetoothIconPath = std::string(ICON_PATH) + std::string("/bluetooth.png");
+
+int32_t getTicks()
+{
+ int32_t ticks;
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ ticks = now.tv_sec * 1000l;
+ ticks += now.tv_usec / 1000l;
+ return ticks;
+}
+
+CWiiRemote g_WiiRemote;
+
+#ifdef CWIID_OLD
+void CWiiRemote::MessageCallback(cwiid_wiimote_t *wiiremote, int mesg_count, union cwiid_mesg mesg[])
+{
+ MessageCallback(wiiremote, mesg_count, mesg, NULL);
+}
+#endif
+
+/* The MessageCallback for the Wiiremote.
+ This callback is used for error reports, mainly to see if the connection has been broken
+ This callback is also used for getting the IR sources, if this is done in update as with
+ buttons we usually only get 1 IR source at a time which is much harder to calculate */
+void CWiiRemote::MessageCallback(cwiid_wiimote_t *wiiremote, int mesg_count, union cwiid_mesg mesg[], struct timespec *timestamp)
+{
+ for (int i=0; i < mesg_count; i++)
+ {
+ int valid_source;
+ switch (mesg[i].type)
+ {
+ case CWIID_MESG_IR:
+ valid_source = 0;
+ for (int j = 0; j < CWIID_IR_SRC_COUNT; j++)
+ {
+ if (mesg[i].ir_mesg.src[j].valid)
+ valid_source++;
+ }
+ if (valid_source == 2)
+ {
+ g_WiiRemote.CalculateMousePointer(mesg[i].ir_mesg.src[0].pos[CWIID_X],
+ mesg[i].ir_mesg.src[0].pos[CWIID_Y],
+ mesg[i].ir_mesg.src[1].pos[CWIID_X],
+ mesg[i].ir_mesg.src[1].pos[CWIID_Y]);
+ }
+ else if (valid_source > 2)
+ { //TODO Make this care with the strength of the sources
+ g_WiiRemote.CalculateMousePointer(mesg[i].ir_mesg.src[0].pos[CWIID_X],
+ mesg[i].ir_mesg.src[0].pos[CWIID_Y],
+ mesg[i].ir_mesg.src[1].pos[CWIID_X],
+ mesg[i].ir_mesg.src[1].pos[CWIID_Y]);
+ }
+ break;
+ case CWIID_MESG_ERROR:
+ g_WiiRemote.DisconnectNow(true);
+ break;
+ case CWIID_MESG_BTN:
+ g_WiiRemote.ProcessKey(mesg[i].btn_mesg.buttons);
+ break;
+ case CWIID_MESG_STATUS:
+ //Here we can figure out Extension types and such
+ break;
+ case CWIID_MESG_NUNCHUK:
+ g_WiiRemote.ProcessNunchuck(mesg[i].nunchuk_mesg);
+ break;
+ case CWIID_MESG_ACC:
+ case CWIID_MESG_BALANCE:
+ case CWIID_MESG_CLASSIC:
+ case CWIID_MESG_MOTIONPLUS:
+ //Not implemented
+ break;
+ case CWIID_MESG_UNKNOWN:
+ //...
+ break;
+ }
+ }
+#ifdef CWIID_OLD
+ g_WiiRemote.CheckIn();
+#endif
+}
+
+#ifndef _DEBUG
+/* This takes the errors generated at pre-connect and silence them as they are mostly not needed */
+void CWiiRemote::ErrorCallback(struct wiimote *wiiremote, const char *str, va_list ap)
+{
+ //Error checking
+}
+#endif
+
+//Constructor
+/*This constructor is never used but it shows how one would connect to just a specific Wiiremote by Mac-Address*/
+CWiiRemote::CWiiRemote(char *wii_btaddr)
+{
+ SetBluetoothAddress(wii_btaddr);
+ m_SamplesX = NULL;
+ m_SamplesY = NULL;
+
+ m_JoyMap = NULL;
+}
+
+//Destructor
+CWiiRemote::~CWiiRemote()
+{
+ if (m_connected == true)
+ this->DisconnectNow(false);
+
+ if (m_SamplesY != NULL)
+ free(m_SamplesY);
+ if (m_SamplesX != NULL)
+ free(m_SamplesX);
+
+ if (m_JoyMap)
+ free(m_JoyMap);
+}
+
+//---------------------Public-------------------------------------------------------------------
+/* Basically this just sets up standard control bits */
+void CWiiRemote::SetBluetoothAddress(const char *btaddr)
+{
+ static const bdaddr_t b = {{0, 0, 0, 0, 0, 0}}; /* BDADDR_ANY */
+ if (btaddr != NULL)
+ str2ba(btaddr, &m_btaddr);
+ else
+ bacpy(&m_btaddr, &b);
+}
+
+void CWiiRemote::SetSensitivity(float DeadX, float DeadY, int NumSamples)
+{
+ m_NumSamples = NumSamples;
+
+ m_MinX = MOUSE_MAX * DeadX;
+ m_MinY = MOUSE_MAX * DeadY;
+
+ m_MaxX = MOUSE_MAX * (1.0f + DeadX + DeadX);
+ m_MaxY = MOUSE_MAX * (1.0f + DeadY + DeadY);
+
+ if (m_SamplesY != NULL)
+ delete [] m_SamplesY;
+ if (m_SamplesX != NULL)
+ delete [] m_SamplesX;
+
+ m_SamplesY = new int[m_NumSamples];
+ m_SamplesX = new int[m_NumSamples];
+}
+
+void CWiiRemote::SetJoystickMap(const char *JoyMap)
+{
+ if (m_JoyMap)
+ free(m_JoyMap);
+ if (JoyMap != NULL)
+ {
+ m_JoyMap = (char*)malloc(strlen(JoyMap) + 5);
+ sprintf(m_JoyMap, "JS0:%s", JoyMap);
+ }
+ else
+ m_JoyMap = strdup("JS0:WiiRemote");
+}
+
+void CWiiRemote::Initialize(CAddress Addr, int Socket)
+{
+ m_connected = false;
+ m_lastKeyPressed = 0;
+ m_LastKey = 0;
+ m_buttonRepeat = false;
+ m_lastKeyPressedNunchuck = 0;
+ m_LastKeyNunchuck = 0;
+ m_buttonRepeatNunchuck = false;
+ m_useIRMouse = true;
+ m_rptMode = 0;
+
+ m_Socket = Socket;
+ m_MyAddr = Addr;
+
+ m_NumSamples = WIIREMOTE_SAMPLES;
+
+ m_MaxX = WIIREMOTE_X_MAX;
+ m_MaxY = WIIREMOTE_Y_MAX;
+ m_MinX = WIIREMOTE_X_MIN;
+ m_MinY = WIIREMOTE_Y_MIN;
+#ifdef CWIID_OLD
+ m_LastMsgTime = getTicks();
+#endif
+
+ //All control bits are set to false when cwiid is started
+ //Report Button presses
+ ToggleBit(m_rptMode, CWIID_RPT_BTN);
+ if (g_AllowNunchuck)
+ ToggleBit(m_rptMode, CWIID_RPT_NUNCHUK);
+
+ //If wiiremote is used as a mouse, then report the IR sources
+#ifndef CWIID_OLD
+ if (m_useIRMouse)
+#endif
+ ToggleBit(m_rptMode, CWIID_RPT_IR);
+
+ //Have the first and fourth LED on the Wiiremote shine when connected
+ ToggleBit(m_ledState, CWIID_LED1_ON);
+ ToggleBit(m_ledState, CWIID_LED4_ON);
+}
+
+/* Update is run regularly and we gather the state of the Wiiremote and see if the user have pressed on a button or moved the wiiremote
+ This could have been done with callbacks instead but it doesn't look nice in C++*/
+void CWiiRemote::Update()
+{
+ if (m_DisconnectWhenPossible)
+ {//If the user has chosen to disconnect or lost communication
+ DisconnectNow(true);
+ m_DisconnectWhenPossible = false;
+ }
+#ifdef CWIID_OLD
+ if(m_connected)
+ {//Here we check if the connection is suddenly broken
+ if (!CheckConnection())
+ {
+ DisconnectNow(true);
+ return;
+ }
+ }
+#endif
+}
+
+/* Enable mouse emulation */
+void CWiiRemote::EnableMouseEmulation()
+{
+ if (m_useIRMouse)
+ return;
+
+ m_useIRMouse = true;
+
+#ifndef CWIID_OLD
+ //We toggle IR Reporting (Save resources?)
+ if (!(m_rptMode & CWIID_RPT_IR))
+ ToggleBit(m_rptMode, CWIID_RPT_IR);
+ if (m_connected)
+ SetRptMode();
+#endif
+
+ CPacketLOG log(LOGDEBUG, "Enabled WiiRemote mouse emulation");
+ log.Send(m_Socket, m_MyAddr);
+}
+/* Disable mouse emulation */
+void CWiiRemote::DisableMouseEmulation()
+{
+ if (!m_useIRMouse)
+ return;
+
+ m_useIRMouse = false;
+#ifndef CWIID_OLD
+ //We toggle IR Reporting (Save resources?)
+ if (m_rptMode & CWIID_RPT_IR)
+ ToggleBit(m_rptMode, CWIID_RPT_IR);
+ if (m_connected)
+ SetRptMode();
+#endif
+
+ CPacketLOG log(LOGDEBUG, "Disabled WiiRemote mouse emulation");
+ log.Send(m_Socket, m_MyAddr);
+}
+
+/* Is a wiiremote connected*/
+bool CWiiRemote::GetConnected()
+{
+ return m_connected;
+}
+
+/* Disconnect ASAP*/
+void CWiiRemote::Disconnect()
+{ //This is always called from a criticalsection
+ if (m_connected)
+ m_DisconnectWhenPossible = true;
+}
+
+#ifdef CWIID_OLD
+/* This function is mostly a hack as CWIID < 6.0 doesn't report on disconnects, this function is called everytime
+ a message is sent to the callback (Will be once every 10 ms or so) this is to see if the connection is interrupted. */
+void CWiiRemote::CheckIn()
+{ //This is always called from a criticalsection
+ m_LastMsgTime = getTicks();
+}
+#endif
+
+//---------------------Private-------------------------------------------------------------------
+/* Connect is designed to be run in a different thread as it only
+ exits if wiiremote is either disabled or a connection is made*/
+bool CWiiRemote::Connect()
+{
+#ifndef _DEBUG
+ cwiid_set_err(ErrorCallback);
+#endif
+ while (!m_connected)
+ {
+ g_Ping->Send(m_Socket, m_MyAddr);
+ int flags = 0;
+ ToggleBit(flags, CWIID_FLAG_MESG_IFC);
+ ToggleBit(flags, CWIID_FLAG_REPEAT_BTN);
+
+ m_wiiremoteHandle = cwiid_connect(&m_btaddr, flags);
+ if (m_wiiremoteHandle != NULL)
+ {
+ SetupWiiRemote();
+ // get battery state etc.
+ cwiid_state wiiremote_state;
+ int err = cwiid_get_state(m_wiiremoteHandle, &wiiremote_state);
+ if (!err)
+ {
+ char Mesg[1024];
+ sprintf(Mesg, "%i%% battery remaining", static_cast<int>(((float)(wiiremote_state.battery)/CWIID_BATTERY_MAX)*100.0));
+ CPacketNOTIFICATION notification("Wii Remote connected", Mesg, ICON_PNG, g_BluetoothIconPath.c_str());
+ notification.Send(m_Socket, m_MyAddr);
+ }
+ else
+ {
+ printf("Problem probing for status of WiiRemote; cwiid_get_state returned non-zero\n");
+ CPacketLOG log(
+ LOGINFO, "Problem probing for status of WiiRemote; cwiid_get_state returned non-zero");
+ log.Send(m_Socket, m_MyAddr);
+ CPacketNOTIFICATION notification("Wii Remote connected", "", ICON_PNG, g_BluetoothIconPath.c_str());
+ notification.Send(m_Socket, m_MyAddr);
+ }
+#ifdef CWIID_OLD
+ /* CheckIn to say that this is the last msg, If this isn't called it could give issues if we Connects -> Disconnect and then try to connect again
+ the CWIID_OLD hack would automatically disconnect the wiiremote as the lastmsg is too old. */
+ CheckIn();
+#endif
+ m_connected = true;
+
+ CPacketLOG log(LOGINFO, "Successfully connected a WiiRemote");
+ log.Send(m_Socket, m_MyAddr);
+ return true;
+ }
+ //Here's a good place to have a quit flag check...
+
+ }
+ return false;
+}
+
+/* Disconnect */
+void CWiiRemote::DisconnectNow(bool startConnectThread)
+{
+ if (m_connected) //It shouldn't be enabled at the same time as it is connected
+ {
+ cwiid_disconnect(m_wiiremoteHandle);
+
+ if (g_AllowReconnect)
+ {
+ CPacketNOTIFICATION notification("Wii Remote disconnected", "Press 1 and 2 to reconnect", ICON_PNG, g_BluetoothIconPath.c_str());
+ notification.Send(m_Socket, m_MyAddr);
+ }
+ else
+ {
+ CPacketNOTIFICATION notification("Wii Remote disconnected", "", ICON_PNG, g_BluetoothIconPath.c_str());
+ notification.Send(m_Socket, m_MyAddr);
+ }
+
+ CPacketLOG log(LOGINFO, "Successfully disconnected a WiiRemote");
+ log.Send(m_Socket, m_MyAddr);
+ }
+ m_connected = false;
+}
+
+#ifdef CWIID_OLD
+/* This is a harsh check if there really is a connection, It will mainly be used in CWIID < 6.0
+ as it doesn't report connect error, which is needed to see if the Wiiremote suddenly disconnected.
+ This could possible be done with bluetooth specific queries but I cannot find how to do it. */
+bool CWiiRemote::CheckConnection()
+{
+ if ((getTicks() - m_LastMsgTime) > 1000)
+ {
+ CPacketLOG log(LOGINFO, "Lost connection to the WiiRemote");
+ log.Send(m_Socket, m_MyAddr);
+ return false;
+ }
+ else
+ return true;
+}
+#endif
+
+/* Sets rpt mode when a new wiiremote is connected */
+void CWiiRemote::SetupWiiRemote()
+{ //Lights up the appropriate led and setups the rapport mode, so buttons and IR work
+ SetRptMode();
+ SetLedState();
+
+ for (int i = 0; i < WIIREMOTE_SAMPLES; i++)
+ {
+ m_SamplesX[i] = 0;
+ m_SamplesY[i] = 0;
+ }
+
+ if (cwiid_set_mesg_callback(m_wiiremoteHandle, MessageCallback))
+ {
+ CPacketLOG log(LOGERROR, "Unable to set message callback to the WiiRemote");
+ log.Send(m_Socket, m_MyAddr);
+ }
+}
+
+void CWiiRemote::ProcessKey(int Key)
+{
+ if (Key != m_LastKey)
+ {
+ m_LastKey = Key;
+ m_lastKeyPressed = getTicks();
+ m_buttonRepeat = false;
+ }
+ else
+ {
+ if (m_buttonRepeat)
+ {
+ if (getTicks() - m_lastKeyPressed > WIIREMOTE_BUTTON_REPEAT_TIME)
+ m_lastKeyPressed = getTicks();
+ else
+ return;
+ }
+ else
+ {
+ if (getTicks() - m_lastKeyPressed > WIIREMOTE_BUTTON_DELAY_TIME)
+ {
+ m_buttonRepeat = true;
+ m_lastKeyPressed = getTicks();
+ }
+ else
+ return;
+ }
+ }
+
+ int RtnKey = -1;
+
+ if (Key == CWIID_BTN_UP)
+ RtnKey = 1;
+ else if (Key == CWIID_BTN_RIGHT)
+ RtnKey = 4;
+ else if (Key == CWIID_BTN_LEFT)
+ RtnKey = 3;
+ else if (Key == CWIID_BTN_DOWN)
+ RtnKey = 2;
+
+ else if (Key == CWIID_BTN_A)
+ RtnKey = 5;
+ else if (Key == CWIID_BTN_B)
+ RtnKey = 6;
+
+ else if (Key == CWIID_BTN_MINUS)
+ RtnKey = 7;
+ else if (Key == CWIID_BTN_PLUS)
+ RtnKey = 9;
+
+ else if (Key == CWIID_BTN_HOME)
+ RtnKey = 8;
+
+ else if (Key == CWIID_BTN_1)
+ RtnKey = 10;
+ else if (Key == CWIID_BTN_2)
+ RtnKey = 11;
+
+ if (RtnKey != -1)
+ {
+ CPacketBUTTON btn(RtnKey, m_JoyMap, BTN_QUEUE | BTN_NO_REPEAT);
+ btn.Send(m_Socket, m_MyAddr);
+ }
+}
+
+void CWiiRemote::ProcessNunchuck(struct cwiid_nunchuk_mesg &Nunchuck)
+{
+ if (Nunchuck.stick[0] > 135)
+ { //R
+ int x = (int)((((float)Nunchuck.stick[0] - 135.0f) / 95.0f) * 65535.0f);
+ printf("Right: %i\n", x);
+ CPacketBUTTON btn(24, m_JoyMap, (BTN_QUEUE | BTN_DOWN), x);
+ btn.Send(m_Socket, m_MyAddr);
+ }
+ else if (Nunchuck.stick[0] < 125)
+ { //L
+ int x = (int)((((float)Nunchuck.stick[0] - 125.0f) / 90.0f) * -65535.0f);
+ printf("Left: %i\n", x);
+ CPacketBUTTON btn(23, m_JoyMap, (BTN_QUEUE | BTN_DOWN), x);
+ btn.Send(m_Socket, m_MyAddr);
+ }
+
+ if (Nunchuck.stick[1] > 130)
+ { //U
+ int x = (int)((((float)Nunchuck.stick[1] - 130.0f) / 92.0f) * 65535.0f);
+ printf("Up: %i\n", x);
+ CPacketBUTTON btn(21, m_JoyMap, (BTN_QUEUE | BTN_DOWN), x);
+ btn.Send(m_Socket, m_MyAddr);
+ }
+ else if (Nunchuck.stick[1] < 120)
+ { //D
+ int x = (int)((((float)Nunchuck.stick[1] - 120.0f) / 90.0f) * -65535.0f);
+ printf("Down: %i\n", x);
+ CPacketBUTTON btn(22, m_JoyMap, (BTN_QUEUE | BTN_DOWN), x);
+ btn.Send(m_Socket, m_MyAddr);
+ }
+
+ if (Nunchuck.buttons != m_LastKeyNunchuck)
+ {
+ m_LastKeyNunchuck = Nunchuck.buttons;
+ m_lastKeyPressedNunchuck = getTicks();
+ m_buttonRepeatNunchuck = false;
+ }
+ else
+ {
+ if (m_buttonRepeatNunchuck)
+ {
+ if (getTicks() - m_lastKeyPressedNunchuck > WIIREMOTE_BUTTON_REPEAT_TIME)
+ m_lastKeyPressedNunchuck = getTicks();
+ else
+ return;
+ }
+ else
+ {
+ if (getTicks() - m_lastKeyPressedNunchuck > WIIREMOTE_BUTTON_DELAY_TIME)
+ {
+ m_buttonRepeatNunchuck = true;
+ m_lastKeyPressedNunchuck = getTicks();
+ }
+ else
+ return;
+ }
+ }
+
+ int RtnKey = -1;
+
+ if (Nunchuck.buttons == CWIID_NUNCHUK_BTN_C)
+ RtnKey = 25;
+ else if (Nunchuck.buttons == CWIID_NUNCHUK_BTN_Z)
+ RtnKey = 26;
+
+ if (RtnKey != -1)
+ {
+ CPacketBUTTON btn(RtnKey, m_JoyMap, BTN_QUEUE | BTN_NO_REPEAT);
+ btn.Send(m_Socket, m_MyAddr);
+ }
+}
+
+/* Tell cwiid which data will be reported */
+void CWiiRemote::SetRptMode()
+{ //Sets our wiiremote to report something, for example IR, Buttons
+#ifdef CWIID_OLD
+ if (cwiid_command(m_wiiremoteHandle, CWIID_CMD_RPT_MODE, m_rptMode))
+#else
+ if (cwiid_set_rpt_mode(m_wiiremoteHandle, m_rptMode))
+#endif
+ {
+ CPacketLOG log(LOGERROR, "Error setting WiiRemote report mode");
+ log.Send(m_Socket, m_MyAddr);
+ }
+}
+/* Tell cwiid the LED states */
+void CWiiRemote::SetLedState()
+{ //Sets our leds on the wiiremote
+#ifdef CWIID_OLD
+ if (cwiid_command(m_wiiremoteHandle, CWIID_CMD_LED, m_ledState))
+#else
+ if (cwiid_set_led(m_wiiremoteHandle, m_ledState))
+#endif
+ {
+ CPacketLOG log(LOGERROR, "Error setting WiiRemote LED state");
+ log.Send(m_Socket, m_MyAddr);
+ }
+}
+
+/* Calculate the mousepointer from 2 IR sources (Default) */
+void CWiiRemote::CalculateMousePointer(int x1, int y1, int x2, int y2)
+{
+ int x3, y3;
+
+ x3 = ( (x1 + x2) / 2 );
+ y3 = ( (y1 + y2) / 2 );
+
+ x3 = (int)( ((float)x3 / (float)CWIID_IR_X_MAX) * m_MaxX);
+ y3 = (int)( ((float)y3 / (float)CWIID_IR_Y_MAX) * m_MaxY);
+
+ x3 = (int)(x3 - m_MinX);
+ y3 = (int)(y3 - m_MinY);
+
+ if (x3 < MOUSE_MIN) x3 = MOUSE_MIN;
+ else if (x3 > MOUSE_MAX) x3 = MOUSE_MAX;
+
+ if (y3 < MOUSE_MIN) y3 = MOUSE_MIN;
+ else if (y3 > MOUSE_MAX) y3 = MOUSE_MAX;
+
+ x3 = MOUSE_MAX - x3;
+
+ if (m_NumSamples == 1)
+ {
+ CPacketMOUSE mouse(x3, y3);
+ mouse.Send(m_Socket, m_MyAddr);
+ return;
+ }
+ else
+ {
+ for (int i = m_NumSamples; i > 0; i--)
+ {
+ m_SamplesX[i] = m_SamplesX[i-1];
+ m_SamplesY[i] = m_SamplesY[i-1];
+ }
+
+ m_SamplesX[0] = x3;
+ m_SamplesY[0] = y3;
+
+ long x4 = 0, y4 = 0;
+
+ for (int i = 0; i < m_NumSamples; i++)
+ {
+ x4 += m_SamplesX[i];
+ y4 += m_SamplesY[i];
+ }
+ CPacketMOUSE mouse((x4 / m_NumSamples), (y4 / m_NumSamples));
+ mouse.Send(m_Socket, m_MyAddr);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void PrintHelp(const char *Prog)
+{
+ printf("Commands:\n");
+ printf("\t--disable-mouseemulation\n\t--disable-reconnect\n\t--disable-nunchuck\n");
+ printf("\t--address ADDRESS\n\t--port PORT\n");
+ printf("\t--btaddr MACADDRESS\n");
+ printf("\t--deadzone-x DEADX | Number between 0 - 100 (Default: %i)\n", (int)(DEADZONE_X * 100));
+ printf("\t--deadzone-y DEADY | Number between 0 - 100 (Default: %i)\n", (int)(DEADZONE_Y * 100));
+ printf("\t--deadzone DEAD | Sets both X and Y too the number\n");
+ printf("\t--smoothing-samples SAMPLE | Number 1 counts as Off (Default: %i)\n", WIIREMOTE_SAMPLES);
+ printf("\t--joystick-map JOYMAP | The string ID for the joymap (Default: WiiRemote)\n");
+}
+
+int main(int argc, char **argv)
+{
+ char *Address = NULL;
+ char *btaddr = NULL;
+ int Port = 9777;
+
+ int NumSamples = WIIREMOTE_SAMPLES;
+ float DeadX = DEADZONE_X;
+ float DeadY = DEADZONE_Y;
+
+ char *JoyMap = NULL;
+
+ for (int i = 0; i < argc; i++)
+ {
+ if (strcmp(argv[i], "--help") == 0)
+ {
+ PrintHelp(argv[0]);
+ return 0;
+ }
+ else if (strcmp(argv[i], "--disable-mouseemulation") == 0)
+ g_AllowMouse = false;
+ else if (strcmp(argv[i], "--disable-reconnect") == 0)
+ g_AllowReconnect = false;
+ else if (strcmp(argv[i], "--disable-nunchuck") == 0)
+ g_AllowNunchuck = false;
+ else if (strcmp(argv[i], "--address") == 0 && ((i + 1) <= argc))
+ Address = argv[i + 1];
+ else if (strcmp(argv[i], "--port") == 0 && ((i + 1) <= argc))
+ Port = atoi(argv[i + 1]);
+ else if (strcmp(argv[i], "--btaddr") == 0 && ((i + 1) <= argc))
+ btaddr = argv[i + 1];
+ else if (strcmp(argv[i], "--deadzone-x") == 0 && ((i + 1) <= argc))
+ DeadX = ((float)atoi(argv[i + 1]) / 100.0f);
+ else if (strcmp(argv[i], "--deadzone-y") == 0 && ((i + 1) <= argc))
+ DeadY = ((float)atoi(argv[i + 1]) / 100.0f);
+ else if (strcmp(argv[i], "--deadzone") == 0 && ((i + 1) <= argc))
+ DeadX = DeadY = ((float)atoi(argv[i + 1]) / 100.0f);
+ else if (strcmp(argv[i], "--smoothing-samples") == 0 && ((i + 1) <= argc))
+ NumSamples = atoi(argv[i + 1]);
+ else if (strcmp(argv[i], "--joystick-map") == 0 && ((i + 1) <= argc))
+ JoyMap = argv[i + 1];
+ }
+
+ if (NumSamples < 1 || DeadX < 0 || DeadY < 0 || DeadX > 1 || DeadY > 1)
+ {
+ PrintHelp(argv[0]);
+ return -1;
+ }
+
+ CAddress my_addr(Address, Port); // Address => localhost on 9777
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ {
+ printf("Error creating socket\n");
+ return -1;
+ }
+
+ if (hci_get_route(NULL) < 0)
+ {
+ CPacketLOG log(LOGERROR, "Error No bluetooth device");
+ log.Send(sockfd, my_addr);
+ return -1;
+ }
+ g_Ping = new CPacketHELO("WiiRemote", ICON_PNG, g_BluetoothIconPath.c_str());
+ g_WiiRemote.Initialize(my_addr, sockfd);
+ g_WiiRemote.SetBluetoothAddress(btaddr);
+ g_WiiRemote.SetSensitivity(DeadX, DeadY, NumSamples);
+ g_WiiRemote.SetSensitivity(DeadX, DeadY, NumSamples);
+ g_WiiRemote.SetJoystickMap(JoyMap);
+ if (g_AllowMouse)
+ g_WiiRemote.EnableMouseEmulation();
+ else
+ g_WiiRemote.DisableMouseEmulation();
+
+ g_Ping->Send(sockfd, my_addr);
+ bool HaveConnected = false;
+ while (true)
+ {
+ bool Connected = g_WiiRemote.GetConnected();
+
+ while (!Connected)
+ {
+ if (HaveConnected && !g_AllowReconnect)
+ exit(0);
+
+ Connected = g_WiiRemote.Connect();
+ HaveConnected = true;
+ }
+#ifdef CWIID_OLD
+// Update the state of the WiiRemote more often when we have the old lib due too it not telling when disconnected..
+ sleep (5);
+#else
+ sleep (15);
+#endif
+ g_Ping->Send(sockfd, my_addr);
+ g_WiiRemote.Update();
+ }
+}
diff --git a/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.h b/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.h
new file mode 100644
index 0000000..58d051e
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/CWIID_WiiRemote.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2007 by Tobias Arrskog
+ * topfs@tobias
+ *
+ * Copyright (C) 2007-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+/* Toggle one bit */
+#define ToggleBit(bf,b) (bf) = ((bf) & b) ? ((bf) & ~(b)) : ((bf) | (b))
+
+//Settings
+#define WIIREMOTE_SAMPLES 16
+
+#define DEADZONE_Y 0.3f
+#define DEADZONE_X 0.5f
+
+#define MOUSE_MAX 65535
+#define MOUSE_MIN 0
+
+//The work area is from 0 - MAX but the one sent to XBMC is MIN - (MIN + MOUSE_MAX)
+#define WIIREMOTE_X_MIN MOUSE_MAX * DEADZONE_X
+#define WIIREMOTE_Y_MIN MOUSE_MAX * DEADZONE_Y
+
+#define WIIREMOTE_X_MAX MOUSE_MAX * (1.0f + DEADZONE_X + DEADZONE_X)
+#define WIIREMOTE_Y_MAX MOUSE_MAX * (1.0f + DEADZONE_Y + DEADZONE_Y)
+
+#define WIIREMOTE_BUTTON_REPEAT_TIME 30 // How long between buttonpresses in repeat mode
+#define WIIREMOTE_BUTTON_DELAY_TIME 500
+//#define CWIID_OLD // Uncomment if the system is running cwiid that is older than 6.0 (The one from ubuntu gutsy repository is < 6.0)
+
+//CWIID
+#include <cwiid.h>
+//Bluetooth specific
+#include <sys/socket.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+// UDP Client
+#ifdef DEB_PACK
+#include <xbmc/xbmcclient.h>
+#else
+#include "../../lib/c++/xbmcclient.h"
+#endif
+/*#include <stdio.h>*/
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <string>
+
+class CWiiRemote
+{
+public:
+ CWiiRemote(char *btaddr = NULL);
+ ~CWiiRemote();
+
+ void Initialize(CAddress Addr, int Socket);
+ void Disconnect();
+ bool GetConnected();
+
+ bool EnableWiiRemote();
+ bool DisableWiiRemote();
+
+ void Update();
+
+ // Mouse functions
+ bool HaveIRSources();
+ bool isActive();
+ void EnableMouseEmulation();
+ void DisableMouseEmulation();
+
+ bool Connect();
+
+ void SetBluetoothAddress(const char * btaddr);
+ void SetSensitivity(float DeadX, float DeadY, int Samples);
+ void SetJoystickMap(const char *JoyMap);
+private:
+ int m_NumSamples;
+ int *m_SamplesX;
+ int *m_SamplesY;
+
+ float m_MaxX;
+ float m_MaxY;
+ float m_MinX;
+ float m_MinY;
+#ifdef CWIID_OLD
+ bool CheckConnection();
+ int m_LastMsgTime;
+#endif
+ char *m_JoyMap;
+ int m_lastKeyPressed;
+ int m_LastKey;
+ bool m_buttonRepeat;
+
+ int m_lastKeyPressedNunchuck;
+ int m_LastKeyNunchuck;
+ bool m_buttonRepeatNunchuck;
+
+ void SetRptMode();
+ void SetLedState();
+
+ void SetupWiiRemote();
+
+ bool m_connected;
+
+ bool m_DisconnectWhenPossible;
+ bool m_connectThreadRunning;
+
+ //CWIID Specific
+ cwiid_wiimote_t *m_wiiremoteHandle;
+ unsigned char m_ledState;
+ unsigned char m_rptMode;
+ bdaddr_t m_btaddr;
+
+ static void MessageCallback(cwiid_wiimote_t *wiiremote, int mesgCount, union cwiid_mesg mesg[], struct timespec *timestamp);
+#ifdef CWIID_OLD
+ static void MessageCallback(cwiid_wiimote_t *wiiremote, int mesgCount, union cwiid_mesg mesg[]);
+#endif
+
+#ifndef _DEBUG
+/* This takes the errors generated at pre-connect and silence them as they are mostly not needed */
+ static void ErrorCallback(struct wiimote *wiiremote, const char *str, va_list ap);
+#endif
+
+ int m_Socket;
+ CAddress m_MyAddr;
+
+ // Mouse
+ bool m_haveIRSources;
+ bool m_isActive;
+ bool m_useIRMouse;
+ int m_lastActiveTime;
+
+/* The protected functions is for the static callbacks */
+ protected:
+ //Connection
+ void DisconnectNow(bool startConnectThread);
+
+ //Mouse
+ void CalculateMousePointer(int x1, int y1, int x2, int y2);
+// void SetIR(bool set);
+
+ //Button
+ void ProcessKey(int Key);
+
+ //Nunchuck
+ void ProcessNunchuck(struct cwiid_nunchuk_mesg &Nunchuck);
+#ifdef CWIID_OLD
+ //Disconnect check
+ void CheckIn();
+#endif
+};
+
+extern CWiiRemote g_WiiRemote;
diff --git a/tools/EventClients/Clients/WiiRemote/Makefile b/tools/EventClients/Clients/WiiRemote/Makefile
new file mode 100644
index 0000000..eba0f1e
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/Makefile
@@ -0,0 +1,14 @@
+CXX ?= g++
+CFLAGS = -Wall -pipe -fPIC -funroll-loops
+OBJ_DIR = release-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2)
+OBJS = wiiuse_v0.12/src/$(OBJ_DIR)/libwiiuse.so
+BIN = WiiUse_WiiRemote
+VERSION = v0.12
+
+all:
+ @$(MAKE) -C wiiuse_$(VERSION)/src $@
+ $(CXX) $(CFLAGS) -I./wiiuse_$(VERSION)/src WiiUse_WiiRemote.cpp $(OBJS) -o $(BIN)
+wiiuse:
+ @$(MAKE) -C wiiuse_$(VERSION)/src
+clean:
+ rm $(OBJS) $(BIN)
diff --git a/tools/EventClients/Clients/WiiRemote/WiiUse_README b/tools/EventClients/Clients/WiiRemote/WiiUse_README
new file mode 100644
index 0000000..5749697
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/WiiUse_README
@@ -0,0 +1,18 @@
+To compile the WiiRemote event client:
+
+$ sudo apt-get install libbluetooth-dev
+$ make
+
+NOTE: if you get a permission denied error when make'ing the event client, you may need to use root,
+e.g. $ sudo make
+
+make will create an executable called WiiUse_WiiRemote that contains the event client.
+
+WiiUse_WiiRemote must be run from this directory as it uses relative linking to the built wiiuse_v0.12 library.
+
+WiiUse_WiiRemote.h contains the button number mappings for the WiiRemote (prefixed with KEYCODE).
+
+TODO:
+Add IR pointer support
+
+TheUni + dteirney \ No newline at end of file
diff --git a/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.cpp b/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.cpp
new file mode 100644
index 0000000..48f5a1a
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.cpp
@@ -0,0 +1,265 @@
+ /* Copyright (C) 2009 by Cory Fields
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#include "WiiUse_WiiRemote.h"
+
+void CWiiController::get_keys(wiimote* wm)
+{
+ m_buttonHeld = 0;
+ m_buttonPressed = 0;
+ m_buttonReleased = 0;
+
+ m_repeatableHeld = (wm->btns & (m_repeatFlags));
+ m_holdableHeld = (wm->btns & (m_holdFlags));
+ m_repeatableReleased = (wm->btns_released & (m_repeatFlags));
+ m_holdableReleased = (wm->btns_released & (m_holdFlags));
+
+ for (int i = 1;i <= WIIMOTE_NUM_BUTTONS; i++)
+ {
+ if (IS_PRESSED(wm,convert_code(i)))
+ m_buttonPressed = i;
+ if (IS_RELEASED(wm,convert_code(i)))
+ m_buttonReleased = i;
+ if (IS_HELD(wm,convert_code(i)))
+ m_buttonHeld = i;
+ }
+}
+
+void CWiiController::handleKeyPress()
+{
+ if ((m_holdableReleased && m_buttonDownTime < g_hold_button_timeout))
+ EventClient.SendButton(m_buttonReleased, m_joyString, BTN_QUEUE | BTN_NO_REPEAT);
+ if (m_buttonPressed && !m_holdableHeld && !m_buttonHeld)
+ EventClient.SendButton(m_buttonPressed, m_joyString, BTN_QUEUE | BTN_NO_REPEAT);
+}
+
+void CWiiController::handleRepeat()
+{
+ if (m_repeatableHeld)
+ EventClient.SendButton(m_buttonPressed, m_joyString, BTN_QUEUE | BTN_NO_REPEAT, 5);
+}
+
+void CWiiController::handleACC(float currentRoll, float currentPitch)
+{
+ int rollWeight = 0;
+ int tiltWeight = 0;
+
+ if (m_start_roll == 0)
+ m_start_roll = currentRoll;
+ m_abs_roll = smoothDeg(m_abs_roll, currentRoll);
+ m_rel_roll = m_abs_roll - m_start_roll;
+ rollWeight = int((m_rel_roll*m_rel_roll));
+ if (rollWeight > 65000)
+ rollWeight = 65000;
+
+ if (m_start_pitch == 0)
+ m_start_pitch = currentPitch;
+ m_abs_pitch = smoothDeg(m_abs_pitch, currentPitch);
+ m_rel_pitch = m_start_pitch - m_abs_pitch;
+ tiltWeight = int((m_rel_pitch*m_rel_pitch*16));
+ if (tiltWeight > 65000)
+ tiltWeight = 65000;
+
+ if (m_currentAction == ACTION_NONE)
+ {
+ if ((g_deadzone - (abs((int)m_rel_roll)) < 5) && (abs((int)m_abs_pitch) < (g_deadzone / 1.5)))
+ // crossed the roll deadzone threshold while inside the pitch deadzone
+ {
+ m_currentAction = ACTION_ROLL;
+ }
+ else if ((g_deadzone - (abs((int)m_rel_pitch)) < 5) && (abs((int)m_abs_roll) < (g_deadzone / 1.5)))
+ // crossed the pitch deadzone threshold while inside the roll deadzone
+ {
+ m_currentAction = ACTION_PITCH;
+ }
+ }
+
+ if (m_currentAction == ACTION_ROLL)
+ {
+ if (m_rel_roll < -g_deadzone)
+ EventClient.SendButton(KEYCODE_ROLL_NEG, m_joyString, BTN_QUEUE | BTN_NO_REPEAT, rollWeight);
+ if (m_rel_roll > g_deadzone)
+ EventClient.SendButton(KEYCODE_ROLL_POS, m_joyString, BTN_QUEUE | BTN_NO_REPEAT, rollWeight);
+// printf("Roll: %f\n",m_rel_roll);
+ }
+
+ if (m_currentAction == ACTION_PITCH)
+ {
+ if (m_rel_pitch > g_deadzone)
+ EventClient.SendButton(KEYCODE_PITCH_POS, m_joyString, BTN_QUEUE | BTN_NO_REPEAT,tiltWeight);
+ if (m_rel_pitch < -g_deadzone)
+ EventClient.SendButton(KEYCODE_PITCH_NEG, m_joyString, BTN_QUEUE | BTN_NO_REPEAT,tiltWeight);
+// printf("Pitch: %f\n",m_rel_pitch);
+ }
+}
+
+void CWiiController::handleIR()
+{
+//TODO
+}
+
+int connectWiimote(wiimote** wiimotes)
+{
+ int found = 0;
+ int connected = 0;
+ wiimote* wm;
+ while(!found)
+ {
+ //Look for Wiimotes. Keep searching until one is found. Wiiuse provides no way to search forever, so search for 5 secs and repeat.
+ found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5);
+ }
+ connected = wiiuse_connect(wiimotes, MAX_WIIMOTES);
+ wm = wiimotes[0];
+ if (connected)
+ {
+ EventClient.SendHELO("Wii Remote", ICON_PNG, NULL);
+ wiiuse_set_leds(wm, WIIMOTE_LED_1);
+ wiiuse_rumble(wm, 1);
+ wiiuse_set_orient_threshold(wm,1);
+ DisableMotionSensing(wm);
+ #ifndef WIN32
+ usleep(200000);
+ #else
+ Sleep(200);
+ #endif
+ wiiuse_rumble(wm, 0);
+
+ return 1;
+ }
+ return 0;
+}
+
+int handle_disconnect(wiimote* wm)
+{
+ EventClient.SendNOTIFICATION("Wii Remote disconnected", "", ICON_PNG, NULL);
+ return 0;
+}
+
+unsigned short convert_code(unsigned short client_code)
+{
+//WIIMOTE variables are from wiiuse. We need them to be 1-11 for the eventclient.
+//For that we use this ugly conversion.
+
+ switch (client_code)
+ {
+ case KEYCODE_BUTTON_UP: return WIIMOTE_BUTTON_UP;
+ case KEYCODE_BUTTON_DOWN: return WIIMOTE_BUTTON_DOWN;
+ case KEYCODE_BUTTON_LEFT: return WIIMOTE_BUTTON_LEFT;
+ case KEYCODE_BUTTON_RIGHT: return WIIMOTE_BUTTON_RIGHT;
+ case KEYCODE_BUTTON_A: return WIIMOTE_BUTTON_A;
+ case KEYCODE_BUTTON_B: return WIIMOTE_BUTTON_B;
+ case KEYCODE_BUTTON_MINUS: return WIIMOTE_BUTTON_MINUS;
+ case KEYCODE_BUTTON_HOME: return WIIMOTE_BUTTON_HOME;
+ case KEYCODE_BUTTON_PLUS: return WIIMOTE_BUTTON_PLUS;
+ case KEYCODE_BUTTON_ONE: return WIIMOTE_BUTTON_ONE;
+ case KEYCODE_BUTTON_TWO: return WIIMOTE_BUTTON_TWO;
+ default : break;
+ }
+return 0;
+}
+
+float smoothDeg(float oldVal, float newVal)
+{
+//If values go over 180 or under -180, weird things happen. This transforms the values to -360 to 360 instead.
+
+ if (newVal - oldVal > 300)
+ return (newVal - 360);
+ if (oldVal - newVal > 300)
+ return(newVal + 360);
+ return(newVal);
+}
+
+int32_t getTicks(void)
+{
+ int32_t ticks;
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ ticks = now.tv_sec * 1000l;
+ ticks += now.tv_usec / 1000l;
+ return ticks;
+}
+
+int main(int argc, char** argv)
+{
+ int32_t timeout = 0;
+ bool connected = 0;
+ wiimote** wiimotes;
+ wiimotes = wiiuse_init(MAX_WIIMOTES);
+ CWiiController controller;
+ wiimote* wm;
+ {
+ //Main Loop
+ while (1)
+ {
+ if (!connected) connected = (connectWiimote(wiimotes));
+ wm = wiimotes[0]; // Only worry about 1 controller. No need for more?
+ controller.m_buttonDownTime = getTicks() - timeout;
+
+//Handle ACC, Repeat, and IR outside of the Event loop so that buttons can be continuously sent
+ if (timeout)
+ {
+ if ((controller.m_buttonDownTime > g_hold_button_timeout) && controller.m_holdableHeld)
+ controller.handleACC(wm->orient.roll, wm->orient.pitch);
+ if ((controller.m_buttonDownTime > g_repeat_rate) && controller.m_repeatableHeld)
+ controller.handleRepeat();
+ }
+ if (wiiuse_poll(wiimotes, MAX_WIIMOTES))
+ {
+ for (int i = 0; i < MAX_WIIMOTES; ++i)
+ //MAX_WIIMOTES hardcoded at 1.
+ {
+ DisableMotionSensing(wm);
+ switch (wiimotes[i]->event)
+ {
+ case WIIUSE_EVENT:
+
+ controller.get_keys(wm); //Load up the CWiiController
+ controller.handleKeyPress();
+ if (!controller.m_buttonHeld && (controller.m_holdableHeld || controller.m_repeatableHeld))
+ {
+ //Prepare to repeat or hold. Do this only once.
+ timeout = getTicks();
+ controller.m_abs_roll = 0;
+ controller.m_abs_pitch = 0;
+ controller.m_start_roll = 0;
+ controller.m_start_pitch = 0;
+ }
+ if (controller.m_buttonReleased)
+ {
+ DisableMotionSensing(wm);
+ controller.m_currentAction = ACTION_NONE;
+ }
+ break;
+ case WIIUSE_STATUS:
+ break;
+ case WIIUSE_DISCONNECT:
+ case WIIUSE_UNEXPECTED_DISCONNECT:
+ handle_disconnect(wm);
+ connected = 0;
+ break;
+ case WIIUSE_READ_DATA:
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ wiiuse_cleanup(wiimotes, MAX_WIIMOTES);
+ return 0;
+}
diff --git a/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.h b/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.h
new file mode 100644
index 0000000..7226137
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/WiiUse_WiiRemote.h
@@ -0,0 +1,127 @@
+ /* Copyright (C) 2009 by Cory Fields
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+//#include <math.h>
+#include <unistd.h>
+#ifdef DEB_PACK
+#include <xbmc/xbmcclient.h>
+#else
+#include "../../lib/c++/xbmcclient.h"
+#endif
+//#ifndef WIN32
+// #include <unistd.h>
+//#endif
+#include "wiiuse.h"
+//#define ICON_PATH "../../"
+#define PORT 9777
+#define MAX_WIIMOTES 1
+#define OVER_180_DEG 1
+#define UNDER_NEG_180_DEG 2
+#define WIIMOTE_BUTTON_TWO 0x0001
+#define WIIMOTE_BUTTON_ONE 0x0002
+#define WIIMOTE_BUTTON_B 0x0004
+#define WIIMOTE_BUTTON_A 0x0008
+#define WIIMOTE_BUTTON_MINUS 0x0010
+#define WIIMOTE_BUTTON_HOME 0x0080
+#define WIIMOTE_BUTTON_LEFT 0x0100
+#define WIIMOTE_BUTTON_RIGHT 0x0200
+#define WIIMOTE_BUTTON_DOWN 0x0400
+#define WIIMOTE_BUTTON_UP 0x0800
+#define WIIMOTE_BUTTON_PLUS 0x1000
+
+#define WIIMOTE_NUM_BUTTONS 11
+#define KEYCODE_BUTTON_UP 1
+#define KEYCODE_BUTTON_DOWN 2
+#define KEYCODE_BUTTON_LEFT 3
+#define KEYCODE_BUTTON_RIGHT 4
+#define KEYCODE_BUTTON_A 5
+#define KEYCODE_BUTTON_B 6
+#define KEYCODE_BUTTON_MINUS 7
+#define KEYCODE_BUTTON_HOME 8
+#define KEYCODE_BUTTON_PLUS 9
+#define KEYCODE_BUTTON_ONE 10
+#define KEYCODE_BUTTON_TWO 11
+#define KEYCODE_ROLL_NEG 33
+#define KEYCODE_ROLL_POS 34
+#define KEYCODE_PITCH_NEG 35
+#define KEYCODE_PITCH_POS 36
+
+
+#define ACTION_NONE 0
+#define ACTION_ROLL 1
+#define ACTION_PITCH 2
+
+class CWiiController{
+ public:
+
+ bool m_holdableHeld;
+ bool m_holdableReleased;
+ bool m_repeatableHeld;
+ bool m_repeatableReleased;
+
+ unsigned short m_buttonPressed;
+ unsigned short m_buttonReleased;
+ unsigned short m_buttonHeld;
+ unsigned short m_repeatFlags;
+ unsigned short m_holdFlags;
+ unsigned short m_currentAction;
+
+ int32_t m_buttonDownTime;
+
+ float m_abs_roll;
+ float m_abs_pitch;
+ float m_rel_roll;
+ float m_rel_pitch;
+ float m_start_roll;
+ float m_start_pitch;
+ char* m_joyString;
+
+
+ void get_keys(wiimote* wm);
+ void handleKeyPress();
+ void handleRepeat();
+ void handleACC(float, float);
+ void handleIR();
+
+ CWiiController()
+ {
+ m_joyString = "JS0:WiiRemote";
+ m_repeatFlags = WIIMOTE_BUTTON_UP | WIIMOTE_BUTTON_DOWN | WIIMOTE_BUTTON_LEFT | WIIMOTE_BUTTON_RIGHT;
+ m_holdFlags = WIIMOTE_BUTTON_B;
+ }
+};
+
+unsigned short g_deadzone = 30;
+unsigned short g_hold_button_timeout = 200;
+unsigned short g_repeat_rate = 400;
+
+int handle_disconnect(wiimote* );
+int connectWiimote(wiimote** );
+int32_t getTicks(void);
+void EnableMotionSensing(wiimote* wm) {if (!WIIUSE_USING_ACC(wm)) wiiuse_motion_sensing(wm, 1);}
+void DisableMotionSensing(wiimote* wm) {if (WIIUSE_USING_ACC(wm)) wiiuse_motion_sensing(wm, 0);}
+unsigned short convert_code(unsigned short);
+float smoothDeg(float, float);
+
+CXBMCClient EventClient;
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/CHANGELOG b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/CHANGELOG
new file mode 100644
index 0000000..8ca3439
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/CHANGELOG
@@ -0,0 +1,208 @@
+---------------------------
+-
+- CHANGE LOG - Wiiuse
+-
+---------------------------
+
+http://wiiuse.net/
+http://wiiuse.sourceforge.net/
+http://sourceforge.net/projects/wiiuse/
+
+---------------------------
+v0.12 -- 2 Apr 2008
+---------------------------
+
+ Added:
+ - API function wiiuse_set_ir_sensitivity()
+ - Macro WIIUSE_GET_IR_SENSITIVITY()
+ - Event type WIIUSE_READ_DATA
+ - Event type WIIUSE_UNEXPECTED_DISCONNECT
+
+ Fixed:
+ - [Linux] Ability to try to select() nothing
+ - [Linux] Changed Makefile to include debug output when compiling in debug mode
+
+ Changed:
+ - wiiuse_set_nunchuk_orient_threshold() now takes a wiimote_t pointer
+ - wiiuse_set_nunchuk_accel_threshold() now takes a wiimote_t pointer
+ - wiiuse_read_data() generates an event WIIUSE_READ_DATA rather than executing a callback
+
+---------------------------
+v0.11 -- 25 Feb 2008
+---------------------------
+
+ Added:
+ - API function wiiuse_set_nunchuk_orient_threshold()
+ - API function wiiuse_set_nunchuk_accel_threshold()
+ - Event type WIIUSE_NUNCHUK_INSERTED
+ - Event type WIIUSE_NUNCHUK_REMOVED
+ - Event type WIIUSE_CLASSIC_CTRL_INSERTED
+ - Event type WIIUSE_CLASSIC_CTRL_REMOVED
+ - Event type WIIUSE_GUITAR_HERO_3_CTRL_INSERTED
+ - Event type WIIUSE_GUITAR_HERO_3_CTRL_REMOVED
+
+ Fixed:
+ - Added some missing function prototypes to wiiuse.h
+ - [Linux] Fixed Makefile to link libmath and libbluetooth
+ - Status event is set when a status report comes in
+ - Orientation threshold not being saved in lstate
+
+---------------------------
+v0.10 -- 11 Feb 2008
+---------------------------
+
+ Added:
+ - Real dynamic linking (by noisehole)
+ - Changed from callback to SDL style
+ - Guitar Hero 3 controller support
+ - API function wiiuse_set_accel_threshold()
+ - API function wiiuse_version()
+ - Macro WIIUSE_USING_SPEAKER()
+ - Macro WIIUSE_IS_LED_SET(wm, num)
+ - wiiuse_init() now autogenerates unids
+ - orient_t::a_roll/a_pitch
+ - wiiuse_resync()
+ - wiiuse_cleanup()
+ - wiiuse_set_timeout()
+
+ Fixed:
+ - [Windows] Fixed bug where it did not detect expansions on startup
+ - Renamed INFO/WARNING/DEBUG macros to WIIUSE_* (by noisehole)
+ - Updated Makefiles (by noisehole)
+ - Fixed incorrect roll/pitch when smoothing was enabled
+ - Fixed nunchuk and classic controller flooding events when significant changes occurred
+ - Fixed bug where IR was not correct on roll if IR was enabled before handshake
+
+ Removed:
+ - wiiuse_startup(), no longer needed
+
+---------------------------
+v0.9 -- 3 Nov 2007
+---------------------------
+
+ Fixed:
+ - Can now use include/wiiuse.h in C++ projects.
+ - HOME button works again.
+ - IR now functions after expansion is connected or removed.
+
+---------------------------
+v0.8 -- 27 Oct 2007
+---------------------------
+
+ - Bumped API version to 8
+ - Exported all API functions for usage with non-C/C++ languages.
+ - Changed event callback to only trigger if a significant state change occurs.
+
+ Added:
+ - wiimote_t::lstate structure
+
+ Fixed:
+ - Bug 1820140 - Buffer overflow in io_nix.c. Thanks proppy.
+
+---------------------------
+v0.7 -- 19 Oct 2007
+---------------------------
+
+ - Bumped API version to 7
+ - Renamed Linux build from wii.so to wiiuse.so
+ - Changed version representation from float to const char*.
+
+ Added:
+ - [Windows] BlueSoleil support.
+ - [Windows] Bluetooth stack auto-detection (WinXP SP2, Bluesoleil, Widdcomm tested).
+ - [Windows] API function wiiuse_set_bluetooth_stack().
+ - Calculates yaw if IR tracking is enabled.
+
+ Fixed:
+ - [Windows] Problem where a connection is made to a wiimote that does not exist.
+ - [Windows] Issue that occurred while using multiple wiimotes.
+
+---------------------------
+v0.6 -- 16 Oct 2007
+---------------------------
+
+ - Bumped API version to 0.6.
+ - Ported to Microsoft Windows.
+ - Improved IR tracking.
+ - Default IR virtual screen resolutions changed depending on 16:9 or 4:3.
+
+ Added:
+ - src/msvc/ and api/msvc/ - Microsoft Visual C++ 6.0 project files.
+
+---------------------------
+v0.5 -- 13 Oct 2007
+---------------------------
+
+ - Bumped API version to 0.5.
+ - Greatly improved IR tracking.
+ - Renamed function wiiuse_set_ir_correction() to wiiuse_set_ir_position().
+
+ Added:
+ - API function wiiuse_set_aspect_ratio()
+
+ Fixed:
+ - When rolling around 180 degree rotation smoothing would not be seemless.
+
+---------------------------
+v0.4 -- 08 Oct 2007
+---------------------------
+
+ - Bumped API version to 0.4.
+ - Greatly improved classic controller joystick functionality.
+ - Changed all functions named wiimote_*() to wiiuse_*()
+ - Renamed many macros from WIIMOTE_* to WIIUSE_*
+
+ Added:
+ - IR support
+ - New WIIMOTE_CONTINUOUS flag to set continuous reporting
+ - Macro IS_JUST_PRESSED()
+ - Macro WIIUSE_USING_ACC()
+ - Macro WIIUSE_USING_EXP()
+ - Macro WIIUSE_USING_IR()
+ - API function wiiuse_set_ir()
+ - API function wiiuse_set_ir_vres()
+ - API function wiiuse_set_ir_correction()
+
+ - gfx/ - A small OpenGL example that renders IR data
+
+ Fixed:
+ - Sometimes classic controller would only report infinite angle and magnitude for joysticks.
+
+---------------------------
+v0.3 -- 10 Sept 2007
+---------------------------
+
+ - Moved license to GPLv3.
+ - Bumped API version to 0.3.
+
+ Added:
+ - Support for Classic Controller
+ - Smoothing for roll and pitch values of the wiimote and nunchuk.
+
+ - API: wiimote_set_flags() to set or disable wiimote options.
+ - API: wiimote_set_smooth_alpha() to set smoothing alpha value.
+
+ Fixed:
+ - When the wiimote accelerates the roll or pitch is unreliable and was set to 0.
+ It now remains at previous tilt value.
+ - If no event callback was specified then no events would be processed internally.
+
+---------------------------
+v0.2 -- 25 Aug 2007
+---------------------------
+
+ - Bumped API version to 0.2.
+
+ Added:
+ - Nunchuk support.
+ - Ability to write to flash memory.
+
+ Fixed:
+ - Roll and pitch rotation now ranges from -180 to 180 degrees (previously -90 to 90).
+ - Bug when reading data from flash memory would read wrong address.
+
+---------------------------
+v0.1 -- 23 Feb 2007
+---------------------------
+
+ - Initial release
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE
new file mode 100644
index 0000000..85b8e59
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE
@@ -0,0 +1,620 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE_noncommercial b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE_noncommercial
new file mode 100644
index 0000000..ea8fae6
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/LICENSE_noncommercial
@@ -0,0 +1,170 @@
+This license can be used for any works that this license defines
+as "derived" or "combined" works that are strictly NON-COMMERCIAL.
+This license prohibits the use of any source or object code
+in works that are PROPRIETARY.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/Makefile b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/Makefile
new file mode 100644
index 0000000..f63da69
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/Makefile
@@ -0,0 +1,23 @@
+#
+# wiiuse Makefile
+#
+
+all clean install:
+ @$(MAKE) -C src $@
+ @$(MAKE) -C example $@
+ @$(MAKE) -C example-sdl $@
+
+wiiuse:
+ @$(MAKE) -C src
+
+ex:
+ @$(MAKE) -C example
+
+sdl-ex:
+ @$(MAKE) -C example-sdl
+
+distclean:
+ @$(MAKE) -C src $@
+ @$(MAKE) -C example $@
+ @$(MAKE) -C example-sdl $@
+ @find . -type f \( -name "*.save" -or -name "*~" -or -name gmon.out \) -delete &> /dev/null
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/README b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/README
new file mode 100644
index 0000000..b06bb96
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/README
@@ -0,0 +1,155 @@
+---------------------------
+-
+- README - Wiiuse
+-
+---------------------------
+
+http://wiiuse.net/
+http://wiiuse.sourceforge.net/
+http://sourceforge.net/projects/wiiuse/
+
+---------------------------
+
+ABOUT
+
+ Wiiuse is a library written in C that connects with several Nintendo Wii remotes.
+ Supports motion sensing, IR tracking, nunchuk, classic controller, and the Guitar Hero 3 controller.
+ Single threaded and nonblocking makes a light weight and clean API.
+
+ Distributed under the GPL and LGPL.
+
+
+AUTHORS
+
+ Michael Laforest < para >
+ Email: < thepara (--AT--) g m a i l [--DOT--] com >
+
+ The following people have contributed patches to wiiuse:
+ - dhewg
+
+
+LICENSE
+
+ There are two licenses for wiiuse. Please read them carefully before choosing which one
+ you use. You may of course at any time switch the license you are currently using to
+ the other.
+
+ Briefly, the license options are:
+
+ a) GNU LGPL (modified for non-commercial usage only)
+ b) GNU GPL
+
+ PLEASE READ THE LICENSES!
+
+
+ACKNOWLEDGEMENTS
+
+ http://wiibrew.org/
+ This site and their users have contributed an immense amount of information
+ about the wiimote and its technical details. I could not have written this program
+ without the vast amounts of reverse engineered information that was researched by them.
+
+ Nintendo
+ Of course Nintendo for designing and manufacturing the Wii and Wii remote.
+
+ BlueZ
+ Easy and intuitive bluetooth stack for Linux.
+
+ Thanks to Brent for letting me borrow his Guitar Hero 3 controller.
+
+
+DISCLAIMER AND WARNINGS
+
+ I am in no way responsible for any damages or effects, intended or not, caused by this program.
+
+ *** WARNING *** WARNING *** WARNING ***
+
+ Be aware that writing to memory may damage or destroy your wiimote or expansions.
+
+ *** WARNING *** WARNING *** WARNING ***
+
+ This program was written using reverse engineered specifications available from wiibrew.org.
+ Therefore the operation of this program may not be entirely correct.
+ Results obtained by using this program may vary.
+
+
+AUDIENCE
+
+ This project is intended for developers who wish to include support for the Nintendo Wii remote
+ with their third party application. Please be aware that by using this software you are bound
+ to the terms of the GNU GPL.
+
+
+PLATFORMS AND DEPENDENCIES
+
+ Wiiuse currently operates on both Linux and Windows.
+ You will need:
+
+ For Linux:
+ - The kernel must support bluetooth
+ - The BlueZ bluetooth drivers must be installed
+
+ For Windows:
+ - Bluetooth driver (tested with Microsoft's stack with Windows XP SP2)
+ - If compiling, Microsoft Windows Driver Development Kit (DDK)
+
+
+COMPILING
+
+ Linux:
+ You need SDL and OpenGL installed to compile the SDL example.
+
+ # make [target]
+
+ If 'target' is omitted then everything is compiled.
+
+ Where 'target' can be any of the following:
+
+ - wiiuse
+ Compiles libwiiuse.so
+
+ - ex
+ Compiles wiiuse-example
+
+ - sdl-ex
+ Compiles wiiuse-sdl
+
+ Become root.
+
+ # make install
+
+ The above command will only install the binaries that you
+ selected to compile.
+
+ wiiuse.so is installed to /usr/lib
+ wiiuse-example and wiiuse-sdl are installed to /usr/bin
+
+ Windows:
+ A Microsoft Visual C++ 6.0 project file has been included.
+
+ You need the install the Windows DDK (driver development kit)
+ to compile wiiuse. Make sure you include the inc/ and lib/
+ directories from the DDK in your IDE include and library paths.
+ You can download this from here:
+ http://www.microsoft.com/whdc/devtools/ddk/default.mspx
+
+ You need to link the following libraries (already set in the
+ included project file):
+ - Ws2_32.lib
+ - hid.lib
+ - setupapi.lib
+
+
+USING THE LIBRARY IN A THIRD PARTY APPLICATION
+
+ To use the library in your own program you must first compile wiiuse as a module.
+ Include include/wiiuse.h in any file that uses wiiuse.
+
+ For Linux you must link wiiuse.so ( -lwiiuse ).
+ For Windows you must link wiiuse.lib. When your program runs it will need wiiuse.dll.
+
+
+BUGS
+
+ On Windows using more than one wiimote (usually more than two wiimotes) may cause
+ significant latency.
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/Makefile b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/Makefile
new file mode 100644
index 0000000..3420d7b
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/Makefile
@@ -0,0 +1,83 @@
+#
+# wiiuse Makefile
+#
+
+#
+# Change this to your GCC version.
+#
+CC ?= gcc
+
+####################################################
+#
+# You should not need to edit below this line.
+#
+####################################################
+
+#
+# Universal cflags
+#
+CFLAGS = -Wall -pipe -fPIC -funroll-loops
+
+ifeq ($(debug),1)
+ OBJ_PREFIX = debug
+ CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG
+else
+ OBJ_PREFIX = release
+ CFLAGS += -O2
+endif
+
+OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2)
+
+#
+# Linking flags
+#
+LDFLAGS = -L../src/$(OBJ_DIR) -lm -lGL -lGLU -lglut -lSDL -lbluetooth -lwiiuse
+
+#
+# Target binaries (always created as BIN)
+#
+BIN = ./$(OBJ_DIR)/wiiuse-sdl
+
+#
+# Inclusion paths.
+#
+INCLUDES = -I../src/ -I/usr/include/SDL
+
+#
+# Generate a list of object files
+#
+OBJS = $(OBJ_DIR)/sdl.o
+
+###############################
+#
+# Build targets.
+#
+###############################
+
+all: $(BIN)
+
+clean:
+ @-rm $(OBJS) 2> /dev/null
+
+distclean: clean
+ @-rm -r debug-* release-* 2> /dev/null
+
+install:
+ @if [ -e $(BIN) ]; then \
+ cp -v $(BIN) /usr/bin ;\
+ fi
+
+$(BIN): mkdir $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN)
+
+$(OBJ_DIR)/%.o: %.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+
+mkdir:
+ @if [ ! -d $(OBJ_DIR) ]; then \
+ mkdir $(OBJ_DIR); \
+ fi
+
+run: all
+ LD_LIBRARY_PATH=`pwd`/../src/$(OBJ_DIR):$(LD_LIBRARY_PATH) $(BIN)
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsp b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsp
new file mode 100644
index 0000000..007d676
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsp
@@ -0,0 +1,111 @@
+# Microsoft Developer Studio Project File - Name="wiiusesdl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=wiiusesdl - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "wiiusesdl.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "wiiusesdl.mak" CFG="wiiusesdl - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "wiiusesdl - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "wiiusesdl - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "wiiusesdl - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib opengl32.lib glu32.lib wiiuse.lib /nologo /subsystem:windows /machine:I386
+
+!ELSEIF "$(CFG)" == "wiiusesdl - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib opengl32.lib glu32.lib wiiuse.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "wiiusesdl - Win32 Release"
+# Name "wiiusesdl - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\sdl.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\wiiuse.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsw b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsw
new file mode 100644
index 0000000..ee501ff
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "wiiusesdl"=".\wiiusesdl.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.opt b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.opt
new file mode 100644
index 0000000..fa46687
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/msvc/wiiusesdl.opt
Binary files differ
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/sdl.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/sdl.c
new file mode 100644
index 0000000..c469968
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example-sdl/sdl.c
@@ -0,0 +1,439 @@
+/*
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifndef WIN32
+ #include <unistd.h>
+ #include <sys/time.h>
+ #include <time.h>
+#else
+ #include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glut.h>
+#include <SDL.h>
+
+#include <wiiuse.h>
+
+#define PI 3.14159265358979323846
+#define PI_DIV_180 0.017453292519943296
+#define deg PI_DIV_180
+
+#define MAX_WIIMOTES 2
+
+GLint width = 1024, height = 768;
+GLfloat backColor[4] = {1.0,1.0,1.0,1.0};
+
+wiimote** wiimotes = NULL;
+
+int last_dots[4][2] = {{0}};
+int xcoord = 0;
+int ycoord = 0;
+
+#ifdef WIN32
+ DWORD last_render;
+#else
+ struct timeval last_render;
+ int last_sec = 0;
+ int fps = 0;
+#endif
+
+enum render_mode_t {
+ IR = 1,
+ TEAPOT
+};
+enum render_mode_t render_mode = IR;
+
+/* light information */
+struct light_t {
+ GLfloat position[4];
+ GLfloat spotDirection[3];
+ GLfloat ambient[4];
+ GLfloat diffuse[4];
+ GLfloat specular[4];
+ GLfloat spotCutoff;
+ GLfloat spotExponent;
+ GLfloat spotAttenuation[3]; /* [0] = constant, [1] = linear, [2] = quadratic */
+};
+struct light_t light = {
+ { 1.0, 1.0, -2.0, 1.0 },
+ { -1.0, -1.0, 2.0 },
+ { 0.0, 0.0, 0.0, 1.0 },
+ { 1.0, 1.0, 1.0, 1.0 },
+ { 1.0, 1.0, 1.0, 1.0 },
+ 180.0, 0.0,
+ { 1.0, 0.0, 0.0 }
+};
+
+/* material information */
+struct material_t {
+ GLfloat ambient[4];
+ GLfloat diffuse[4];
+ GLfloat specular[4];
+ GLfloat emission[4];
+ GLfloat shininess;
+};
+struct material_t red_plastic = {
+ { 0.3, 0.0, 0.0, 1.0 },
+ { 0.3, 0.0, 0.0, 1.0 },
+ { 0.8, 0.6, 0.6, 1.0 },
+ { 0.0, 0.0, 0.0, 1.0 },
+ 32.0
+};
+
+
+void handle_event(struct wiimote_t* wm);
+void display();
+void update_light(GLenum l, struct light_t* lptr);
+void set_material(struct material_t* mptr);
+void resize_window(GLint new_width, GLint new_height);
+
+void handle_event(struct wiimote_t* wm) {
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS))
+ wiiuse_motion_sensing(wm, 1);
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS))
+ wiiuse_motion_sensing(wm, 0);
+
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP))
+ wiiuse_set_ir(wm, 1);
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN))
+ wiiuse_set_ir(wm, 0);
+
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_B))
+ wiiuse_toggle_rumble(wm);
+
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_ONE)) {
+ int level;
+ WIIUSE_GET_IR_SENSITIVITY(wm, &level);
+ wiiuse_set_ir_sensitivity(wm, level+1);
+ }
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_TWO)) {
+ int level;
+ WIIUSE_GET_IR_SENSITIVITY(wm, &level);
+ wiiuse_set_ir_sensitivity(wm, level-1);
+ }
+
+ #if 0
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_A)) {
+ if (render_mode == IR)
+ render_mode = TEAPOT;
+ else
+ render_mode = IR;
+ resize_window(width, height);
+ }
+ #endif
+}
+
+#define DRAW_TRIANGLE(x, y, z, s) do { \
+ glVertex3f(x, y-s, z); \
+ glVertex3f(x+s, y+s, z); \
+ glVertex3f(x-s, y+s, z); \
+ } while (0)
+
+int can_render() {
+ /* quick fps limit to ~60fps -- not too fancy, could be better */
+ #ifdef WIN32
+ if (GetTickCount() < (last_render + 16))
+ return 0;
+ last_render = GetTickCount();
+ return 1;
+ #else
+ struct timeval now;
+ long elapsed_usec = 0;
+
+ gettimeofday(&now, NULL);
+
+ if (now.tv_usec > 1000000) {
+ now.tv_usec -= 1000000;
+ ++now.tv_sec;
+ }
+
+ if (now.tv_sec > last_render.tv_sec)
+ elapsed_usec = ((now.tv_sec - last_render.tv_sec) * 1000000);
+
+ if (now.tv_usec > last_render.tv_usec)
+ elapsed_usec += now.tv_usec - last_render.tv_usec;
+ else
+ elapsed_usec += last_render.tv_usec - now.tv_usec;
+
+ if (time(NULL) > last_sec) {
+ printf("fps: %i\n", fps);
+ fps = 0;
+ last_sec = time(NULL);
+ }
+
+ if (elapsed_usec < 16000)
+ return 0;
+
+ last_render = now;
+ ++fps;
+
+ return 1;
+ #endif
+}
+
+void display() {
+ int i, wm;
+ float size = 5;
+
+ if (!can_render())
+ return;
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ if (render_mode == IR) {
+ /* draw the IR stuff */
+
+ glDisable(GL_LIGHTING);
+
+ glBegin(GL_TRIANGLES);
+ /* green center */
+ glColor3f(0.0, 1.0, 0.0);
+ DRAW_TRIANGLE(width/2, height/2, 0, size);
+ glEnd();
+
+ for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
+ glBegin(GL_TRIANGLES);
+ /* red ir */
+ glColor3f(1.0, 0.0, 0.0);
+ for (i = 0; i < 4; ++i) {
+ if (wiimotes[wm]->ir.dot[i].visible)
+ DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].rx, wiimotes[wm]->ir.dot[i].ry, 0, size);
+ }
+
+ /* yellow corrected ir */
+ glColor3f(1.0, 1.0, 0.0);
+ for (i = 0; i < 4; ++i) {
+ if (wiimotes[wm]->ir.dot[i].visible)
+ DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].x, wiimotes[wm]->ir.dot[i].y, 0, size);
+ }
+
+ /* blue cursor */
+ glColor3f(0.0, 0.0, 1.0);
+ DRAW_TRIANGLE(wiimotes[wm]->ir.x, wiimotes[wm]->ir.y-size, 0, size);
+ glEnd();
+ }
+ } else {
+ /* draw the teapot */
+ gluLookAt(0.0, 0.0, -5.0,
+ 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0);
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ update_light(GL_LIGHT0, &light);
+ set_material(&red_plastic);
+
+ glRotatef(wiimotes[0]->orient.roll, 0.0f, 0.0f, 1.0f);
+ glRotatef(wiimotes[0]->orient.pitch, 1.0f, 0.0f, 0.0f);
+
+
+ glutSolidTeapot(1);
+ }
+
+ SDL_GL_SwapBuffers();
+}
+
+
+void update_light(GLenum l, struct light_t* lptr) {
+ glLightfv(l, GL_POSITION, lptr->position);
+ glLightfv(l, GL_DIFFUSE, lptr->diffuse);
+ glLightfv(l, GL_SPECULAR, lptr->specular);
+ glLightfv(l, GL_AMBIENT, lptr->ambient);
+ glLightfv(l, GL_SPOT_DIRECTION, lptr->spotDirection);
+ glLightf(l, GL_SPOT_CUTOFF, lptr->spotCutoff);
+ glLightf(l, GL_SPOT_EXPONENT, lptr->spotExponent);
+ glLightf(l, GL_CONSTANT_ATTENUATION, lptr->spotAttenuation[0]);
+ glLightf(l, GL_LINEAR_ATTENUATION, lptr->spotAttenuation[1]);
+ glLightf(l, GL_QUADRATIC_ATTENUATION, lptr->spotAttenuation[2]);
+}
+
+
+void set_material(struct material_t* mptr) {
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mptr->ambient);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mptr->diffuse);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mptr->specular);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mptr->shininess);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mptr->emission);
+}
+
+
+void resize_window(GLint new_width, GLint new_height) {
+ int wm;
+
+ width = new_width;
+ height = new_height;
+
+ if (new_height == 0)
+ new_height = 1;
+
+ SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL);
+
+ glViewport(0, 0, new_width, new_height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ if (render_mode == IR)
+ gluOrtho2D(0, width, height, 0);
+ else
+ gluPerspective(60.0f, (float)new_width/(float)new_height, 0.1f, 100.0f);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ width = new_width;
+ height = new_height;
+
+ for (wm = 0; wm < MAX_WIIMOTES; ++wm)
+ wiiuse_set_ir_vres(wiimotes[wm], width, height);
+}
+
+#ifndef WIN32
+int main(int argc, char** argv) {
+#else
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
+#endif
+ int found, connected;
+ int wm;
+
+ //printf("wiiuse version = %s\n", wiiuse_version());
+
+ wiimotes = wiiuse_init(MAX_WIIMOTES);
+ found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5);
+ if (!found)
+ return 0;
+ connected = wiiuse_connect(wiimotes, MAX_WIIMOTES);
+ if (connected)
+ printf("Connected to %i wiimotes (of %i found).\n", connected, found);
+ else {
+ printf("Failed to connect to any wiimote.\n");
+ return 0;
+ }
+ wiiuse_set_leds(wiimotes[0], WIIMOTE_LED_1 | WIIMOTE_LED_4);
+ wiiuse_set_leds(wiimotes[1], WIIMOTE_LED_2 | WIIMOTE_LED_4);
+ wiiuse_rumble(wiimotes[0], 1);
+
+ #ifndef WIN32
+ usleep(200000);
+ #else
+ Sleep(200);
+ #endif
+
+ wiiuse_rumble(wiimotes[0], 0);
+
+ /* enable IR and motion sensing for all wiimotes */
+ for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
+ wiiuse_motion_sensing(wiimotes[wm], 1);
+ wiiuse_set_ir(wiimotes[wm], 1);
+ }
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ printf("Failed to initialize SDL: %s\n", SDL_GetError());
+ return 0;
+ }
+
+ SDL_WM_SetCaption("wiiuse SDL IR Example", "wiiuse SDL IR Example");
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+
+ /* set window size */
+ width = wiimotes[0]->ir.vres[0];
+ height = wiimotes[0]->ir.vres[1];
+ SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL);
+
+ for (wm = 0; wm < MAX_WIIMOTES; ++wm)
+ wiiuse_set_ir_vres(wiimotes[wm], width, height);
+
+ /* set OpenGL stuff */
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_NORMALIZE);
+ glEnable(GL_BLEND);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDepthFunc(GL_LEQUAL);
+ glClearColor(0, 0, 0, 0);
+
+ /* set the size of the window */
+ resize_window(width, height);
+
+ display();
+
+ #ifdef WIN32
+ last_render = GetTickCount();
+ #endif
+
+ while (1) {
+ SDL_Event event;
+
+ if (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_VIDEORESIZE:
+ {
+ /* resize the window */
+ resize_window(event.resize.w, event.resize.h);
+ break;
+ }
+ case SDL_QUIT:
+ {
+ /* shutdown */
+ SDL_Quit();
+ wiiuse_cleanup(wiimotes, MAX_WIIMOTES);
+ return 0;
+ }
+ default:
+ {
+ }
+ }
+ }
+
+ if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) {
+ /*
+ * This happens if something happened on any wiimote.
+ * So go through each one and check if anything happened.
+ */
+ int i = 0;
+ for (; i < MAX_WIIMOTES; ++i) {
+ switch (wiimotes[i]->event) {
+ case WIIUSE_EVENT:
+ /* a generic event occurred */
+ handle_event(wiimotes[i]);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ display();
+ }
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/Makefile b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/Makefile
new file mode 100644
index 0000000..e3e907c
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/Makefile
@@ -0,0 +1,84 @@
+#
+# wiiuse Makefile
+#
+
+#
+# Change this to your GCC version.
+#
+CC ?= gcc
+
+####################################################
+#
+# You should not need to edit below this line.
+#
+####################################################
+
+#
+# Universal cflags
+#
+CFLAGS = -Wall -pipe -fPIC -funroll-loops
+
+ifeq ($(debug),1)
+ OBJ_PREFIX = debug
+ CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG
+else
+ OBJ_PREFIX = release
+ CFLAGS += -O2
+endif
+
+OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2)
+
+#
+# Linking flags
+#
+LDFLAGS = -L../src/$(OBJ_DIR) -lm -lwiiuse
+
+#
+# Target binaries (always created as BIN)
+#
+BIN = ./$(OBJ_DIR)/wiiuse-example
+
+#
+# Inclusion paths.
+#
+INCLUDES = -I../src/
+
+#
+# Generate a list of object files
+#
+OBJS = $(OBJ_DIR)/example.o
+
+###############################
+#
+# Build targets.
+#
+###############################
+
+all: $(BIN)
+
+clean:
+ @-rm $(OBJS) 2> /dev/null
+
+distclean:
+ @-rm -r debug-* release-* 2> /dev/null
+
+install:
+ @if [ -e $(BIN) ]; then \
+ cp -v $(BIN) /usr/bin ; \
+ fi
+
+
+$(BIN): mkdir $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN)
+
+$(OBJ_DIR)/%.o: %.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+
+mkdir:
+ @if [ ! -d $(OBJ_DIR) ]; then \
+ mkdir $(OBJ_DIR); \
+ fi
+
+run: all
+ LD_LIBRARY_PATH=`pwd`/../src/$(OBJ_DIR):$(LD_LIBRARY_PATH) $(BIN)
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/example.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/example.c
new file mode 100644
index 0000000..d401d80
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/example.c
@@ -0,0 +1,437 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ *
+ * @brief Example using the wiiuse API.
+ *
+ * This file is an example of how to use the wiiuse library.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef WIN32
+ #include <unistd.h>
+#endif
+
+#include "wiiuse.h"
+
+
+#define MAX_WIIMOTES 4
+
+
+/**
+ * @brief Callback that handles an event.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ *
+ * This function is called automatically by the wiiuse library when an
+ * event occurs on the specified wiimote.
+ */
+void handle_event(struct wiimote_t* wm) {
+ printf("\n\n--- EVENT [id %i] ---\n", wm->unid);
+
+ /* if a button is pressed, report it */
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) printf("A pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_B)) printf("B pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP)) printf("UP pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) printf("DOWN pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT)) printf("LEFT pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT)) printf("RIGHT pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) printf("MINUS pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS)) printf("PLUS pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE)) printf("ONE pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_TWO)) printf("TWO pressed\n");
+ if (IS_PRESSED(wm, WIIMOTE_BUTTON_HOME)) printf("HOME pressed\n");
+
+ /*
+ * Pressing minus will tell the wiimote we are no longer interested in movement.
+ * This is useful because it saves battery power.
+ */
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS))
+ wiiuse_motion_sensing(wm, 0);
+
+ /*
+ * Pressing plus will tell the wiimote we are interested in movement.
+ */
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS))
+ wiiuse_motion_sensing(wm, 1);
+
+ /*
+ * Pressing B will toggle the rumble
+ *
+ * if B is pressed but is not held, toggle the rumble
+ */
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_B))
+ wiiuse_toggle_rumble(wm);
+
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP))
+ wiiuse_set_ir(wm, 1);
+ if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN))
+ wiiuse_set_ir(wm, 0);
+
+ /* if the accelerometer is turned on then print angles */
+ if (WIIUSE_USING_ACC(wm)) {
+ printf("wiimote roll = %f [%f]\n", wm->orient.roll, wm->orient.a_roll);
+ printf("wiimote pitch = %f [%f]\n", wm->orient.pitch, wm->orient.a_pitch);
+ printf("wiimote yaw = %f\n", wm->orient.yaw);
+ }
+
+ /*
+ * If IR tracking is enabled then print the coordinates
+ * on the virtual screen that the wiimote is pointing to.
+ *
+ * Also make sure that we see at least 1 dot.
+ */
+ if (WIIUSE_USING_IR(wm)) {
+ int i = 0;
+
+ /* go through each of the 4 possible IR sources */
+ for (; i < 4; ++i) {
+ /* check if the source is visible */
+ if (wm->ir.dot[i].visible)
+ printf("IR source %i: (%u, %u)\n", i, wm->ir.dot[i].x, wm->ir.dot[i].y);
+ }
+
+ printf("IR cursor: (%u, %u)\n", wm->ir.x, wm->ir.y);
+ printf("IR z distance: %f\n", wm->ir.z);
+ }
+
+ /* show events specific to supported expansions */
+ if (wm->exp.type == EXP_NUNCHUK) {
+ /* nunchuk */
+ struct nunchuk_t* nc = (nunchuk_t*)&wm->exp.nunchuk;
+
+ if (IS_PRESSED(nc, NUNCHUK_BUTTON_C)) printf("Nunchuk: C pressed\n");
+ if (IS_PRESSED(nc, NUNCHUK_BUTTON_Z)) printf("Nunchuk: Z pressed\n");
+
+ printf("nunchuk roll = %f\n", nc->orient.roll);
+ printf("nunchuk pitch = %f\n", nc->orient.pitch);
+ printf("nunchuk yaw = %f\n", nc->orient.yaw);
+
+ printf("nunchuk joystick angle: %f\n", nc->js.ang);
+ printf("nunchuk joystick magnitude: %f\n", nc->js.mag);
+ } else if (wm->exp.type == EXP_CLASSIC) {
+ /* classic controller */
+ struct classic_ctrl_t* cc = (classic_ctrl_t*)&wm->exp.classic;
+
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZL)) printf("Classic: ZL pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_B)) printf("Classic: B pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_Y)) printf("Classic: Y pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_A)) printf("Classic: A pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_X)) printf("Classic: X pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZR)) printf("Classic: ZR pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_LEFT)) printf("Classic: LEFT pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_UP)) printf("Classic: UP pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_RIGHT)) printf("Classic: RIGHT pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_DOWN)) printf("Classic: DOWN pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_L)) printf("Classic: FULL L pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_MINUS)) printf("Classic: MINUS pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_HOME)) printf("Classic: HOME pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_PLUS)) printf("Classic: PLUS pressed\n");
+ if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_R)) printf("Classic: FULL R pressed\n");
+
+ printf("classic L button pressed: %f\n", cc->l_shoulder);
+ printf("classic R button pressed: %f\n", cc->r_shoulder);
+ printf("classic left joystick angle: %f\n", cc->ljs.ang);
+ printf("classic left joystick magnitude: %f\n", cc->ljs.mag);
+ printf("classic right joystick angle: %f\n", cc->rjs.ang);
+ printf("classic right joystick magnitude: %f\n", cc->rjs.mag);
+ } else if (wm->exp.type == EXP_GUITAR_HERO_3) {
+ /* guitar hero 3 guitar */
+ struct guitar_hero_3_t* gh3 = (guitar_hero_3_t*)&wm->exp.gh3;
+
+ if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_UP)) printf("Guitar: Strum Up pressed\n");
+ if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_DOWN)) printf("Guitar: Strum Down pressed\n");
+ if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_YELLOW)) printf("Guitar: Yellow pressed\n");
+ if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_GREEN)) printf("Guitar: Green pressed\n");
+ if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_BLUE)) printf("Guitar: Blue pressed\n");
+ if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_RED)) printf("Guitar: Red pressed\n");
+ if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_ORANGE)) printf("Guitar: Orange pressed\n");
+ if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_PLUS)) printf("Guitar: Plus pressed\n");
+ if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_MINUS)) printf("Guitar: Minus pressed\n");
+
+ printf("Guitar whammy bar: %f\n", gh3->whammy_bar);
+ printf("Guitar joystick angle: %f\n", gh3->js.ang);
+ printf("Guitar joystick magnitude: %f\n", gh3->js.mag);
+ }
+}
+
+
+/**
+ * @brief Callback that handles a read event.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param data Pointer to the filled data block.
+ * @param len Length in bytes of the data block.
+ *
+ * This function is called automatically by the wiiuse library when
+ * the wiimote has returned the full data requested by a previous
+ * call to wiiuse_read_data().
+ *
+ * You can read data on the wiimote, such as Mii data, if
+ * you know the offset address and the length.
+ *
+ * The \a data pointer was specified on the call to wiiuse_read_data().
+ * At the time of this function being called, it is not safe to deallocate
+ * this buffer.
+ */
+void handle_read(struct wiimote_t* wm, byte* data, unsigned short len) {
+ int i = 0;
+
+ printf("\n\n--- DATA READ [wiimote id %i] ---\n", wm->unid);
+ printf("finished read of size %i\n", len);
+ for (; i < len; ++i) {
+ if (!(i%16))
+ printf("\n");
+ printf("%x ", data[i]);
+ }
+ printf("\n\n");
+}
+
+
+/**
+ * @brief Callback that handles a controller status event.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param attachment Is there an attachment? (1 for yes, 0 for no)
+ * @param speaker Is the speaker enabled? (1 for yes, 0 for no)
+ * @param ir Is the IR support enabled? (1 for yes, 0 for no)
+ * @param led What LEDs are lit.
+ * @param battery_level Battery level, between 0.0 (0%) and 1.0 (100%).
+ *
+ * This occurs when either the controller status changed
+ * or the controller status was requested explicitly by
+ * wiiuse_status().
+ *
+ * One reason the status can change is if the nunchuk was
+ * inserted or removed from the expansion port.
+ */
+void handle_ctrl_status(struct wiimote_t* wm) {
+ printf("\n\n--- CONTROLLER STATUS [wiimote id %i] ---\n", wm->unid);
+
+ printf("attachment: %i\n", wm->exp.type);
+ printf("speaker: %i\n", WIIUSE_USING_SPEAKER(wm));
+ printf("ir: %i\n", WIIUSE_USING_IR(wm));
+ printf("leds: %i %i %i %i\n", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4));
+ printf("battery: %f %%\n", wm->battery_level);
+}
+
+
+/**
+ * @brief Callback that handles a disconnection event.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ *
+ * This can happen if the POWER button is pressed, or
+ * if the connection is interrupted.
+ */
+void handle_disconnect(wiimote* wm) {
+ printf("\n\n--- DISCONNECTED [wiimote id %i] ---\n", wm->unid);
+}
+
+
+void test(struct wiimote_t* wm, byte* data, unsigned short len) {
+ printf("test: %i [%x %x %x %x]\n", len, data[0], data[1], data[2], data[3]);
+}
+
+
+
+/**
+ * @brief main()
+ *
+ * Connect to up to two wiimotes and print any events
+ * that occur on either device.
+ */
+int main(int argc, char** argv) {
+ wiimote** wiimotes;
+ int found, connected;
+
+ /*
+ * Initialize an array of wiimote objects.
+ *
+ * The parameter is the number of wiimotes I want to create.
+ */
+ wiimotes = wiiuse_init(MAX_WIIMOTES);
+
+ /*
+ * Find wiimote devices
+ *
+ * Now we need to find some wiimotes.
+ * Give the function the wiimote array we created, and tell it there
+ * are MAX_WIIMOTES wiimotes we are interested in.
+ *
+ * Set the timeout to be 5 seconds.
+ *
+ * This will return the number of actual wiimotes that are in discovery mode.
+ */
+ found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5);
+ if (!found) {
+ printf ("No wiimotes found.");
+ return 0;
+ }
+
+ /*
+ * Connect to the wiimotes
+ *
+ * Now that we found some wiimotes, connect to them.
+ * Give the function the wiimote array and the number
+ * of wiimote devices we found.
+ *
+ * This will return the number of established connections to the found wiimotes.
+ */
+ connected = wiiuse_connect(wiimotes, MAX_WIIMOTES);
+ if (connected)
+ printf("Connected to %i wiimotes (of %i found).\n", connected, found);
+ else {
+ printf("Failed to connect to any wiimote.\n");
+ return 0;
+ }
+
+ /*
+ * Now set the LEDs and rumble for a second so it's easy
+ * to tell which wiimotes are connected (just like the wii does).
+ */
+ wiiuse_set_leds(wiimotes[0], WIIMOTE_LED_1);
+ wiiuse_set_leds(wiimotes[1], WIIMOTE_LED_2);
+ wiiuse_set_leds(wiimotes[2], WIIMOTE_LED_3);
+ wiiuse_set_leds(wiimotes[3], WIIMOTE_LED_4);
+ wiiuse_rumble(wiimotes[0], 1);
+ wiiuse_rumble(wiimotes[1], 1);
+
+ #ifndef WIN32
+ usleep(200000);
+ #else
+ Sleep(200);
+ #endif
+
+ wiiuse_rumble(wiimotes[0], 0);
+ wiiuse_rumble(wiimotes[1], 0);
+
+ /*
+ * Maybe I'm interested in the battery power of the 0th
+ * wiimote. This should be WIIMOTE_ID_1 but to be sure
+ * you can get the wiimote assoicated with WIIMOTE_ID_1
+ * using the wiiuse_get_by_id() function.
+ *
+ * A status request will return other things too, like
+ * if any expansions are plugged into the wiimote or
+ * what LEDs are lit.
+ */
+ //wiiuse_status(wiimotes[0]);
+
+ /*
+ * This is the main loop
+ *
+ * wiiuse_poll() needs to be called with the wiimote array
+ * and the number of wiimote structures in that array
+ * (it doesn't matter if some of those wiimotes are not used
+ * or are not connected).
+ *
+ * This function will set the event flag for each wiimote
+ * when the wiimote has things to report.
+ */
+ while (1) {
+ if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) {
+ /*
+ * This happens if something happened on any wiimote.
+ * So go through each one and check if anything happened.
+ */
+ int i = 0;
+ for (; i < MAX_WIIMOTES; ++i) {
+ switch (wiimotes[i]->event) {
+ case WIIUSE_EVENT:
+ /* a generic event occurred */
+ handle_event(wiimotes[i]);
+ break;
+
+ case WIIUSE_STATUS:
+ /* a status event occurred */
+ handle_ctrl_status(wiimotes[i]);
+ break;
+
+ case WIIUSE_DISCONNECT:
+ case WIIUSE_UNEXPECTED_DISCONNECT:
+ /* the wiimote disconnected */
+ handle_disconnect(wiimotes[i]);
+ break;
+
+ case WIIUSE_READ_DATA:
+ /*
+ * Data we requested to read was returned.
+ * Take a look at wiimotes[i]->read_req
+ * for the data.
+ */
+ break;
+
+ case WIIUSE_NUNCHUK_INSERTED:
+ /*
+ * a nunchuk was inserted
+ * This is a good place to set any nunchuk specific
+ * threshold values. By default they are the same
+ * as the wiimote.
+ */
+ //wiiuse_set_nunchuk_orient_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 90.0f);
+ //wiiuse_set_nunchuk_accel_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 100);
+ printf("Nunchuk inserted.\n");
+ break;
+
+ case WIIUSE_CLASSIC_CTRL_INSERTED:
+ printf("Classic controller inserted.\n");
+ break;
+
+ case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
+ /* some expansion was inserted */
+ handle_ctrl_status(wiimotes[i]);
+ printf("Guitar Hero 3 controller inserted.\n");
+ break;
+
+ case WIIUSE_NUNCHUK_REMOVED:
+ case WIIUSE_CLASSIC_CTRL_REMOVED:
+ case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
+ /* some expansion was removed */
+ handle_ctrl_status(wiimotes[i]);
+ printf("An expansion was removed.\n");
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Disconnect the wiimotes
+ */
+ wiiuse_cleanup(wiimotes, MAX_WIIMOTES);
+
+ return 0;
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsp b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsp
new file mode 100644
index 0000000..2329dbc
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsp
@@ -0,0 +1,106 @@
+# Microsoft Developer Studio Project File - Name="wiiuseexample" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=wiiuseexample - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "wiiuseexample.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "wiiuseexample.mak" CFG="wiiuseexample - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "wiiuseexample - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "wiiuseexample - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "wiiuseexample - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib wiiuse.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "wiiuseexample - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "wiiuseexample - Win32 Release"
+# Name "wiiuseexample - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\example.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\src\wiiuse.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsw b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsw
new file mode 100644
index 0000000..88298b6
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "wiiuseexample"=".\wiiuseexample.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.opt b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.opt
new file mode 100644
index 0000000..fe837f8
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/example/msvc/wiiuseexample.opt
Binary files differ
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/Makefile b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/Makefile
new file mode 100644
index 0000000..53cc612
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/Makefile
@@ -0,0 +1,91 @@
+#
+# wiiuse Makefile
+#
+
+#
+# Change this to your GCC version.
+#
+CC ?= gcc
+
+####################################################
+#
+# You should not need to edit below this line.
+#
+####################################################
+
+#
+# Universal cflags
+#
+CFLAGS = -Wall -pipe -fPIC -funroll-loops
+
+ifeq ($(debug),1)
+ OBJ_PREFIX = debug
+ CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG
+
+else
+ OBJ_PREFIX = release
+ CFLAGS += -O2
+endif
+
+OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2)
+
+#
+# Linking flags
+#
+LDFLAGS = -shared -lm -lbluetooth
+
+#
+# Target binaries (always created as BIN)
+#
+BIN = ./$(OBJ_DIR)/libwiiuse.so
+
+#
+# Inclusion paths.
+#
+INCLUDES = -I.
+
+#
+# Generate a list of object files
+#
+OBJS = \
+ $(OBJ_DIR)/classic.o \
+ $(OBJ_DIR)/dynamics.o \
+ $(OBJ_DIR)/events.o \
+ $(OBJ_DIR)/io.o \
+ $(OBJ_DIR)/io_nix.o \
+ $(OBJ_DIR)/ir.o \
+ $(OBJ_DIR)/nunchuk.o \
+ $(OBJ_DIR)/guitar_hero_3.o \
+ $(OBJ_DIR)/wiiuse.o
+
+###############################
+#
+# Build targets.
+#
+###############################
+
+all: $(BIN)
+
+clean:
+ @-rm $(OBJS) 2> /dev/null
+
+distclean:
+ @-rm -r debug-* release-* 2> /dev/null
+
+install:
+ @if [ -e $(BIN) ]; then \
+ cp -v $(BIN) /usr/lib ; \
+ fi
+ @cp -v wiiuse.h /usr/include
+
+$(BIN): mkdir $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN)
+
+$(OBJ_DIR)/%.o: %.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+
+mkdir:
+ @if [ ! -d $(OBJ_DIR) ]; then \
+ mkdir $(OBJ_DIR); \
+ fi
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.c
new file mode 100644
index 0000000..1d3abaa
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.c
@@ -0,0 +1,190 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Classic controller expansion device.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+ #include <Winsock2.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "events.h"
+#include "classic.h"
+
+static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now);
+
+/**
+ * @brief Handle the handshake data from the classic controller.
+ *
+ * @param cc A pointer to a classic_ctrl_t structure.
+ * @param data The data read in from the device.
+ * @param len The length of the data block, in bytes.
+ *
+ * @return Returns 1 if handshake was successful, 0 if not.
+ */
+int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len) {
+ int i;
+ int offset = 0;
+
+ cc->btns = 0;
+ cc->btns_held = 0;
+ cc->btns_released = 0;
+ cc->r_shoulder = 0;
+ cc->l_shoulder = 0;
+
+ /* decrypt data */
+ for (i = 0; i < len; ++i)
+ data[i] = (data[i] ^ 0x17) + 0x17;
+
+ if (data[offset] == 0xFF) {
+ /*
+ * Sometimes the data returned here is not correct.
+ * This might happen because the wiimote is lagging
+ * behind our initialization sequence.
+ * To fix this just request the handshake again.
+ *
+ * Other times it's just the first 16 bytes are 0xFF,
+ * but since the next 16 bytes are the same, just use
+ * those.
+ */
+ if (data[offset + 16] == 0xFF) {
+ /* get the calibration data */
+ byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+
+ WIIUSE_DEBUG("Classic controller handshake appears invalid, trying again.");
+ wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+ return 0;
+ } else
+ offset += 16;
+ }
+
+
+ /* joystick stuff */
+ cc->ljs.max.x = data[0 + offset] / 4;
+ cc->ljs.min.x = data[1 + offset] / 4;
+ cc->ljs.center.x = data[2 + offset] / 4;
+ cc->ljs.max.y = data[3 + offset] / 4;
+ cc->ljs.min.y = data[4 + offset] / 4;
+ cc->ljs.center.y = data[5 + offset] / 4;
+
+ cc->rjs.max.x = data[6 + offset] / 8;
+ cc->rjs.min.x = data[7 + offset] / 8;
+ cc->rjs.center.x = data[8 + offset] / 8;
+ cc->rjs.max.y = data[9 + offset] / 8;
+ cc->rjs.min.y = data[10 + offset] / 8;
+ cc->rjs.center.y = data[11 + offset] / 8;
+
+ /* handshake done */
+ wm->exp.type = EXP_CLASSIC;
+
+ #ifdef WIN32
+ wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
+ #endif
+
+ return 1;
+}
+
+
+/**
+ * @brief The classic controller disconnected.
+ *
+ * @param cc A pointer to a classic_ctrl_t structure.
+ */
+void classic_ctrl_disconnected(struct classic_ctrl_t* cc) {
+ memset(cc, 0, sizeof(struct classic_ctrl_t));
+}
+
+
+
+/**
+ * @brief Handle classic controller event.
+ *
+ * @param cc A pointer to a classic_ctrl_t structure.
+ * @param msg The message specified in the event packet.
+ */
+void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg) {
+ int i, lx, ly, rx, ry;
+ byte l, r;
+
+ /* decrypt data */
+ for (i = 0; i < 6; ++i)
+ msg[i] = (msg[i] ^ 0x17) + 0x17;
+
+ classic_ctrl_pressed_buttons(cc, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
+
+ /* left/right buttons */
+ l = (((msg[2] & 0x60) >> 2) | ((msg[3] & 0xE0) >> 5));
+ r = (msg[3] & 0x1F);
+
+ /*
+ * TODO - LR range hardcoded from 0x00 to 0x1F.
+ * This is probably in the calibration somewhere.
+ */
+ cc->r_shoulder = ((float)r / 0x1F);
+ cc->l_shoulder = ((float)l / 0x1F);
+
+ /* calculate joystick orientation */
+ lx = (msg[0] & 0x3F);
+ ly = (msg[1] & 0x3F);
+ rx = ((msg[0] & 0xC0) >> 3) | ((msg[1] & 0xC0) >> 5) | ((msg[2] & 0x80) >> 7);
+ ry = (msg[2] & 0x1F);
+
+ calc_joystick_state(&cc->ljs, lx, ly);
+ calc_joystick_state(&cc->rjs, rx, ry);
+}
+
+
+/**
+ * @brief Find what buttons are pressed.
+ *
+ * @param cc A pointer to a classic_ctrl_t structure.
+ * @param msg The message byte specified in the event packet.
+ */
+static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now) {
+ /* message is inverted (0 is active, 1 is inactive) */
+ now = ~now & CLASSIC_CTRL_BUTTON_ALL;
+
+ /* pressed now & were pressed, then held */
+ cc->btns_held = (now & cc->btns);
+
+ /* were pressed or were held & not pressed now, then released */
+ cc->btns_released = ((cc->btns | cc->btns_held) & ~now);
+
+ /* buttons pressed now */
+ cc->btns = now;
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.h
new file mode 100644
index 0000000..308e1b5
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/classic.h
@@ -0,0 +1,51 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Classic controller expansion device.
+ */
+
+#pragma once
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len);
+
+void classic_ctrl_disconnected(struct classic_ctrl_t* cc);
+
+void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/definitions.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/definitions.h
new file mode 100644
index 0000000..c5d1270
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/definitions.h
@@ -0,0 +1,77 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief General definitions.
+ */
+
+#pragma once
+
+/* this is wiiuse - used to distinguish from third party programs using wiiuse.h */
+#include "os.h"
+
+#define WIIMOTE_PI 3.14159265f
+
+//#define WITH_WIIUSE_DEBUG
+
+/* Error output macros */
+#define WIIUSE_ERROR(fmt, ...) fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__)
+
+/* Warning output macros */
+#define WIIUSE_WARNING(fmt, ...) fprintf(stderr, "[WARNING] " fmt "\n", ##__VA_ARGS__)
+
+/* Information output macros */
+#define WIIUSE_INFO(fmt, ...) fprintf(stderr, "[INFO] " fmt "\n", ##__VA_ARGS__)
+
+#ifdef WITH_WIIUSE_DEBUG
+ #ifdef WIN32
+ #define WIIUSE_DEBUG(fmt, ...) do { \
+ char* file = __FILE__; \
+ int i = strlen(file) - 1; \
+ for (; i && (file[i] != '\\'); --i); \
+ fprintf(stderr, "[DEBUG] %s:%i: " fmt "\n", file+i+1, __LINE__, ##__VA_ARGS__); \
+ } while (0)
+ #else
+ #define WIIUSE_DEBUG(fmt, ...) fprintf(stderr, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__)
+ #endif
+#else
+ #define WIIUSE_DEBUG(fmt, ...)
+#endif
+
+/* Convert between radians and degrees */
+#define RAD_TO_DEGREE(r) ((r * 180.0f) / WIIMOTE_PI)
+#define DEGREE_TO_RAD(d) (d * (WIIMOTE_PI / 180.0f))
+
+/* Convert to big endian */
+#define BIG_ENDIAN_LONG(i) (htonl(i))
+#define BIG_ENDIAN_SHORT(i) (htons(i))
+
+#define absf(x) ((x >= 0) ? (x) : (x * -1.0f))
+#define diff_f(x, y) ((x >= y) ? (absf(x - y)) : (absf(y - x)))
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.c
new file mode 100644
index 0000000..b6baa72
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.c
@@ -0,0 +1,228 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles the dynamics of the wiimote.
+ *
+ * The file includes functions that handle the dynamics
+ * of the wiimote. Such dynamics include orientation and
+ * motion sensing.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+ #include <float.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "ir.h"
+#include "dynamics.h"
+
+/**
+ * @brief Calculate the roll, pitch, yaw.
+ *
+ * @param ac An accelerometer (accel_t) structure.
+ * @param accel [in] Pointer to a vec3b_t structure that holds the raw acceleration data.
+ * @param orient [out] Pointer to a orient_t structure that will hold the orientation data.
+ * @param rorient [out] Pointer to a orient_t structure that will hold the non-smoothed orientation data.
+ * @param smooth If smoothing should be performed on the angles calculated. 1 to enable, 0 to disable.
+ *
+ * Given the raw acceleration data from the accelerometer struct, calculate
+ * the orientation of the device and set it in the \a orient parameter.
+ */
+void calculate_orientation(struct accel_t* ac, struct vec3b_t* accel, struct orient_t* orient, int smooth) {
+ float xg, yg, zg;
+ float x, y, z;
+
+ /*
+ * roll - use atan(z / x) [ ranges from -180 to 180 ]
+ * pitch - use atan(z / y) [ ranges from -180 to 180 ]
+ * yaw - impossible to tell without IR
+ */
+
+ /* yaw - set to 0, IR will take care of it if it's enabled */
+ orient->yaw = 0.0f;
+
+ /* find out how much it has to move to be 1g */
+ xg = (float)ac->cal_g.x;
+ yg = (float)ac->cal_g.y;
+ zg = (float)ac->cal_g.z;
+
+ /* find out how much it actually moved and normalize to +/- 1g */
+ x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
+ y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
+ z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
+
+ /* make sure x,y,z are between -1 and 1 for the tan functions */
+ if (x < -1.0f) x = -1.0f;
+ else if (x > 1.0f) x = 1.0f;
+ if (y < -1.0f) y = -1.0f;
+ else if (y > 1.0f) y = 1.0f;
+ if (z < -1.0f) z = -1.0f;
+ else if (z > 1.0f) z = 1.0f;
+
+ /* if it is over 1g then it is probably accelerating and not reliable */
+ if (abs(accel->x - ac->cal_zero.x) <= ac->cal_g.x) {
+ /* roll */
+ x = RAD_TO_DEGREE(atan2f(x, z));
+
+ orient->roll = x;
+ orient->a_roll = x;
+ }
+
+ if (abs(accel->y - ac->cal_zero.y) <= ac->cal_g.y) {
+ /* pitch */
+ y = RAD_TO_DEGREE(atan2f(y, z));
+
+ orient->pitch = y;
+ orient->a_pitch = y;
+ }
+
+ /* smooth the angles if enabled */
+ if (smooth) {
+ apply_smoothing(ac, orient, SMOOTH_ROLL);
+ apply_smoothing(ac, orient, SMOOTH_PITCH);
+ }
+}
+
+
+/**
+ * @brief Calculate the gravity forces on each axis.
+ *
+ * @param ac An accelerometer (accel_t) structure.
+ * @param accel [in] Pointer to a vec3b_t structure that holds the raw acceleration data.
+ * @param gforce [out] Pointer to a gforce_t structure that will hold the gravity force data.
+ */
+void calculate_gforce(struct accel_t* ac, struct vec3b_t* accel, struct gforce_t* gforce) {
+ float xg, yg, zg;
+
+ /* find out how much it has to move to be 1g */
+ xg = (float)ac->cal_g.x;
+ yg = (float)ac->cal_g.y;
+ zg = (float)ac->cal_g.z;
+
+ /* find out how much it actually moved and normalize to +/- 1g */
+ gforce->x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
+ gforce->y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
+ gforce->z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
+}
+
+
+/**
+ * @brief Calculate the angle and magnitude of a joystick.
+ *
+ * @param js [out] Pointer to a joystick_t structure.
+ * @param x The raw x-axis value.
+ * @param y The raw y-axis value.
+ */
+void calc_joystick_state(struct joystick_t* js, float x, float y) {
+ float rx, ry, ang;
+
+ /*
+ * Since the joystick center may not be exactly:
+ * (min + max) / 2
+ * Then the range from the min to the center and the center to the max
+ * may be different.
+ * Because of this, depending on if the current x or y value is greater
+ * or less than the assoicated axis center value, it needs to be interpolated
+ * between the center and the minimum or maxmimum rather than between
+ * the minimum and maximum.
+ *
+ * So we have something like this:
+ * (x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max)
+ * Where the * is the current x value.
+ * The range is therefore -1 to 1, 0 being the exact center rather than
+ * the middle of min and max.
+ */
+ if (x == js->center.x)
+ rx = 0;
+ else if (x >= js->center.x)
+ rx = ((float)(x - js->center.x) / (float)(js->max.x - js->center.x));
+ else
+ rx = ((float)(x - js->min.x) / (float)(js->center.x - js->min.x)) - 1.0f;
+
+ if (y == js->center.y)
+ ry = 0;
+ else if (y >= js->center.y)
+ ry = ((float)(y - js->center.y) / (float)(js->max.y - js->center.y));
+ else
+ ry = ((float)(y - js->min.y) / (float)(js->center.y - js->min.y)) - 1.0f;
+
+ /* calculate the joystick angle and magnitude */
+ ang = RAD_TO_DEGREE(atanf(ry / rx));
+ ang -= 90.0f;
+ if (rx < 0.0f)
+ ang -= 180.0f;
+ js->ang = absf(ang);
+ js->mag = (float) sqrt((rx * rx) + (ry * ry));
+}
+
+
+void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type) {
+ switch (type) {
+ case SMOOTH_ROLL:
+ {
+ /* it's possible last iteration was nan or inf, so set it to 0 if that happened */
+ if (isnan(ac->st_roll) || isinf(ac->st_roll))
+ ac->st_roll = 0.0f;
+
+ /*
+ * If the sign changes (which will happen if going from -180 to 180)
+ * or from (-1 to 1) then don't smooth, just use the new angle.
+ */
+ if (((ac->st_roll < 0) && (orient->roll > 0)) || ((ac->st_roll > 0) && (orient->roll < 0))) {
+ ac->st_roll = orient->roll;
+ } else {
+ orient->roll = ac->st_roll + (ac->st_alpha * (orient->a_roll - ac->st_roll));
+ ac->st_roll = orient->roll;
+ }
+
+ return;
+ }
+
+ case SMOOTH_PITCH:
+ {
+ if (isnan(ac->st_pitch) || isinf(ac->st_pitch))
+ ac->st_pitch = 0.0f;
+
+ if (((ac->st_pitch < 0) && (orient->pitch > 0)) || ((ac->st_pitch > 0) && (orient->pitch < 0))) {
+ ac->st_pitch = orient->pitch;
+ } else {
+ orient->pitch = ac->st_pitch + (ac->st_alpha * (orient->a_pitch - ac->st_pitch));
+ ac->st_pitch = orient->pitch;
+ }
+
+ return;
+ }
+ }
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.h
new file mode 100644
index 0000000..2f41d04
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/dynamics.h
@@ -0,0 +1,54 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles the dynamics of the wiimote.
+ *
+ * The file includes functions that handle the dynamics
+ * of the wiimote. Such dynamics include orientation and
+ * motion sensing.
+ */
+
+#pragma once
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void calculate_orientation(struct accel_t* ac, struct vec3b_t* accel, struct orient_t* orient, int smooth);
+void calculate_gforce(struct accel_t* ac, struct vec3b_t* accel, struct gforce_t* gforce);
+void calc_joystick_state(struct joystick_t* js, float x, float y);
+void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.c
new file mode 100644
index 0000000..04c2ea5
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.c
@@ -0,0 +1,878 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles wiimote events.
+ *
+ * The file includes functions that handle the events
+ * that are sent from the wiimote to us.
+ */
+
+#include <stdio.h>
+
+#ifndef WIN32
+ #include <sys/time.h>
+ #include <unistd.h>
+ #include <errno.h>
+#else
+ #include <winsock2.h>
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "definitions.h"
+#include "io.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "ir.h"
+#include "nunchuk.h"
+#include "classic.h"
+#include "guitar_hero_3.h"
+#include "events.h"
+
+static void idle_cycle(struct wiimote_t* wm);
+static void clear_dirty_reads(struct wiimote_t* wm);
+static void propagate_event(struct wiimote_t* wm, byte event, byte* msg);
+static void event_data_read(struct wiimote_t* wm, byte* msg);
+static void event_status(struct wiimote_t* wm, byte* msg);
+static void handle_expansion(struct wiimote_t* wm, byte* msg);
+
+static void save_state(struct wiimote_t* wm);
+static int state_changed(struct wiimote_t* wm);
+
+/**
+ * @brief Poll the wiimotes for any events.
+ *
+ * @param wm An array of pointers to wiimote_t structures.
+ * @param wiimotes The number of wiimote_t structures in the \a wm array.
+ *
+ * @return Returns number of wiimotes that an event has occurred on.
+ *
+ * It is necessary to poll the wiimote devices for events
+ * that occur. If an event occurs on a particular wiimote,
+ * the event variable will be set.
+ */
+int wiiuse_poll(struct wiimote_t** wm, int wiimotes) {
+ int evnt = 0;
+
+ #ifndef WIN32
+ /*
+ * *nix
+ */
+ struct timeval tv;
+ fd_set fds;
+ int r;
+ int i;
+ int highest_fd = -1;
+
+ if (!wm) return 0;
+
+ /* block select() for 1/2000th of a second */
+ tv.tv_sec = 0;
+ tv.tv_usec = 500;
+
+ FD_ZERO(&fds);
+
+ for (i = 0; i < wiimotes; ++i) {
+ /* only poll it if it is connected */
+ if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) {
+ FD_SET(wm[i]->in_sock, &fds);
+
+ /* find the highest fd of the connected wiimotes */
+ if (wm[i]->in_sock > highest_fd)
+ highest_fd = wm[i]->in_sock;
+ }
+
+ wm[i]->event = WIIUSE_NONE;
+ }
+
+ if (highest_fd == -1)
+ /* nothing to poll */
+ return 0;
+
+ if (select(highest_fd + 1, &fds, NULL, NULL, &tv) == -1) {
+ WIIUSE_ERROR("Unable to select() the wiimote interrupt socket(s).");
+ perror("Error Details");
+ return 0;
+ }
+
+ /* check each socket for an event */
+ for (i = 0; i < wiimotes; ++i) {
+ /* if this wiimote is not connected, skip it */
+ if (!WIIMOTE_IS_CONNECTED(wm[i]))
+ continue;
+
+ if (FD_ISSET(wm[i]->in_sock, &fds)) {
+ /* clear out the event buffer */
+ memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf));
+
+ /* clear out any old read requests */
+ clear_dirty_reads(wm[i]);
+
+ /* read the pending message into the buffer */
+ r = read(wm[i]->in_sock, wm[i]->event_buf, sizeof(wm[i]->event_buf));
+ if (r == -1) {
+ /* error reading data */
+ WIIUSE_ERROR("Receiving wiimote data (id %i).", wm[i]->unid);
+ perror("Error Details");
+
+ if (errno == ENOTCONN) {
+ /* this can happen if the bluetooth dongle is disconnected */
+ WIIUSE_ERROR("Bluetooth appears to be disconnected. Wiimote unid %i will be disconnected.", wm[i]->unid);
+ wiiuse_disconnect(wm[i]);
+ wm[i]->event = WIIUSE_UNEXPECTED_DISCONNECT;
+ }
+
+ continue;
+ }
+ if (!r) {
+ /* remote disconnect */
+ wiiuse_disconnected(wm[i]);
+ evnt = 1;
+ continue;
+ }
+
+ /* propagate the event */
+ propagate_event(wm[i], wm[i]->event_buf[1], wm[i]->event_buf+2);
+ evnt += (wm[i]->event != WIIUSE_NONE);
+ } else {
+ idle_cycle(wm[i]);
+ }
+ }
+ #else
+ /*
+ * Windows
+ */
+ int i;
+
+ if (!wm) return 0;
+
+ for (i = 0; i < wiimotes; ++i) {
+ wm[i]->event = WIIUSE_NONE;
+
+ if (wiiuse_io_read(wm[i])) {
+ /* propagate the event */
+ propagate_event(wm[i], wm[i]->event_buf[0], wm[i]->event_buf+1);
+ evnt += (wm[i]->event != WIIUSE_NONE);
+
+ /* clear out the event buffer */
+ memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf));
+ } else {
+ idle_cycle(wm[i]);
+ }
+ }
+ #endif
+
+ return evnt;
+}
+
+
+/**
+ * @brief Called on a cycle where no significant change occurs.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+static void idle_cycle(struct wiimote_t* wm) {
+ /*
+ * Smooth the angles.
+ *
+ * This is done to make sure that on every cycle the orientation
+ * angles are smoothed. Normally when an event occurs the angles
+ * are updated and smoothed, but if no packet comes in then the
+ * angles remain the same. This means the angle wiiuse reports
+ * is still an old value. Smoothing needs to be applied in this
+ * case in order for the angle it reports to converge to the true
+ * angle of the device.
+ */
+ if (WIIUSE_USING_ACC(wm) && WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)) {
+ apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_ROLL);
+ apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_PITCH);
+ }
+
+ /* clear out any old read requests */
+ clear_dirty_reads(wm);
+}
+
+
+/**
+ * @brief Clear out all old 'dirty' read requests.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+static void clear_dirty_reads(struct wiimote_t* wm) {
+ struct read_req_t* req = wm->read_req;
+
+ while (req && req->dirty) {
+ WIIUSE_DEBUG("Cleared old read request for address: %x", req->addr);
+
+ wm->read_req = req->next;
+ free(req);
+ req = wm->read_req;
+ }
+}
+
+
+/**
+ * @brief Analyze the event that occurred on a wiimote.
+ *
+ * @param wm An array of pointers to wiimote_t structures.
+ * @param event The event that occurred.
+ * @param msg The message specified in the event packet.
+ *
+ * Pass the event to the registered event callback.
+ */
+static void propagate_event(struct wiimote_t* wm, byte event, byte* msg) {
+ save_state(wm);
+
+ switch (event) {
+ case WM_RPT_BTN:
+ {
+ /* button */
+ wiiuse_pressed_buttons(wm, msg);
+ break;
+ }
+ case WM_RPT_BTN_ACC:
+ {
+ /* button - motion */
+ wiiuse_pressed_buttons(wm, msg);
+
+ wm->accel.x = msg[2];
+ wm->accel.y = msg[3];
+ wm->accel.z = msg[4];
+
+ /* calculate the remote orientation */
+ calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+
+ /* calculate the gforces on each axis */
+ calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+ break;
+ }
+ case WM_RPT_READ:
+ {
+ /* data read */
+ event_data_read(wm, msg);
+
+ /* yeah buttons may be pressed, but this wasn't an "event" */
+ return;
+ }
+ case WM_RPT_CTRL_STATUS:
+ {
+ /* controller status */
+ event_status(wm, msg);
+
+ /* don't execute the event callback */
+ return;
+ }
+ case WM_RPT_BTN_EXP:
+ {
+ /* button - expansion */
+ wiiuse_pressed_buttons(wm, msg);
+ handle_expansion(wm, msg+2);
+
+ break;
+ }
+ case WM_RPT_BTN_ACC_EXP:
+ {
+ /* button - motion - expansion */
+ wiiuse_pressed_buttons(wm, msg);
+
+ wm->accel.x = msg[2];
+ wm->accel.y = msg[3];
+ wm->accel.z = msg[4];
+
+ calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+ calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+ handle_expansion(wm, msg+5);
+
+ break;
+ }
+ case WM_RPT_BTN_ACC_IR:
+ {
+ /* button - motion - ir */
+ wiiuse_pressed_buttons(wm, msg);
+
+ wm->accel.x = msg[2];
+ wm->accel.y = msg[3];
+ wm->accel.z = msg[4];
+
+ calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+ calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+ /* ir */
+ calculate_extended_ir(wm, msg+5);
+
+ break;
+ }
+ case WM_RPT_BTN_IR_EXP:
+ {
+ /* button - ir - expansion */
+ wiiuse_pressed_buttons(wm, msg);
+ handle_expansion(wm, msg+12);
+
+ /* ir */
+ calculate_basic_ir(wm, msg+2);
+
+ break;
+ }
+ case WM_RPT_BTN_ACC_IR_EXP:
+ {
+ /* button - motion - ir - expansion */
+ wiiuse_pressed_buttons(wm, msg);
+
+ wm->accel.x = msg[2];
+ wm->accel.y = msg[3];
+ wm->accel.z = msg[4];
+
+ calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+ calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+ handle_expansion(wm, msg+15);
+
+ /* ir */
+ calculate_basic_ir(wm, msg+5);
+
+ break;
+ }
+ case WM_RPT_WRITE:
+ {
+ /* write feedback - safe to skip */
+ break;
+ }
+ default:
+ {
+ WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event);
+ return;
+ }
+ }
+
+ /* was there an event? */
+ if (state_changed(wm))
+ wm->event = WIIUSE_EVENT;
+}
+
+
+/**
+ * @brief Find what buttons are pressed.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param msg The message specified in the event packet.
+ */
+void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg) {
+ short now;
+
+ /* convert to big endian */
+ now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL;
+
+ /* pressed now & were pressed, then held */
+ wm->btns_held = (now & wm->btns);
+
+ /* were pressed or were held & not pressed now, then released */
+ wm->btns_released = ((wm->btns | wm->btns_held) & ~now);
+
+ /* buttons pressed now */
+ wm->btns = now;
+}
+
+
+/**
+ * @brief Received a data packet from a read request.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param msg The message specified in the event packet.
+ *
+ * Data from the wiimote comes in packets. If the requested
+ * data segment size is bigger than one packet can hold then
+ * several packets will be received. These packets are first
+ * reassembled into one, then the registered callback function
+ * that handles data reads is invoked.
+ */
+static void event_data_read(struct wiimote_t* wm, byte* msg) {
+ /* we must always assume the packet received is from the most recent request */
+ byte err;
+ byte len;
+ unsigned short offset;
+ struct read_req_t* req = wm->read_req;
+
+ wiiuse_pressed_buttons(wm, msg);
+
+ /* find the next non-dirty request */
+ while (req && req->dirty)
+ req = req->next;
+
+ /* if we don't have a request out then we didn't ask for this packet */
+ if (!req) {
+ WIIUSE_WARNING("Received data packet when no request was made.");
+ return;
+ }
+
+ err = msg[2] & 0x0F;
+
+ if (err == 0x08)
+ WIIUSE_WARNING("Unable to read data - address does not exist.");
+ else if (err == 0x07)
+ WIIUSE_WARNING("Unable to read data - address is for write-only registers.");
+ else if (err)
+ WIIUSE_WARNING("Unable to read data - unknown error code %x.", err);
+
+ if (err) {
+ /* this request errored out, so skip it and go to the next one */
+
+ /* delete this request */
+ wm->read_req = req->next;
+ free(req);
+
+ /* if another request exists send it to the wiimote */
+ if (wm->read_req)
+ wiiuse_send_next_pending_read_request(wm);
+
+ return;
+ }
+
+ len = ((msg[2] & 0xF0) >> 4) + 1;
+ offset = BIG_ENDIAN_SHORT(*(unsigned short*)(msg + 3));
+ req->addr = (req->addr & 0xFFFF);
+
+ req->wait -= len;
+ if (req->wait >= req->size)
+ /* this should never happen */
+ req->wait = 0;
+
+ WIIUSE_DEBUG("Received read packet:");
+ WIIUSE_DEBUG(" Packet read offset: %i bytes", offset);
+ WIIUSE_DEBUG(" Request read offset: %i bytes", req->addr);
+ WIIUSE_DEBUG(" Read offset into buf: %i bytes", offset - req->addr);
+ WIIUSE_DEBUG(" Read data size: %i bytes", len);
+ WIIUSE_DEBUG(" Still need: %i bytes", req->wait);
+
+ /* reconstruct this part of the data */
+ memcpy((req->buf + offset - req->addr), (msg + 5), len);
+
+ #ifdef WITH_WIIUSE_DEBUG
+ {
+ int i = 0;
+ printf("Read: ");
+ for (; i < req->size - req->wait; ++i)
+ printf("%x ", req->buf[i]);
+ printf("\n");
+ }
+ #endif
+
+ /* if all data has been received, execute the read event callback or generate event */
+ if (!req->wait) {
+ if (req->cb) {
+ /* this was a callback, so invoke it now */
+ req->cb(wm, req->buf, req->size);
+
+ /* delete this request */
+ wm->read_req = req->next;
+ free(req);
+ } else {
+ /*
+ * This should generate an event.
+ * We need to leave the event in the array so the client
+ * can access it still. We'll flag is as being 'dirty'
+ * and give the client one cycle to use it. Next event
+ * we will remove it from the list.
+ */
+ wm->event = WIIUSE_READ_DATA;
+ req->dirty = 1;
+ }
+
+ /* if another request exists send it to the wiimote */
+ if (wm->read_req)
+ wiiuse_send_next_pending_read_request(wm);
+ }
+}
+
+
+/**
+ * @brief Read the controller status.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param msg The message specified in the event packet.
+ *
+ * Read the controller status and execute the registered status callback.
+ */
+static void event_status(struct wiimote_t* wm, byte* msg) {
+ int led[4] = {0};
+ int attachment = 0;
+ int ir = 0;
+ int exp_changed = 0;
+
+ /*
+ * An event occurred.
+ * This event can be overwritten by a more specific
+ * event type during a handshake or expansion removal.
+ */
+ wm->event = WIIUSE_STATUS;
+
+ wiiuse_pressed_buttons(wm, msg);
+
+ /* find what LEDs are lit */
+ if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_1) led[0] = 1;
+ if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_2) led[1] = 1;
+ if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_3) led[2] = 1;
+ if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_4) led[3] = 1;
+
+ /* is an attachment connected to the expansion port? */
+ if ((msg[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT)
+ attachment = 1;
+
+ /* is the speaker enabled? */
+ if ((msg[2] & WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) == WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED)
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_SPEAKER);
+
+ /* is IR sensing enabled? */
+ if ((msg[2] & WM_CTRL_STATUS_BYTE1_IR_ENABLED) == WM_CTRL_STATUS_BYTE1_IR_ENABLED)
+ ir = 1;
+
+ /* find the battery level and normalize between 0 and 1 */
+ wm->battery_level = (msg[5] / (float)WM_MAX_BATTERY_CODE);
+
+ /* expansion port */
+ if (attachment && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
+ /* send the initialization code for the attachment */
+ handshake_expansion(wm, NULL, 0);
+ exp_changed = 1;
+ } else if (!attachment && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
+ /* attachment removed */
+ disable_expansion(wm);
+ exp_changed = 1;
+ }
+
+ #ifdef WIN32
+ if (!attachment) {
+ WIIUSE_DEBUG("Setting timeout to normal %i ms.", wm->normal_timeout);
+ wm->timeout = wm->normal_timeout;
+ }
+ #endif
+
+ /*
+ * From now on the remote will only send status packets.
+ * We need to send a WIIMOTE_CMD_REPORT_TYPE packet to
+ * reenable other incoming reports.
+ */
+ if (exp_changed && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
+ /*
+ * Since the expansion status changed IR needs to
+ * be reset for the new IR report mode.
+ */
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
+ wiiuse_set_ir(wm, 1);
+ } else
+ wiiuse_set_report_type(wm);
+}
+
+
+/**
+ * @brief Handle data from the expansion.
+ *
+ * @param wm A pointer to a wiimote_t structure.
+ * @param msg The message specified in the event packet for the expansion.
+ */
+static void handle_expansion(struct wiimote_t* wm, byte* msg) {
+ switch (wm->exp.type) {
+ case EXP_NUNCHUK:
+ nunchuk_event(&wm->exp.nunchuk, msg);
+ break;
+ case EXP_CLASSIC:
+ classic_ctrl_event(&wm->exp.classic, msg);
+ break;
+ case EXP_GUITAR_HERO_3:
+ guitar_hero_3_event(&wm->exp.gh3, msg);
+ break;
+ default:
+ break;
+ }
+}
+
+
+/**
+ * @brief Handle the handshake data from the expansion device.
+ *
+ * @param wm A pointer to a wiimote_t structure.
+ * @param data The data read in from the device.
+ * @param len The length of the data block, in bytes.
+ *
+ * Tries to determine what kind of expansion was attached
+ * and invoke the correct handshake function.
+ *
+ * If the data is NULL then this function will try to start
+ * a handshake with the expansion.
+ */
+void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len) {
+ int id;
+
+ if (!data) {
+ byte* handshake_buf;
+ byte buf = 0x00;
+
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
+ disable_expansion(wm);
+
+ /* increase the timeout until the handshake completes */
+ #ifdef WIN32
+ WIIUSE_DEBUG("Setting timeout to expansion %i ms.", wm->exp_timeout);
+ wm->timeout = wm->exp_timeout;
+ #endif
+
+ wiiuse_write_data(wm, WM_EXP_MEM_ENABLE, &buf, 1);
+
+ /* get the calibration data */
+ handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+ wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+ /* tell the wiimote to send expansion data */
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP);
+
+ return;
+ }
+
+ id = BIG_ENDIAN_LONG(*(int*)(data + 220));
+
+ /* call the corresponding handshake function for this expansion */
+ switch (id) {
+ case EXP_ID_CODE_NUNCHUK:
+ {
+ if (nunchuk_handshake(wm, &wm->exp.nunchuk, data, len))
+ wm->event = WIIUSE_NUNCHUK_INSERTED;
+ break;
+ }
+ case EXP_ID_CODE_CLASSIC_CONTROLLER:
+ {
+ if (classic_ctrl_handshake(wm, &wm->exp.classic, data, len))
+ wm->event = WIIUSE_CLASSIC_CTRL_INSERTED;
+ break;
+ }
+ case EXP_ID_CODE_GUITAR:
+ {
+ if (guitar_hero_3_handshake(wm, &wm->exp.gh3, data, len))
+ wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED;
+ break;
+ }
+ default:
+ {
+ WIIUSE_WARNING("Unknown expansion type. Code: 0x%x", id);
+ break;
+ }
+ }
+
+ free(data);
+}
+
+
+
+/**
+ * @brief Disable the expansion device if it was enabled.
+ *
+ * @param wm A pointer to a wiimote_t structure.
+ * @param data The data read in from the device.
+ * @param len The length of the data block, in bytes.
+ *
+ * If the data is NULL then this function will try to start
+ * a handshake with the expansion.
+ */
+void disable_expansion(struct wiimote_t* wm) {
+ if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
+ return;
+
+ /* tell the assoicated module the expansion was removed */
+ switch (wm->exp.type) {
+ case EXP_NUNCHUK:
+ nunchuk_disconnected(&wm->exp.nunchuk);
+ wm->event = WIIUSE_NUNCHUK_REMOVED;
+ break;
+ case EXP_CLASSIC:
+ classic_ctrl_disconnected(&wm->exp.classic);
+ wm->event = WIIUSE_CLASSIC_CTRL_REMOVED;
+ break;
+ case EXP_GUITAR_HERO_3:
+ guitar_hero_3_disconnected(&wm->exp.gh3);
+ wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED;
+ break;
+ default:
+ break;
+ }
+
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
+ wm->exp.type = EXP_NONE;
+}
+
+
+/**
+ * @brief Save important state data.
+ * @param wm A pointer to a wiimote_t structure.
+ */
+static void save_state(struct wiimote_t* wm) {
+ /* wiimote */
+ wm->lstate.btns = wm->btns;
+ wm->lstate.accel = wm->accel;
+
+ /* ir */
+ if (WIIUSE_USING_IR(wm)) {
+ wm->lstate.ir_ax = wm->ir.ax;
+ wm->lstate.ir_ay = wm->ir.ay;
+ wm->lstate.ir_distance = wm->ir.distance;
+ }
+
+ /* expansion */
+ switch (wm->exp.type) {
+ case EXP_NUNCHUK:
+ wm->lstate.exp_ljs_ang = wm->exp.nunchuk.js.ang;
+ wm->lstate.exp_ljs_mag = wm->exp.nunchuk.js.mag;
+ wm->lstate.exp_btns = wm->exp.nunchuk.btns;
+ wm->lstate.exp_accel = wm->exp.nunchuk.accel;
+ break;
+
+ case EXP_CLASSIC:
+ wm->lstate.exp_ljs_ang = wm->exp.classic.ljs.ang;
+ wm->lstate.exp_ljs_mag = wm->exp.classic.ljs.mag;
+ wm->lstate.exp_rjs_ang = wm->exp.classic.rjs.ang;
+ wm->lstate.exp_rjs_mag = wm->exp.classic.rjs.mag;
+ wm->lstate.exp_r_shoulder = wm->exp.classic.r_shoulder;
+ wm->lstate.exp_l_shoulder = wm->exp.classic.l_shoulder;
+ wm->lstate.exp_btns = wm->exp.classic.btns;
+ break;
+
+ case EXP_GUITAR_HERO_3:
+ wm->lstate.exp_ljs_ang = wm->exp.gh3.js.ang;
+ wm->lstate.exp_ljs_mag = wm->exp.gh3.js.mag;
+ wm->lstate.exp_r_shoulder = wm->exp.gh3.whammy_bar;
+ wm->lstate.exp_btns = wm->exp.gh3.btns;
+ break;
+
+ case EXP_NONE:
+ break;
+ }
+}
+
+
+/**
+ * @brief Determine if the current state differs significantly from the previous.
+ * @param wm A pointer to a wiimote_t structure.
+ * @return 1 if a significant change occurred, 0 if not.
+ */
+static int state_changed(struct wiimote_t* wm) {
+ #define STATE_CHANGED(a, b) if (a != b) return 1
+
+ #define CROSS_THRESH(last, now, thresh) \
+ do { \
+ if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \
+ if ((diff_f(last.roll, now.roll) >= thresh) || \
+ (diff_f(last.pitch, now.pitch) >= thresh) || \
+ (diff_f(last.yaw, now.yaw) >= thresh)) \
+ { \
+ last = now; \
+ return 1; \
+ } \
+ } else { \
+ if (last.roll != now.roll) return 1; \
+ if (last.pitch != now.pitch) return 1; \
+ if (last.yaw != now.yaw) return 1; \
+ } \
+ } while (0)
+
+ #define CROSS_THRESH_XYZ(last, now, thresh) \
+ do { \
+ if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \
+ if ((diff_f(last.x, now.x) >= thresh) || \
+ (diff_f(last.y, now.y) >= thresh) || \
+ (diff_f(last.z, now.z) >= thresh)) \
+ { \
+ last = now; \
+ return 1; \
+ } \
+ } else { \
+ if (last.x != now.x) return 1; \
+ if (last.y != now.y) return 1; \
+ if (last.z != now.z) return 1; \
+ } \
+ } while (0)
+
+ /* ir */
+ if (WIIUSE_USING_IR(wm)) {
+ STATE_CHANGED(wm->lstate.ir_ax, wm->ir.ax);
+ STATE_CHANGED(wm->lstate.ir_ay, wm->ir.ay);
+ STATE_CHANGED(wm->lstate.ir_distance, wm->ir.distance);
+ }
+
+ /* accelerometer */
+ if (WIIUSE_USING_ACC(wm)) {
+ /* raw accelerometer */
+ CROSS_THRESH_XYZ(wm->lstate.accel, wm->accel, wm->accel_threshold);
+
+ /* orientation */
+ CROSS_THRESH(wm->lstate.orient, wm->orient, wm->orient_threshold);
+ }
+
+ /* expansion */
+ switch (wm->exp.type) {
+ case EXP_NUNCHUK:
+ {
+ STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.nunchuk.js.ang);
+ STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.nunchuk.js.mag);
+ STATE_CHANGED(wm->lstate.exp_btns, wm->exp.nunchuk.btns);
+
+ CROSS_THRESH(wm->lstate.exp_orient, wm->exp.nunchuk.orient, wm->exp.nunchuk.orient_threshold);
+ CROSS_THRESH_XYZ(wm->lstate.exp_accel, wm->exp.nunchuk.accel, wm->exp.nunchuk.accel_threshold);
+ break;
+ }
+ case EXP_CLASSIC:
+ {
+ STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.classic.ljs.ang);
+ STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.classic.ljs.mag);
+ STATE_CHANGED(wm->lstate.exp_rjs_ang, wm->exp.classic.rjs.ang);
+ STATE_CHANGED(wm->lstate.exp_rjs_mag, wm->exp.classic.rjs.mag);
+ STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.classic.r_shoulder);
+ STATE_CHANGED(wm->lstate.exp_l_shoulder, wm->exp.classic.l_shoulder);
+ STATE_CHANGED(wm->lstate.exp_btns, wm->exp.classic.btns);
+ break;
+ }
+ case EXP_GUITAR_HERO_3:
+ {
+ STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.gh3.js.ang);
+ STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.gh3.js.mag);
+ STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.gh3.whammy_bar);
+ STATE_CHANGED(wm->lstate.exp_btns, wm->exp.gh3.btns);
+ break;
+ }
+ case EXP_NONE:
+ {
+ break;
+ }
+ }
+
+ STATE_CHANGED(wm->lstate.btns, wm->btns);
+
+ return 0;
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.h
new file mode 100644
index 0000000..9b9121c
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/events.h
@@ -0,0 +1,51 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles wiimote events.
+ *
+ * The file includes functions that handle the events
+ * that are sent from the wiimote to us.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg);
+
+void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len);
+void disable_expansion(struct wiimote_t* wm);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.c
new file mode 100644
index 0000000..29c58af
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.c
@@ -0,0 +1,172 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Guitar Hero 3 expansion device.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+ #include <Winsock2.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "events.h"
+#include "guitar_hero_3.h"
+
+static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now);
+
+/**
+ * @brief Handle the handshake data from the guitar.
+ *
+ * @param cc A pointer to a classic_ctrl_t structure.
+ * @param data The data read in from the device.
+ * @param len The length of the data block, in bytes.
+ *
+ * @return Returns 1 if handshake was successful, 0 if not.
+ */
+int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len) {
+ int i;
+ int offset = 0;
+
+ /*
+ * The good fellows that made the Guitar Hero 3 controller
+ * failed to factory calibrate the devices. There is no
+ * calibration data on the device.
+ */
+
+ gh3->btns = 0;
+ gh3->btns_held = 0;
+ gh3->btns_released = 0;
+ gh3->whammy_bar = 0.0f;
+
+ /* decrypt data */
+ for (i = 0; i < len; ++i)
+ data[i] = (data[i] ^ 0x17) + 0x17;
+
+ if (data[offset] == 0xFF) {
+ /*
+ * Sometimes the data returned here is not correct.
+ * This might happen because the wiimote is lagging
+ * behind our initialization sequence.
+ * To fix this just request the handshake again.
+ *
+ * Other times it's just the first 16 bytes are 0xFF,
+ * but since the next 16 bytes are the same, just use
+ * those.
+ */
+ if (data[offset + 16] == 0xFF) {
+ /* get the calibration data */
+ byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+
+ WIIUSE_DEBUG("Guitar Hero 3 handshake appears invalid, trying again.");
+ wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+ return 0;
+ } else
+ offset += 16;
+ }
+
+ /* joystick stuff */
+ gh3->js.max.x = GUITAR_HERO_3_JS_MAX_X;
+ gh3->js.min.x = GUITAR_HERO_3_JS_MIN_X;
+ gh3->js.center.x = GUITAR_HERO_3_JS_CENTER_X;
+ gh3->js.max.y = GUITAR_HERO_3_JS_MAX_Y;
+ gh3->js.min.y = GUITAR_HERO_3_JS_MIN_Y;
+ gh3->js.center.y = GUITAR_HERO_3_JS_CENTER_Y;
+
+ /* handshake done */
+ wm->exp.type = EXP_GUITAR_HERO_3;
+
+ #ifdef WIN32
+ wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
+ #endif
+
+ return 1;
+}
+
+
+/**
+ * @brief The guitar disconnected.
+ *
+ * @param cc A pointer to a classic_ctrl_t structure.
+ */
+void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3) {
+ memset(gh3, 0, sizeof(struct guitar_hero_3_t));
+}
+
+
+
+/**
+ * @brief Handle guitar event.
+ *
+ * @param cc A pointer to a classic_ctrl_t structure.
+ * @param msg The message specified in the event packet.
+ */
+void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg) {
+ int i;
+
+ /* decrypt data */
+ for (i = 0; i < 6; ++i)
+ msg[i] = (msg[i] ^ 0x17) + 0x17;
+
+ guitar_hero_3_pressed_buttons(gh3, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
+
+ /* whammy bar */
+ gh3->whammy_bar = (msg[3] - GUITAR_HERO_3_WHAMMY_BAR_MIN) / (float)(GUITAR_HERO_3_WHAMMY_BAR_MAX - GUITAR_HERO_3_WHAMMY_BAR_MIN);
+
+ /* joy stick */
+ calc_joystick_state(&gh3->js, msg[0], msg[1]);
+}
+
+
+/**
+ * @brief Find what buttons are pressed.
+ *
+ * @param cc A pointer to a classic_ctrl_t structure.
+ * @param msg The message byte specified in the event packet.
+ */
+static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now) {
+ /* message is inverted (0 is active, 1 is inactive) */
+ now = ~now & GUITAR_HERO_3_BUTTON_ALL;
+
+ /* pressed now & were pressed, then held */
+ gh3->btns_held = (now & gh3->btns);
+
+ /* were pressed or were held & not pressed now, then released */
+ gh3->btns_released = ((gh3->btns | gh3->btns_held) & ~now);
+
+ /* buttons pressed now */
+ gh3->btns = now;
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.h
new file mode 100644
index 0000000..a8c8ffa
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/guitar_hero_3.h
@@ -0,0 +1,60 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Guitar Hero 3 expansion device.
+ */
+
+#pragma once
+
+#include "wiiuse_internal.h"
+
+#define GUITAR_HERO_3_JS_MIN_X 0xC5
+#define GUITAR_HERO_3_JS_MAX_X 0xFC
+#define GUITAR_HERO_3_JS_CENTER_X 0xE0
+#define GUITAR_HERO_3_JS_MIN_Y 0xC5
+#define GUITAR_HERO_3_JS_MAX_Y 0xFA
+#define GUITAR_HERO_3_JS_CENTER_Y 0xE0
+#define GUITAR_HERO_3_WHAMMY_BAR_MIN 0xEF
+#define GUITAR_HERO_3_WHAMMY_BAR_MAX 0xFA
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len);
+
+void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3);
+
+void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.c
new file mode 100644
index 0000000..65b3627
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.c
@@ -0,0 +1,119 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles device I/O (non-OS specific).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "io.h"
+
+
+ /**
+ * @brief Get initialization data from the wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param data unused
+ * @param len unused
+ *
+ * When first called for a wiimote_t structure, a request
+ * is sent to the wiimote for initialization information.
+ * This includes factory set accelerometer data.
+ * The handshake will be concluded when the wiimote responds
+ * with this data.
+ */
+void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len) {
+ if (!wm) return;
+
+ switch (wm->handshake_state) {
+ case 0:
+ {
+ /* send request to wiimote for accelerometer calibration */
+ byte* buf;
+
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
+ wiiuse_set_leds(wm, WIIMOTE_LED_NONE);
+
+ buf = (byte*)malloc(sizeof(byte) * 8);
+ wiiuse_read_data_cb(wm, wiiuse_handshake, buf, WM_MEM_OFFSET_CALIBRATION, 7);
+ wm->handshake_state++;
+
+ wiiuse_set_leds(wm, WIIMOTE_LED_NONE);
+
+ break;
+ }
+ case 1:
+ {
+ struct read_req_t* req = wm->read_req;
+ struct accel_t* accel = &wm->accel_calib;
+
+ /* received read data */
+ accel->cal_zero.x = req->buf[0];
+ accel->cal_zero.y = req->buf[1];
+ accel->cal_zero.z = req->buf[2];
+
+ accel->cal_g.x = req->buf[4] - accel->cal_zero.x;
+ accel->cal_g.y = req->buf[5] - accel->cal_zero.y;
+ accel->cal_g.z = req->buf[6] - accel->cal_zero.z;
+
+ /* done with the buffer */
+ free(req->buf);
+
+ /* handshake is done */
+ WIIUSE_DEBUG("Handshake finished. Calibration: Idle: X=%x Y=%x Z=%x\t+1g: X=%x Y=%x Z=%x",
+ accel->cal_zero.x, accel->cal_zero.y, accel->cal_zero.z,
+ accel->cal_g.x, accel->cal_g.y, accel->cal_g.z);
+
+
+ /* request the status of the wiimote to see if there is an expansion */
+ wiiuse_status(wm);
+
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
+ wm->handshake_state++;
+
+ /* now enable IR if it was set before the handshake completed */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
+ WIIUSE_DEBUG("Handshake finished, enabling IR.");
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
+ wiiuse_set_ir(wm, 1);
+ }
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.h
new file mode 100644
index 0000000..19e7031
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io.h
@@ -0,0 +1,54 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles device I/O.
+ */
+
+#pragma once
+
+#ifndef WIN32
+ #include <bluetooth/bluetooth.h>
+#endif
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len);
+
+int wiiuse_io_read(struct wiimote_t* wm);
+int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_nix.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_nix.c
new file mode 100644
index 0000000..0f2c5b8
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_nix.c
@@ -0,0 +1,271 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles device I/O for *nix.
+ */
+
+#ifndef WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/l2cap.h>
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "io.h"
+
+static int wiiuse_connect_single(struct wiimote_t* wm, char* address);
+
+/**
+ * @brief Find a wiimote or wiimotes.
+ *
+ * @param wm An array of wiimote_t structures.
+ * @param max_wiimotes The number of wiimote structures in \a wm.
+ * @param timeout The number of seconds before the search times out.
+ *
+ * @return The number of wiimotes found.
+ *
+ * @see wiimote_connect()
+ *
+ * This function will only look for wiimote devices. \n
+ * When a device is found the address in the structures will be set. \n
+ * You can then call wiimote_connect() to connect to the found \n
+ * devices.
+ */
+int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
+ int device_id;
+ int device_sock;
+ int found_devices;
+ int found_wiimotes;
+
+ /* reset all wiimote bluetooth device addresses */
+ for (found_wiimotes = 0; found_wiimotes < max_wiimotes; ++found_wiimotes)
+ wm[found_wiimotes]->bdaddr = *BDADDR_ANY;
+ found_wiimotes = 0;
+
+ /* get the id of the first bluetooth device. */
+ device_id = hci_get_route(NULL);
+ if (device_id < 0) {
+ perror("hci_get_route");
+ return 0;
+ }
+
+ /* create a socket to the device */
+ device_sock = hci_open_dev(device_id);
+ if (device_sock < 0) {
+ perror("hci_open_dev");
+ return 0;
+ }
+
+ inquiry_info scan_info_arr[128];
+ inquiry_info* scan_info = scan_info_arr;
+ memset(&scan_info_arr, 0, sizeof(scan_info_arr));
+
+ /* scan for bluetooth devices for 'timeout' seconds */
+ found_devices = hci_inquiry(device_id, timeout, 128, NULL, &scan_info, IREQ_CACHE_FLUSH);
+ if (found_devices < 0) {
+ perror("hci_inquiry");
+ return 0;
+ }
+
+ WIIUSE_INFO("Found %i bluetooth device(s).", found_devices);
+
+ int i = 0;
+
+ /* display discovered devices */
+ for (; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) {
+ if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) &&
+ (scan_info[i].dev_class[1] == WM_DEV_CLASS_1) &&
+ (scan_info[i].dev_class[2] == WM_DEV_CLASS_2))
+ {
+ /* found a device */
+ ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str);
+
+ WIIUSE_INFO("Found wiimote (%s) [id %i].", wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid);
+
+ wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr;
+ WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND);
+ ++found_wiimotes;
+ }
+ }
+
+ close(device_sock);
+ return found_wiimotes;
+}
+
+
+/**
+ * @brief Connect to a wiimote or wiimotes once an address is known.
+ *
+ * @param wm An array of wiimote_t structures.
+ * @param wiimotes The number of wiimote structures in \a wm.
+ *
+ * @return The number of wiimotes that successfully connected.
+ *
+ * @see wiiuse_find()
+ * @see wiiuse_connect_single()
+ * @see wiiuse_disconnect()
+ *
+ * Connect to a number of wiimotes when the address is already set
+ * in the wiimote_t structures. These addresses are normally set
+ * by the wiiuse_find() function, but can also be set manually.
+ */
+int wiiuse_connect(struct wiimote_t** wm, int wiimotes) {
+ int connected = 0;
+ int i = 0;
+
+ for (; i < wiimotes; ++i) {
+ if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND))
+ /* if the device address is not set, skip it */
+ continue;
+
+ if (wiiuse_connect_single(wm[i], NULL))
+ ++connected;
+ }
+
+ return connected;
+}
+
+
+/**
+ * @brief Connect to a wiimote with a known address.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param address The address of the device to connect to.
+ * If NULL, use the address in the struct set by wiiuse_find().
+ *
+ * @return 1 on success, 0 on failure
+ */
+static int wiiuse_connect_single(struct wiimote_t* wm, char* address) {
+ struct sockaddr_l2 addr;
+
+ memset(&addr, 0, sizeof (addr));
+ if (!wm || WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+
+ addr.l2_family = AF_BLUETOOTH;
+
+ if (address)
+ /* use provided address */
+ str2ba(address, &addr.l2_bdaddr);
+ else
+ /* use address of device discovered */
+ addr.l2_bdaddr = wm->bdaddr;
+
+ /*
+ * OUTPUT CHANNEL
+ */
+ wm->out_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+ if (wm->out_sock == -1)
+ return 0;
+
+ addr.l2_psm = htobs(WM_OUTPUT_CHANNEL);
+
+ /* connect to wiimote */
+ if (connect(wm->out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ perror("connect() output sock");
+ return 0;
+ }
+
+ /*
+ * INPUT CHANNEL
+ */
+ wm->in_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+ if (wm->in_sock == -1) {
+ close(wm->out_sock);
+ wm->out_sock = -1;
+ return 0;
+ }
+
+ addr.l2_psm = htobs(WM_INPUT_CHANNEL);
+
+ /* connect to wiimote */
+ if (connect(wm->in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ perror("connect() interrupt sock");
+ close(wm->out_sock);
+ wm->out_sock = -1;
+ return 0;
+ }
+
+ WIIUSE_INFO("Connected to wiimote [id %i].", wm->unid);
+
+ /* do the handshake */
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
+ wiiuse_handshake(wm, NULL, 0);
+
+ wiiuse_set_report_type(wm);
+
+ return 1;
+}
+
+
+/**
+ * @brief Disconnect a wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ *
+ * @see wiiuse_connect()
+ *
+ * Note that this will not free the wiimote structure.
+ */
+void wiiuse_disconnect(struct wiimote_t* wm) {
+ if (!wm || WIIMOTE_IS_CONNECTED(wm))
+ return;
+
+ close(wm->out_sock);
+ close(wm->in_sock);
+
+ wm->out_sock = -1;
+ wm->in_sock = -1;
+ wm->event = WIIUSE_NONE;
+
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
+}
+
+
+int wiiuse_io_read(struct wiimote_t* wm) {
+ /* not used */
+ return 0;
+}
+
+
+int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) {
+ return write(wm->out_sock, buf, len);
+}
+
+
+
+#endif /* ifndef WIN32 */
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_win.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_win.c
new file mode 100644
index 0000000..6aeeb81
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/io_win.c
@@ -0,0 +1,247 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles device I/O for Windows.
+ */
+
+#ifdef WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <windows.h>
+#include <hidsdi.h>
+#include <setupapi.h>
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "io.h"
+
+
+int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
+ GUID device_id;
+ HANDLE dev;
+ HDEVINFO device_info;
+ int i, index;
+ DWORD len;
+ SP_DEVICE_INTERFACE_DATA device_data;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
+ HIDD_ATTRIBUTES attr;
+ int found = 0;
+
+ (void) timeout; // unused
+
+ device_data.cbSize = sizeof(device_data);
+ index = 0;
+
+ /* get the device id */
+ HidD_GetHidGuid(&device_id);
+
+ /* get all hid devices connected */
+ device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
+
+ for (;; ++index) {
+
+ if (detail_data) {
+ free(detail_data);
+ detail_data = NULL;
+ }
+
+ /* query the next hid device info */
+ if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data))
+ break;
+
+ /* get the size of the data block required */
+ i = SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL);
+ detail_data = malloc(len);
+ detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+ /* query the data for this device */
+ if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL))
+ continue;
+
+ /* open the device */
+ dev = CreateFile(detail_data->DevicePath,
+ (GENERIC_READ | GENERIC_WRITE),
+ (FILE_SHARE_READ | FILE_SHARE_WRITE),
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+ if (dev == INVALID_HANDLE_VALUE)
+ continue;
+
+ /* get device attributes */
+ attr.Size = sizeof(attr);
+ i = HidD_GetAttributes(dev, &attr);
+
+ if ((attr.VendorID == WM_VENDOR_ID) && (attr.ProductID == WM_PRODUCT_ID)) {
+ /* this is a wiimote */
+ wm[found]->dev_handle = dev;
+
+ wm[found]->hid_overlap.hEvent = CreateEvent(NULL, 1, 1, "");
+ wm[found]->hid_overlap.Offset = 0;
+ wm[found]->hid_overlap.OffsetHigh = 0;
+
+ WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_DEV_FOUND);
+ WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED);
+
+ /* try to set the output report to see if the device is actually connected */
+ if (!wiiuse_set_report_type(wm[found])) {
+ WIIMOTE_DISABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED);
+ continue;
+ }
+
+ /* do the handshake */
+ wiiuse_handshake(wm[found], NULL, 0);
+
+ WIIUSE_INFO("Connected to wiimote [id %i].", wm[found]->unid);
+
+ ++found;
+ if (found >= max_wiimotes)
+ break;
+ } else {
+ /* not a wiimote */
+ CloseHandle(dev);
+ }
+ }
+
+ if (detail_data)
+ free(detail_data);
+
+ SetupDiDestroyDeviceInfoList(device_info);
+
+ return found;
+}
+
+
+int wiiuse_connect(struct wiimote_t** wm, int wiimotes) {
+ int connected = 0;
+ int i = 0;
+
+ for (; i < wiimotes; ++i) {
+ if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED))
+ ++connected;
+ }
+
+ return connected;
+}
+
+
+void wiiuse_disconnect(struct wiimote_t* wm) {
+ if (!wm || WIIMOTE_IS_CONNECTED(wm))
+ return;
+
+ CloseHandle(wm->dev_handle);
+ wm->dev_handle = 0;
+
+ ResetEvent(&wm->hid_overlap);
+
+ wm->event = WIIUSE_NONE;
+
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
+}
+
+
+int wiiuse_io_read(struct wiimote_t* wm) {
+ DWORD b, r;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+
+ if (!ReadFile(wm->dev_handle, wm->event_buf, sizeof(wm->event_buf), &b, &wm->hid_overlap)) {
+ /* partial read */
+ b = GetLastError();
+
+ if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) {
+ /* remote disconnect */
+ wiiuse_disconnected(wm);
+ return 0;
+ }
+
+ r = WaitForSingleObject(wm->hid_overlap.hEvent, wm->timeout);
+ if (r == WAIT_TIMEOUT) {
+ /* timeout - cancel and continue */
+
+ if (*wm->event_buf)
+ WIIUSE_WARNING("Packet ignored. This may indicate a problem (timeout is %i ms).", wm->timeout);
+
+ CancelIo(wm->dev_handle);
+ ResetEvent(wm->hid_overlap.hEvent);
+ return 0;
+ } else if (r == WAIT_FAILED) {
+ WIIUSE_WARNING("A wait error occurred on reading from wiimote %i.", wm->unid);
+ return 0;
+ }
+
+ if (!GetOverlappedResult(wm->dev_handle, &wm->hid_overlap, &b, 0))
+ return 0;
+ }
+
+ ResetEvent(wm->hid_overlap.hEvent);
+ return 1;
+}
+
+
+int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) {
+ DWORD bytes;
+ int i;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+
+ switch (wm->stack) {
+ case WIIUSE_STACK_UNKNOWN:
+ {
+ /* try to auto-detect the stack type */
+ if (i = WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap)) {
+ /* bluesoleil will always return 1 here, even if it's not connected */
+ wm->stack = WIIUSE_STACK_BLUESOLEIL;
+ return i;
+ }
+
+ if (i = HidD_SetOutputReport(wm->dev_handle, buf, len)) {
+ wm->stack = WIIUSE_STACK_MS;
+ return i;
+ }
+
+ WIIUSE_ERROR("Unable to determine bluetooth stack type.");
+ return 0;
+ }
+
+ case WIIUSE_STACK_MS:
+ return HidD_SetOutputReport(wm->dev_handle, buf, len);
+
+ case WIIUSE_STACK_BLUESOLEIL:
+ return WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap);
+ }
+
+ return 0;
+}
+
+#endif /* ifdef WIN32 */
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.c
new file mode 100644
index 0000000..7a9bb68
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.c
@@ -0,0 +1,748 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles IR data.
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#ifndef WIN32
+ #include <unistd.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "ir.h"
+
+static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2);
+static void interpret_ir_data(struct wiimote_t* wm);
+static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang);
+static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y);
+static void reorder_ir_dots(struct ir_dot_t* dot);
+static float ir_distance(struct ir_dot_t* dot);
+static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y);
+static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy);
+
+
+/**
+ * @brief Set if the wiimote should track IR targets.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param status 1 to enable, 0 to disable.
+ */
+void wiiuse_set_ir(struct wiimote_t* wm, int status) {
+ byte buf;
+ char* block1 = NULL;
+ char* block2 = NULL;
+ int ir_level;
+
+ if (!wm)
+ return;
+
+ /*
+ * Wait for the handshake to finish first.
+ * When it handshake finishes and sees that
+ * IR is enabled, it will call this function
+ * again to actually enable IR.
+ */
+ if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
+ WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes.");
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
+ return;
+ }
+
+ /*
+ * Check to make sure a sensitivity setting is selected.
+ */
+ ir_level = get_ir_sens(wm, &block1, &block2);
+ if (!ir_level) {
+ WIIUSE_ERROR("No IR sensitivity setting selected.");
+ return;
+ }
+
+ if (status) {
+ /* if already enabled then stop */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
+ return;
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
+ } else {
+ /* if already disabled then stop */
+ if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
+ return;
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
+ }
+
+ /* set camera 1 and 2 */
+ buf = (status ? 0x04 : 0x00);
+ wiiuse_send(wm, WM_CMD_IR, &buf, 1);
+ wiiuse_send(wm, WM_CMD_IR_2, &buf, 1);
+
+ if (!status) {
+ WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid);
+ wiiuse_set_report_type(wm);
+ return;
+ }
+
+ /* enable IR, set sensitivity */
+ buf = 0x08;
+ wiiuse_write_data(wm, WM_REG_IR, &buf, 1);
+
+ /* wait for the wiimote to catch up */
+ #ifndef WIN32
+ usleep(50000);
+ #else
+ Sleep(50);
+ #endif
+
+ /* write sensitivity blocks */
+ wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
+ wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);
+
+ /* set the IR mode */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
+ buf = WM_IR_TYPE_BASIC;
+ else
+ buf = WM_IR_TYPE_EXTENDED;
+ wiiuse_write_data(wm, WM_REG_IR_MODENUM, &buf, 1);
+
+ #ifndef WIN32
+ usleep(50000);
+ #else
+ Sleep(50);
+ #endif
+
+ /* set the wiimote report type */
+ wiiuse_set_report_type(wm);
+
+ WIIUSE_DEBUG("Enabled IR camera for wiimote id %i (sensitivity level %i).", wm->unid, ir_level);
+}
+
+
+/**
+ * @brief Get the IR sensitivity settings.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param block1 [out] Pointer to where block1 will be set.
+ * @param block2 [out] Pointer to where block2 will be set.
+ *
+ * @return Returns the sensitivity level.
+ */
+static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) {
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) {
+ *block1 = WM_IR_BLOCK1_LEVEL1;
+ *block2 = WM_IR_BLOCK2_LEVEL1;
+ return 1;
+ } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) {
+ *block1 = WM_IR_BLOCK1_LEVEL2;
+ *block2 = WM_IR_BLOCK2_LEVEL2;
+ return 2;
+ } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) {
+ *block1 = WM_IR_BLOCK1_LEVEL3;
+ *block2 = WM_IR_BLOCK2_LEVEL3;
+ return 3;
+ } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) {
+ *block1 = WM_IR_BLOCK1_LEVEL4;
+ *block2 = WM_IR_BLOCK2_LEVEL4;
+ return 4;
+ } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) {
+ *block1 = WM_IR_BLOCK1_LEVEL5;
+ *block2 = WM_IR_BLOCK2_LEVEL5;
+ return 5;
+ }
+
+ *block1 = NULL;
+ *block2 = NULL;
+ return 0;
+}
+
+
+/**
+ * @brief Set the virtual screen resolution for IR tracking.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param status 1 to enable, 0 to disable.
+ */
+void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y) {
+ if (!wm) return;
+
+ wm->ir.vres[0] = (x-1);
+ wm->ir.vres[1] = (y-1);
+}
+
+
+/**
+ * @brief Set the XY position for the IR cursor.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos) {
+ if (!wm) return;
+
+ wm->ir.pos = pos;
+
+ switch (pos) {
+
+ case WIIUSE_IR_ABOVE:
+ wm->ir.offset[0] = 0;
+
+ if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
+ wm->ir.offset[1] = WM_ASPECT_16_9_Y/2 - 70;
+ else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
+ wm->ir.offset[1] = WM_ASPECT_4_3_Y/2 - 100;
+
+ return;
+
+ case WIIUSE_IR_BELOW:
+ wm->ir.offset[0] = 0;
+
+ if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
+ wm->ir.offset[1] = -WM_ASPECT_16_9_Y/2 + 100;
+ else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
+ wm->ir.offset[1] = -WM_ASPECT_4_3_Y/2 + 70;
+
+ return;
+
+ default:
+ return;
+ };
+}
+
+
+/**
+ * @brief Set the aspect ratio of the TV/monitor.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param aspect Either WIIUSE_ASPECT_16_9 or WIIUSE_ASPECT_4_3
+ */
+void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect) {
+ if (!wm) return;
+
+ wm->ir.aspect = aspect;
+
+ if (aspect == WIIUSE_ASPECT_4_3) {
+ wm->ir.vres[0] = WM_ASPECT_4_3_X;
+ wm->ir.vres[1] = WM_ASPECT_4_3_Y;
+ } else {
+ wm->ir.vres[0] = WM_ASPECT_16_9_X;
+ wm->ir.vres[1] = WM_ASPECT_16_9_Y;
+ }
+
+ /* reset the position offsets */
+ wiiuse_set_ir_position(wm, wm->ir.pos);
+}
+
+
+/**
+ * @brief Set the IR sensitivity.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param level 1-5, same as Wii system sensitivity setting.
+ *
+ * If the level is < 1, then level will be set to 1.
+ * If the level is > 5, then level will be set to 5.
+ */
+void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) {
+ char* block1 = NULL;
+ char* block2 = NULL;
+
+ if (!wm) return;
+
+ if (level > 5) level = 5;
+ if (level < 1) level = 1;
+
+ WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 |
+ WIIMOTE_STATE_IR_SENS_LVL2 |
+ WIIMOTE_STATE_IR_SENS_LVL3 |
+ WIIMOTE_STATE_IR_SENS_LVL4 |
+ WIIMOTE_STATE_IR_SENS_LVL5));
+
+ switch (level) {
+ case 1:
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1);
+ break;
+ case 2:
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2);
+ break;
+ case 3:
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3);
+ break;
+ case 4:
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4);
+ break;
+ case 5:
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5);
+ break;
+ default:
+ return;
+ }
+
+ /* set the new sensitivity */
+ get_ir_sens(wm, &block1, &block2);
+
+ wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
+ wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);
+
+ WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid);
+}
+
+
+/**
+ * @brief Calculate the data from the IR spots. Basic IR mode.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param data Data returned by the wiimote for the IR spots.
+ */
+void calculate_basic_ir(struct wiimote_t* wm, byte* data) {
+ struct ir_dot_t* dot = wm->ir.dot;
+ int i;
+
+ dot[0].rx = 1023 - (data[0] | ((data[2] & 0x30) << 4));
+ dot[0].ry = data[1] | ((data[2] & 0xC0) << 2);
+
+ dot[1].rx = 1023 - (data[3] | ((data[2] & 0x03) << 8));
+ dot[1].ry = data[4] | ((data[2] & 0x0C) << 6);
+
+ dot[2].rx = 1023 - (data[5] | ((data[7] & 0x30) << 4));
+ dot[2].ry = data[6] | ((data[7] & 0xC0) << 2);
+
+ dot[3].rx = 1023 - (data[8] | ((data[7] & 0x03) << 8));
+ dot[3].ry = data[9] | ((data[7] & 0x0C) << 6);
+
+ /* set each IR spot to visible if spot is in range */
+ for (i = 0; i < 4; ++i) {
+ if (dot[i].ry == 1023)
+ dot[i].visible = 0;
+ else {
+ dot[i].visible = 1;
+ dot[i].size = 0; /* since we don't know the size, set it as 0 */
+ }
+ }
+
+ interpret_ir_data(wm);
+}
+
+
+/**
+ * @brief Calculate the data from the IR spots. Extended IR mode.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param data Data returned by the wiimote for the IR spots.
+ */
+void calculate_extended_ir(struct wiimote_t* wm, byte* data) {
+ struct ir_dot_t* dot = wm->ir.dot;
+ int i;
+
+ for (i = 0; i < 4; ++i) {
+ dot[i].rx = 1023 - (data[3*i] | ((data[(3*i)+2] & 0x30) << 4));
+ dot[i].ry = data[(3*i)+1] | ((data[(3*i)+2] & 0xC0) << 2);
+
+ dot[i].size = data[(3*i)+2] & 0x0F;
+
+ /* if in range set to visible */
+ if (dot[i].ry == 1023)
+ dot[i].visible = 0;
+ else
+ dot[i].visible = 1;
+ }
+
+ interpret_ir_data(wm);
+}
+
+
+/**
+ * @brief Interpret IR data into more user friendly variables.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+static void interpret_ir_data(struct wiimote_t* wm) {
+ struct ir_dot_t* dot = wm->ir.dot;
+ int i;
+ float roll = 0.0f;
+ int last_num_dots = wm->ir.num_dots;
+
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC))
+ roll = wm->orient.roll;
+
+ /* count visible dots */
+ wm->ir.num_dots = 0;
+ for (i = 0; i < 4; ++i) {
+ if (dot[i].visible)
+ wm->ir.num_dots++;
+ }
+
+ switch (wm->ir.num_dots) {
+ case 0:
+ {
+ wm->ir.state = 0;
+
+ /* reset the dot ordering */
+ for (i = 0; i < 4; ++i)
+ dot[i].order = 0;
+
+ wm->ir.x = 0;
+ wm->ir.y = 0;
+ wm->ir.z = 0.0f;
+
+ return;
+ }
+ case 1:
+ {
+ fix_rotated_ir_dots(wm->ir.dot, roll);
+
+ if (wm->ir.state < 2) {
+ /*
+ * Only 1 known dot, so use just that.
+ */
+ for (i = 0; i < 4; ++i) {
+ if (dot[i].visible) {
+ wm->ir.x = dot[i].x;
+ wm->ir.y = dot[i].y;
+
+ wm->ir.ax = wm->ir.x;
+ wm->ir.ay = wm->ir.y;
+
+ /* can't calculate yaw because we don't have the distance */
+ //wm->orient.yaw = calc_yaw(&wm->ir);
+
+ ir_convert_to_vres(&wm->ir.x, &wm->ir.y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
+ break;
+ }
+ }
+ } else {
+ /*
+ * Only see 1 dot but know theres 2.
+ * Try to estimate where the other one
+ * should be and use that.
+ */
+ for (i = 0; i < 4; ++i) {
+ if (dot[i].visible) {
+ int ox = 0;
+ int x, y;
+
+ if (dot[i].order == 1)
+ /* visible is the left dot - estimate where the right is */
+ ox = dot[i].x + wm->ir.distance;
+ else if (dot[i].order == 2)
+ /* visible is the right dot - estimate where the left is */
+ ox = dot[i].x - wm->ir.distance;
+
+ x = ((signed int)dot[i].x + ox) / 2;
+ y = dot[i].y;
+
+ wm->ir.ax = x;
+ wm->ir.ay = y;
+ wm->orient.yaw = calc_yaw(&wm->ir);
+
+ if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
+ ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
+ wm->ir.x = x;
+ wm->ir.y = y;
+ }
+
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ case 2:
+ case 3:
+ case 4:
+ {
+ /*
+ * Two (or more) dots known and seen.
+ * Average them together to estimate the true location.
+ */
+ int x, y;
+ wm->ir.state = 2;
+
+ fix_rotated_ir_dots(wm->ir.dot, roll);
+
+ /* if there is at least 1 new dot, reorder them all */
+ if (wm->ir.num_dots > last_num_dots) {
+ reorder_ir_dots(dot);
+ wm->ir.x = 0;
+ wm->ir.y = 0;
+ }
+
+ wm->ir.distance = ir_distance(dot);
+ wm->ir.z = 1023 - wm->ir.distance;
+
+ get_ir_dot_avg(wm->ir.dot, &x, &y);
+
+ wm->ir.ax = x;
+ wm->ir.ay = y;
+ wm->orient.yaw = calc_yaw(&wm->ir);
+
+ if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
+ ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
+ wm->ir.x = x;
+ wm->ir.y = y;
+ }
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ #ifdef WITH_WIIUSE_DEBUG
+ {
+ int ir_level;
+ WIIUSE_GET_IR_SENSITIVITY(wm, &ir_level);
+ WIIUSE_DEBUG("IR sensitivity: %i", ir_level);
+ WIIUSE_DEBUG("IR visible dots: %i", wm->ir.num_dots);
+ for (i = 0; i < 4; ++i)
+ if (dot[i].visible)
+ WIIUSE_DEBUG("IR[%i][order %i] (%.3i, %.3i) -> (%.3i, %.3i)", i, dot[i].order, dot[i].rx, dot[i].ry, dot[i].x, dot[i].y);
+ WIIUSE_DEBUG("IR[absolute]: (%i, %i)", wm->ir.x, wm->ir.y);
+ }
+ #endif
+}
+
+
+
+/**
+ * @brief Fix the rotation of the IR dots.
+ *
+ * @param dot An array of 4 ir_dot_t objects.
+ * @param ang The roll angle to correct by (-180, 180)
+ *
+ * If there is roll then the dots are rotated
+ * around the origin and give a false cursor
+ * position. Correct for the roll.
+ *
+ * If the accelerometer is off then obviously
+ * this will not do anything and the cursor
+ * position may be inaccurate.
+ */
+static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang) {
+ float s, c;
+ int x, y;
+ int i;
+
+ if (!ang) {
+ for (i = 0; i < 4; ++i) {
+ dot[i].x = dot[i].rx;
+ dot[i].y = dot[i].ry;
+ }
+ return;
+ }
+
+ s = sin(DEGREE_TO_RAD(ang));
+ c = cos(DEGREE_TO_RAD(ang));
+
+ /*
+ * [ cos(theta) -sin(theta) ][ ir->rx ]
+ * [ sin(theta) cos(theta) ][ ir->ry ]
+ */
+
+ for (i = 0; i < 4; ++i) {
+ if (!dot[i].visible)
+ continue;
+
+ x = dot[i].rx - (1024/2);
+ y = dot[i].ry - (768/2);
+
+ dot[i].x = (c * x) + (-s * y);
+ dot[i].y = (s * x) + (c * y);
+
+ dot[i].x += (1024/2);
+ dot[i].y += (768/2);
+ }
+}
+
+
+/**
+ * @brief Average IR dots.
+ *
+ * @param dot An array of 4 ir_dot_t objects.
+ * @param x [out] Average X
+ * @param y [out] Average Y
+ */
+static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y) {
+ int vis = 0, i = 0;
+
+ *x = 0;
+ *y = 0;
+
+ for (; i < 4; ++i) {
+ if (dot[i].visible) {
+ *x += dot[i].x;
+ *y += dot[i].y;
+ ++vis;
+ }
+ }
+
+ *x /= vis;
+ *y /= vis;
+}
+
+
+/**
+ * @brief Reorder the IR dots.
+ *
+ * @param dot An array of 4 ir_dot_t objects.
+ */
+static void reorder_ir_dots(struct ir_dot_t* dot) {
+ int i, j, order;
+
+ /* reset the dot ordering */
+ for (i = 0; i < 4; ++i)
+ dot[i].order = 0;
+
+ for (order = 1; order < 5; ++order) {
+ i = 0;
+
+ for (; !dot[i].visible || dot[i].order; ++i)
+ if (i > 4)
+ return;
+
+ for (j = 0; j < 4; ++j) {
+ if (dot[j].visible && !dot[j].order && (dot[j].x < dot[i].x))
+ i = j;
+ }
+
+ dot[i].order = order;
+ }
+}
+
+
+/**
+ * @brief Calculate the distance between the first 2 visible IR dots.
+ *
+ * @param dot An array of 4 ir_dot_t objects.
+ */
+static float ir_distance(struct ir_dot_t* dot) {
+ int i1, i2;
+ int xd, yd;
+
+ for (i1 = 0; i1 < 4; ++i1)
+ if (dot[i1].visible)
+ break;
+ if (i1 == 4)
+ return 0.0f;
+
+ for (i2 = i1+1; i2 < 4; ++i2)
+ if (dot[i2].visible)
+ break;
+ if (i2 == 4)
+ return 0.0f;
+
+ xd = dot[i2].x - dot[i1].x;
+ yd = dot[i2].y - dot[i1].y;
+
+ return sqrt(xd*xd + yd*yd);
+}
+
+
+/**
+ * @brief Correct for the IR bounding box.
+ *
+ * @param x [out] The current X, it will be updated if valid.
+ * @param y [out] The current Y, it will be updated if valid.
+ * @param aspect Aspect ratio of the screen.
+ * @param offset_x The X offset of the bounding box.
+ * @param offset_y The Y offset of the bounding box.
+ *
+ * @return Returns 1 if the point is valid and was updated.
+ *
+ * Nintendo was smart with this bit. They sacrifice a little
+ * precision for a big increase in usability.
+ */
+static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y) {
+ int x0, y0;
+ int xs, ys;
+
+ if (aspect == WIIUSE_ASPECT_16_9) {
+ xs = WM_ASPECT_16_9_X;
+ ys = WM_ASPECT_16_9_Y;
+ } else {
+ xs = WM_ASPECT_4_3_X;
+ ys = WM_ASPECT_4_3_Y;
+ }
+
+ x0 = ((1024 - xs) / 2) + offset_x;
+ y0 = ((768 - ys) / 2) + offset_y;
+
+ if ((*x >= x0)
+ && (*x <= (x0 + xs))
+ && (*y >= y0)
+ && (*y <= (y0 + ys)))
+ {
+ *x -= offset_x;
+ *y -= offset_y;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * @brief Interpolate the point to the user defined virtual screen resolution.
+ */
+static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy) {
+ int xs, ys;
+
+ if (aspect == WIIUSE_ASPECT_16_9) {
+ xs = WM_ASPECT_16_9_X;
+ ys = WM_ASPECT_16_9_Y;
+ } else {
+ xs = WM_ASPECT_4_3_X;
+ ys = WM_ASPECT_4_3_Y;
+ }
+
+ *x -= ((1024-xs)/2);
+ *y -= ((768-ys)/2);
+
+ *x = (*x / (float)xs) * vx;
+ *y = (*y / (float)ys) * vy;
+}
+
+
+/**
+ * @brief Calculate yaw given the IR data.
+ *
+ * @param ir IR data structure.
+ */
+float calc_yaw(struct ir_t* ir) {
+ float x;
+
+ x = ir->ax - 512;
+ x = x * (ir->z / 1024.0f);
+
+ return RAD_TO_DEGREE( atanf(x / ir->z) );
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.h
new file mode 100644
index 0000000..1b9c5c0
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/ir.h
@@ -0,0 +1,52 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Handles IR data.
+ */
+
+#pragma once
+
+#include "wiiuse_internal.h"
+
+#define WII_VRES_X 560
+#define WII_VRES_Y 340
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void calculate_basic_ir(struct wiimote_t* wm, byte* data);
+void calculate_extended_ir(struct wiimote_t* wm, byte* data);
+float calc_yaw(struct ir_t* ir);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsp b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsp
new file mode 100644
index 0000000..d51562a
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsp
@@ -0,0 +1,191 @@
+# Microsoft Developer Studio Project File - Name="wiiuse" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=wiiuse - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "wiiuse.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "wiiuse.mak" CFG="wiiuse - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "wiiuse - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "wiiuse - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "wiiuse - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib hid.lib setupapi.lib /nologo /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "wiiuse - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIIUSE_EXPORTS" /D "WITH_WIIUSE_DEBUG" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib hid.lib setupapi.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "wiiuse - Win32 Release"
+# Name "wiiuse - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\classic.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dynamics.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\events.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\guitar_hero_3.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\io.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\io_nix.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\io_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ir.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nunchuk.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\wiiuse.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\classic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\definitions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\dynamics.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\events.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\guitar_hero_3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\io.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\nunchuk.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\os.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\wiiuse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\wiiuse_internal.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=..\..\CHANGELOG
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsw b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsw
new file mode 100644
index 0000000..1983225
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "wiiuse"=".\wiiuse.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.opt b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.opt
new file mode 100644
index 0000000..b6ebe4c
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/msvc/wiiuse.opt
Binary files differ
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.c
new file mode 100644
index 0000000..fd763bc
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.c
@@ -0,0 +1,210 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Nunchuk expansion device.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "events.h"
+#include "nunchuk.h"
+
+static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now);
+
+/**
+ * @brief Handle the handshake data from the nunchuk.
+ *
+ * @param nc A pointer to a nunchuk_t structure.
+ * @param data The data read in from the device.
+ * @param len The length of the data block, in bytes.
+ *
+ * @return Returns 1 if handshake was successful, 0 if not.
+ */
+int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len) {
+ int i;
+ int offset = 0;
+
+ nc->btns = 0;
+ nc->btns_held = 0;
+ nc->btns_released = 0;
+
+ /* set the smoothing to the same as the wiimote */
+ nc->flags = &wm->flags;
+ nc->accel_calib.st_alpha = wm->accel_calib.st_alpha;
+
+ /* decrypt data */
+ for (i = 0; i < len; ++i)
+ data[i] = (data[i] ^ 0x17) + 0x17;
+
+ if (data[offset] == 0xFF) {
+ /*
+ * Sometimes the data returned here is not correct.
+ * This might happen because the wiimote is lagging
+ * behind our initialization sequence.
+ * To fix this just request the handshake again.
+ *
+ * Other times it's just the first 16 bytes are 0xFF,
+ * but since the next 16 bytes are the same, just use
+ * those.
+ */
+ if (data[offset + 16] == 0xFF) {
+ /* get the calibration data */
+ byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+
+ WIIUSE_DEBUG("Nunchuk handshake appears invalid, trying again.");
+ wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+ return 0;
+ } else
+ offset += 16;
+ }
+
+ nc->accel_calib.cal_zero.x = data[offset + 0];
+ nc->accel_calib.cal_zero.y = data[offset + 1];
+ nc->accel_calib.cal_zero.z = data[offset + 2];
+ nc->accel_calib.cal_g.x = data[offset + 4];
+ nc->accel_calib.cal_g.y = data[offset + 5];
+ nc->accel_calib.cal_g.z = data[offset + 6];
+ nc->js.max.x = data[offset + 8];
+ nc->js.min.x = data[offset + 9];
+ nc->js.center.x = data[offset + 10];
+ nc->js.max.y = data[offset + 11];
+ nc->js.min.y = data[offset + 12];
+ nc->js.center.y = data[offset + 13];
+
+ /* default the thresholds to the same as the wiimote */
+ nc->orient_threshold = wm->orient_threshold;
+ nc->accel_threshold = wm->accel_threshold;
+
+ /* handshake done */
+ wm->exp.type = EXP_NUNCHUK;
+
+ #ifdef WIN32
+ wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
+ #endif
+
+ return 1;
+}
+
+
+/**
+ * @brief The nunchuk disconnected.
+ *
+ * @param nc A pointer to a nunchuk_t structure.
+ */
+void nunchuk_disconnected(struct nunchuk_t* nc) {
+ memset(nc, 0, sizeof(struct nunchuk_t));
+}
+
+
+
+/**
+ * @brief Handle nunchuk event.
+ *
+ * @param nc A pointer to a nunchuk_t structure.
+ * @param msg The message specified in the event packet.
+ */
+void nunchuk_event(struct nunchuk_t* nc, byte* msg) {
+ int i;
+
+ /* decrypt data */
+ for (i = 0; i < 6; ++i)
+ msg[i] = (msg[i] ^ 0x17) + 0x17;
+
+ /* get button states */
+ nunchuk_pressed_buttons(nc, msg[5]);
+
+ /* calculate joystick state */
+ calc_joystick_state(&nc->js, msg[0], msg[1]);
+
+ /* calculate orientation */
+ nc->accel.x = msg[2];
+ nc->accel.y = msg[3];
+ nc->accel.z = msg[4];
+
+ calculate_orientation(&nc->accel_calib, &nc->accel, &nc->orient, NUNCHUK_IS_FLAG_SET(nc, WIIUSE_SMOOTHING));
+ calculate_gforce(&nc->accel_calib, &nc->accel, &nc->gforce);
+}
+
+
+/**
+ * @brief Find what buttons are pressed.
+ *
+ * @param nc Pointer to a nunchuk_t structure.
+ * @param msg The message byte specified in the event packet.
+ */
+static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now) {
+ /* message is inverted (0 is active, 1 is inactive) */
+ now = ~now & NUNCHUK_BUTTON_ALL;
+
+ /* pressed now & were pressed, then held */
+ nc->btns_held = (now & nc->btns);
+
+ /* were pressed or were held & not pressed now, then released */
+ nc->btns_released = ((nc->btns | nc->btns_held) & ~now);
+
+ /* buttons pressed now */
+ nc->btns = now;
+}
+
+
+/**
+ * @brief Set the orientation event threshold for the nunchuk.
+ *
+ * @param wm Pointer to a wiimote_t structure with a nunchuk attached.
+ * @param threshold The decimal place that should be considered a significant change.
+ *
+ * See wiiuse_set_orient_threshold() for details.
+ */
+void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold) {
+ if (!wm) return;
+
+ wm->exp.nunchuk.orient_threshold = threshold;
+}
+
+
+/**
+ * @brief Set the accelerometer event threshold for the nunchuk.
+ *
+ * @param wm Pointer to a wiimote_t structure with a nunchuk attached.
+ * @param threshold The decimal place that should be considered a significant change.
+ *
+ * See wiiuse_set_orient_threshold() for details.
+ */
+void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold) {
+ if (!wm) return;
+
+ wm->exp.nunchuk.accel_threshold = threshold;
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.h
new file mode 100644
index 0000000..a3a2c63
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/nunchuk.h
@@ -0,0 +1,51 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief Nunchuk expansion device.
+ */
+
+#pragma once
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len);
+
+void nunchuk_disconnected(struct nunchuk_t* nc);
+
+void nunchuk_event(struct nunchuk_t* nc, byte* msg);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/os.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/os.h
new file mode 100644
index 0000000..3e99670
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/os.h
@@ -0,0 +1,53 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+
+/**
+ * @file
+ * @brief Operating system related definitions.
+ *
+ * This file is an attempt to separate operating system
+ * dependent functions and choose what should be used
+ * at compile time.
+ */
+
+#pragma once
+
+#ifdef WIN32
+ /* windows */
+ #define isnan(x) _isnan(x)
+ #define isinf(x) !_finite(x)
+
+ /* disable warnings I don't care about */
+ #pragma warning(disable:4244) /* possible loss of data conversion */
+ #pragma warning(disable:4273) /* inconsistent dll linkage */
+ #pragma warning(disable:4217)
+#else
+ /* nix */
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.c b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.c
new file mode 100644
index 0000000..1bb617d
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.c
@@ -0,0 +1,764 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief General wiimote operations.
+ *
+ * The file includes functions that handle general
+ * tasks. Most of these are functions that are part
+ * of the API.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef WIN32
+ #include <unistd.h>
+#else
+ #include <Winsock2.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "events.h"
+#include "io.h"
+
+static int g_banner = 0;
+
+/**
+ * @breif Returns the version of the library.
+ */
+const char* wiiuse_version() {
+ return WIIUSE_VERSION;
+}
+
+
+/**
+ * @brief Clean up wiimote_t array created by wiiuse_init()
+ */
+void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes) {
+ int i = 0;
+
+ if (!wm)
+ return;
+
+ WIIUSE_INFO("wiiuse clean up...");
+
+ for (; i < wiimotes; ++i) {
+ wiiuse_disconnect(wm[i]);
+ free(wm[i]);
+ }
+
+ free(wm);
+
+ return;
+}
+
+
+/**
+ * @brief Initialize an array of wiimote structures.
+ *
+ * @param wiimotes Number of wiimote_t structures to create.
+ *
+ * @return An array of initialized wiimote_t structures.
+ *
+ * @see wiiuse_connect()
+ *
+ * The array returned by this function can be passed to various
+ * functions, including wiiuse_connect().
+ */
+struct wiimote_t** wiiuse_init(int wiimotes) {
+ int i = 0;
+ struct wiimote_t** wm = NULL;
+
+ /*
+ * Please do not remove this banner.
+ * GPL asks that you please leave output credits intact.
+ * Thank you.
+ *
+ * This banner is only displayed once so that if you need
+ * to call this function again it won't be intrusive.
+ */
+ if (!g_banner) {
+ printf( "wiiuse v" WIIUSE_VERSION " loaded.\n"
+ " By: Michael Laforest <thepara[at]gmail{dot}com>\n"
+ " http://wiiuse.net http://wiiuse.sf.net\n");
+ g_banner = 1;
+ }
+
+ if (!wiimotes)
+ return NULL;
+
+ wm = malloc(sizeof(struct wiimote_t*) * wiimotes);
+
+ for (i = 0; i < wiimotes; ++i) {
+ wm[i] = malloc(sizeof(struct wiimote_t));
+ memset(wm[i], 0, sizeof(struct wiimote_t));
+
+ wm[i]->unid = i+1;
+
+ #ifndef WIN32
+ wm[i]->bdaddr = *BDADDR_ANY;
+ wm[i]->out_sock = -1;
+ wm[i]->in_sock = -1;
+ #else
+ wm[i]->dev_handle = 0;
+ wm[i]->stack = WIIUSE_STACK_UNKNOWN;
+ wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT;
+ wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT;
+ wm[i]->timeout = wm[i]->normal_timeout;
+ #endif
+
+ wm[i]->state = WIIMOTE_INIT_STATES;
+ wm[i]->flags = WIIUSE_INIT_FLAGS;
+
+ wm[i]->event = WIIUSE_NONE;
+
+ wm[i]->exp.type = EXP_NONE;
+
+ wiiuse_set_aspect_ratio(wm[i], WIIUSE_ASPECT_4_3);
+ wiiuse_set_ir_position(wm[i], WIIUSE_IR_ABOVE);
+
+ wm[i]->orient_threshold = 0.5f;
+ wm[i]->accel_threshold = 5;
+
+ wm[i]->accel_calib.st_alpha = WIIUSE_DEFAULT_SMOOTH_ALPHA;
+ }
+
+ return wm;
+}
+
+
+/**
+ * @brief The wiimote disconnected.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+void wiiuse_disconnected(struct wiimote_t* wm) {
+ if (!wm) return;
+
+ WIIUSE_INFO("Wiimote disconnected [id %i].", wm->unid);
+
+ /* disable the connected flag */
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
+
+ /* reset a bunch of stuff */
+ #ifndef WIN32
+ wm->out_sock = -1;
+ wm->in_sock = -1;
+ #else
+ wm->dev_handle = 0;
+ #endif
+
+ wm->leds = 0;
+ wm->state = WIIMOTE_INIT_STATES;
+ wm->read_req = NULL;
+ wm->handshake_state = 0;
+ wm->btns = 0;
+ wm->btns_held = 0;
+ wm->btns_released = 0;
+ memset(wm->event_buf, 0, sizeof(wm->event_buf));
+
+ wm->event = WIIUSE_DISCONNECT;
+}
+
+
+/**
+ * @brief Enable or disable the rumble.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param status 1 to enable, 0 to disable.
+ */
+void wiiuse_rumble(struct wiimote_t* wm, int status) {
+ byte buf;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return;
+
+ /* make sure to keep the current lit leds */
+ buf = wm->leds;
+
+ if (status) {
+ WIIUSE_DEBUG("Starting rumble...");
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
+ buf |= 0x01;
+ } else {
+ WIIUSE_DEBUG("Stopping rumble...");
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
+ }
+
+ /* preserve IR state */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
+ buf |= 0x04;
+
+ wiiuse_send(wm, WM_CMD_RUMBLE, &buf, 1);
+}
+
+
+/**
+ * @brief Toggle the state of the rumble.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+void wiiuse_toggle_rumble(struct wiimote_t* wm) {
+ if (!wm) return;
+
+ wiiuse_rumble(wm, !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE));
+}
+
+
+/**
+ * @brief Set the enabled LEDs.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param leds What LEDs to enable.
+ *
+ * \a leds is a bitwise or of WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, or WIIMOTE_LED_4.
+ */
+void wiiuse_set_leds(struct wiimote_t* wm, int leds) {
+ byte buf;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return;
+
+ /* remove the lower 4 bits because they control rumble */
+ wm->leds = (leds & 0xF0);
+
+ /* make sure if the rumble is on that we keep it on */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
+ wm->leds |= 0x01;
+
+ buf = wm->leds;
+
+ wiiuse_send(wm, WM_CMD_LED, &buf, 1);
+}
+
+
+/**
+ * @brief Set if the wiimote should report motion sensing.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param status 1 to enable, 0 to disable.
+ *
+ * Since reporting motion sensing sends a lot of data,
+ * the wiimote saves power by not transmitting it
+ * by default.
+ */
+void wiiuse_motion_sensing(struct wiimote_t* wm, int status) {
+ if (status)
+ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC);
+ else
+ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
+
+ wiiuse_set_report_type(wm);
+}
+
+
+/**
+ * @brief Set the report type based on the current wiimote state.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ *
+ * @return The report type sent.
+ *
+ * The wiimote reports formatted packets depending on the
+ * report type that was last requested. This function will
+ * update the type of report that should be sent based on
+ * the current state of the device.
+ */
+int wiiuse_set_report_type(struct wiimote_t* wm) {
+ byte buf[2];
+ int motion, exp, ir;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+
+ buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */
+ buf[1] = 0x00;
+
+ /* if rumble is enabled, make sure we keep it */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
+ buf[0] |= 0x01;
+
+ motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC);
+ exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
+ ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
+
+ if (motion && ir && exp) buf[1] = WM_RPT_BTN_ACC_IR_EXP;
+ else if (motion && exp) buf[1] = WM_RPT_BTN_ACC_EXP;
+ else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR;
+ else if (ir && exp) buf[1] = WM_RPT_BTN_IR_EXP;
+ else if (ir) buf[1] = WM_RPT_BTN_ACC_IR;
+ else if (exp) buf[1] = WM_RPT_BTN_EXP;
+ else if (motion) buf[1] = WM_RPT_BTN_ACC;
+ else buf[1] = WM_RPT_BTN;
+
+ WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);
+
+ exp = wiiuse_send(wm, WM_CMD_REPORT_TYPE, buf, 2);
+ if (exp <= 0)
+ return exp;
+
+ return buf[1];
+}
+
+
+/**
+ * @brief Read data from the wiimote (callback version).
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param read_cb Function pointer to call when the data arrives from the wiimote.
+ * @param buffer An allocated buffer to store the data as it arrives from the wiimote.
+ * Must be persistent in memory and large enough to hold the data.
+ * @param addr The address of wiimote memory to read from.
+ * @param len The length of the block to be read.
+ *
+ * The library can only handle one data read request at a time
+ * because it must keep track of the buffer and other
+ * events that are specific to that request. So if a request
+ * has already been made, subsequent requests will be added
+ * to a pending list and be sent out when the previous
+ * finishes.
+ */
+int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int addr, unsigned short len) {
+ struct read_req_t* req;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+ if (!buffer || !len || !read_cb)
+ return 0;
+
+ /* make this request structure */
+ req = (struct read_req_t*)malloc(sizeof(struct read_req_t));
+ req->cb = read_cb;
+ req->buf = buffer;
+ req->addr = addr;
+ req->size = len;
+ req->wait = len;
+ req->dirty = 0;
+ req->next = NULL;
+
+ /* add this to the request list */
+ if (!wm->read_req) {
+ /* root node */
+ wm->read_req = req;
+
+ WIIUSE_DEBUG("Data read request can be sent out immediately.");
+
+ /* send the request out immediately */
+ wiiuse_send_next_pending_read_request(wm);
+ } else {
+ struct read_req_t* nptr = wm->read_req;
+ for (; nptr->next; nptr = nptr->next);
+ nptr->next = req;
+
+ WIIUSE_DEBUG("Added pending data read request.");
+ }
+
+ return 1;
+}
+
+
+/**
+ * @brief Read data from the wiimote (event version).
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param buffer An allocated buffer to store the data as it arrives from the wiimote.
+ * Must be persistent in memory and large enough to hold the data.
+ * @param addr The address of wiimote memory to read from.
+ * @param len The length of the block to be read.
+ *
+ * The library can only handle one data read request at a time
+ * because it must keep track of the buffer and other
+ * events that are specific to that request. So if a request
+ * has already been made, subsequent requests will be added
+ * to a pending list and be sent out when the previous
+ * finishes.
+ */
+int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int addr, unsigned short len) {
+ struct read_req_t* req;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+ if (!buffer || !len)
+ return 0;
+
+ /* make this request structure */
+ req = (struct read_req_t*)malloc(sizeof(struct read_req_t));
+ req->cb = NULL;
+ req->buf = buffer;
+ req->addr = addr;
+ req->size = len;
+ req->wait = len;
+ req->dirty = 0;
+ req->next = NULL;
+
+ /* add this to the request list */
+ if (!wm->read_req) {
+ /* root node */
+ wm->read_req = req;
+
+ WIIUSE_DEBUG("Data read request can be sent out immediately.");
+
+ /* send the request out immediately */
+ wiiuse_send_next_pending_read_request(wm);
+ } else {
+ struct read_req_t* nptr = wm->read_req;
+ for (; nptr->next; nptr = nptr->next);
+ nptr->next = req;
+
+ WIIUSE_DEBUG("Added pending data read request.");
+ }
+
+ return 1;
+}
+
+
+/**
+ * @brief Send the next pending data read request to the wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ *
+ * @see wiiuse_read_data()
+ *
+ * This function is not part of the wiiuse API.
+ */
+void wiiuse_send_next_pending_read_request(struct wiimote_t* wm) {
+ byte buf[6];
+ struct read_req_t* req;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return;
+ if (!wm->read_req) return;
+
+ /* skip over dirty ones since they have already been read */
+ req = wm->read_req;
+ while (req && req->dirty)
+ req = req->next;
+ if (!req)
+ return;
+
+ /* the offset is in big endian */
+ *(int*)(buf) = BIG_ENDIAN_LONG(req->addr);
+
+ /* the length is in big endian */
+ *(short*)(buf + 4) = BIG_ENDIAN_SHORT(req->size);
+
+ WIIUSE_DEBUG("Request read at address: 0x%x length: %i", req->addr, req->size);
+ wiiuse_send(wm, WM_CMD_READ_DATA, buf, 6);
+}
+
+
+/**
+ * @brief Request the wiimote controller status.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ *
+ * Controller status includes: battery level, LED status, expansions
+ */
+void wiiuse_status(struct wiimote_t* wm) {
+ byte buf = 0;
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return;
+
+ WIIUSE_DEBUG("Requested wiimote status.");
+
+ wiiuse_send(wm, WM_CMD_CTRL_STATUS, &buf, 1);
+}
+
+
+/**
+ * @brief Find a wiimote_t structure by its unique identifier.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param wiimotes The number of wiimote_t structures in \a wm.
+ * @param unid The unique identifier to search for.
+ *
+ * @return Pointer to a wiimote_t structure, or NULL if not found.
+ */
+struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid) {
+ int i = 0;
+
+ for (; i < wiimotes; ++i) {
+ if (wm[i]->unid == unid)
+ return wm[i];
+ }
+
+ return NULL;
+}
+
+
+/**
+ * @brief Write data to the wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param addr The address to write to.
+ * @param data The data to be written to the memory location.
+ * @param len The length of the block to be written.
+ */
+int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len) {
+ byte buf[21] = {0}; /* the payload is always 23 */
+
+ if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+ return 0;
+ if (!data || !len)
+ return 0;
+
+ WIIUSE_DEBUG("Writing %i bytes to memory location 0x%x...", len, addr);
+
+ #ifdef WITH_WIIUSE_DEBUG
+ {
+ int i = 0;
+ printf("Write data is: ");
+ for (; i < len; ++i)
+ printf("%x ", data[i]);
+ printf("\n");
+ }
+ #endif
+
+ /* the offset is in big endian */
+ *(int*)(buf) = BIG_ENDIAN_LONG(addr);
+
+ /* length */
+ *(byte*)(buf + 4) = len;
+
+ /* data */
+ memcpy(buf + 5, data, len);
+
+ wiiuse_send(wm, WM_CMD_WRITE_DATA, buf, 21);
+ return 1;
+}
+
+
+/**
+ * @brief Send a packet to the wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param report_type The report type to send (WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc). Found in wiiuse.h
+ * @param msg The payload.
+ * @param len Length of the payload in bytes.
+ *
+ * This function should replace any write()s directly to the wiimote device.
+ */
+int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) {
+ byte buf[32]; /* no payload is better than this */
+ int rumble = 0;
+
+ #ifndef WIN32
+ buf[0] = WM_SET_REPORT | WM_BT_OUTPUT;
+ buf[1] = report_type;
+ #else
+ buf[0] = report_type;
+ #endif
+
+ switch (report_type) {
+ case WM_CMD_LED:
+ case WM_CMD_RUMBLE:
+ case WM_CMD_CTRL_STATUS:
+ {
+ /* Rumble flag for: 0x11, 0x13, 0x14, 0x15, 0x19 or 0x1a */
+ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
+ rumble = 1;
+ break;
+ }
+ default:
+ break;
+ }
+
+ #ifndef WIN32
+ memcpy(buf+2, msg, len);
+ if (rumble)
+ buf[2] |= 0x01;
+ #else
+ memcpy(buf+1, msg, len);
+ if (rumble)
+ buf[1] |= 0x01;
+ #endif
+
+ #ifdef WITH_WIIUSE_DEBUG
+ {
+ int x = 2;
+ printf("[DEBUG] (id %i) SEND: (%x) %.2x ", wm->unid, buf[0], buf[1]);
+ #ifndef WIN32
+ for (; x < len+2; ++x)
+ #else
+ for (; x < len+1; ++x)
+ #endif
+ printf("%.2x ", buf[x]);
+ printf("\n");
+ }
+ #endif
+
+ #ifndef WIN32
+ return wiiuse_io_write(wm, buf, len+2);
+ #else
+ return wiiuse_io_write(wm, buf, len+1);
+ #endif
+}
+
+
+/**
+ * @brief Set flags for the specified wiimote.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param enable Flags to enable.
+ * @param disable Flags to disable.
+ *
+ * @return The flags set after 'enable' and 'disable' have been applied.
+ *
+ * The values 'enable' and 'disable' may be any flags OR'ed together.
+ * Flags are defined in wiiuse.h.
+ */
+int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable) {
+ if (!wm) return 0;
+
+ /* remove mutually exclusive flags */
+ enable &= ~disable;
+ disable &= ~enable;
+
+ wm->flags |= enable;
+ wm->flags &= ~disable;
+
+ return wm->flags;
+}
+
+
+/**
+ * @brief Set the wiimote smoothing alpha value.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param alpha The alpha value to set. Between 0 and 1.
+ *
+ * @return Returns the old alpha value.
+ *
+ * The alpha value is between 0 and 1 and is used in an exponential
+ * smoothing algorithm.
+ *
+ * Smoothing is only performed if the WIIMOTE_USE_SMOOTHING is set.
+ */
+float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha) {
+ float old;
+
+ if (!wm) return 0.0f;
+
+ old = wm->accel_calib.st_alpha;
+
+ wm->accel_calib.st_alpha = alpha;
+
+ /* if there is a nunchuk set that too */
+ if (wm->exp.type == EXP_NUNCHUK)
+ wm->exp.nunchuk.accel_calib.st_alpha = alpha;
+
+ return old;
+}
+
+
+/**
+ * @brief Set the bluetooth stack type to use.
+ *
+ * @param wm Array of wiimote_t structures.
+ * @param wiimotes Number of objects in the wm array.
+ * @param type The type of bluetooth stack to use.
+ */
+void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type) {
+ #ifdef WIN32
+ int i;
+
+ if (!wm) return;
+
+ for (i = 0; i < wiimotes; ++i)
+ wm[i]->stack = type;
+ #endif
+}
+
+
+/**
+ * @brief Set the orientation event threshold.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param threshold The decimal place that should be considered a significant change.
+ *
+ * If threshold is 0.01, and any angle changes by 0.01 then a significant change
+ * has occurred and the event callback will be invoked. If threshold is 1 then
+ * the angle has to change by a full degree to generate an event.
+ */
+void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold) {
+ if (!wm) return;
+
+ wm->orient_threshold = threshold;
+}
+
+
+/**
+ * @brief Set the accelerometer event threshold.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param threshold The decimal place that should be considered a significant change.
+ */
+void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold) {
+ if (!wm) return;
+
+ wm->accel_threshold = threshold;
+}
+
+
+/**
+ * @brief Try to resync with the wiimote by starting a new handshake.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ */
+void wiiuse_resync(struct wiimote_t* wm) {
+ if (!wm) return;
+
+ wm->handshake_state = 0;
+ wiiuse_handshake(wm, NULL, 0);
+}
+
+
+/**
+ * @brief Set the normal and expansion handshake timeouts.
+ *
+ * @param wm Array of wiimote_t structures.
+ * @param wiimotes Number of objects in the wm array.
+ * @param normal_timeout The timeout in milliseconds for a normal read.
+ * @param exp_timeout The timeout in millisecondsd to wait for an expansion handshake.
+ */
+void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout) {
+ #ifdef WIN32
+ int i;
+
+ if (!wm) return;
+
+ for (i = 0; i < wiimotes; ++i) {
+ wm[i]->normal_timeout = normal_timeout;
+ wm[i]->exp_timeout = exp_timeout;
+ }
+ #endif
+}
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.h
new file mode 100644
index 0000000..fce263c
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse.h
@@ -0,0 +1,649 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ *
+ * @brief API header file.
+ *
+ * If this file is included from inside the wiiuse source
+ * and not from a third party program, then wiimote_internal.h
+ * is also included which extends this file.
+ */
+
+#pragma once
+
+#ifdef _WIN32
+ /* windows */
+ #include <windows.h>
+#else
+ /* nix */
+ #include <bluetooth/bluetooth.h>
+#endif
+
+#ifdef WIIUSE_INTERNAL_H_INCLUDED
+ #define WCONST
+#else
+ #define WCONST const
+#endif
+
+/* led bit masks */
+#define WIIMOTE_LED_NONE 0x00
+#define WIIMOTE_LED_1 0x10
+#define WIIMOTE_LED_2 0x20
+#define WIIMOTE_LED_3 0x40
+#define WIIMOTE_LED_4 0x80
+
+/* button codes */
+#define WIIMOTE_BUTTON_TWO 0x0001
+#define WIIMOTE_BUTTON_ONE 0x0002
+#define WIIMOTE_BUTTON_B 0x0004
+#define WIIMOTE_BUTTON_A 0x0008
+#define WIIMOTE_BUTTON_MINUS 0x0010
+#define WIIMOTE_BUTTON_ZACCEL_BIT6 0x0020
+#define WIIMOTE_BUTTON_ZACCEL_BIT7 0x0040
+#define WIIMOTE_BUTTON_HOME 0x0080
+#define WIIMOTE_BUTTON_LEFT 0x0100
+#define WIIMOTE_BUTTON_RIGHT 0x0200
+#define WIIMOTE_BUTTON_DOWN 0x0400
+#define WIIMOTE_BUTTON_UP 0x0800
+#define WIIMOTE_BUTTON_PLUS 0x1000
+#define WIIMOTE_BUTTON_ZACCEL_BIT4 0x2000
+#define WIIMOTE_BUTTON_ZACCEL_BIT5 0x4000
+#define WIIMOTE_BUTTON_UNKNOWN 0x8000
+#define WIIMOTE_BUTTON_ALL 0x1F9F
+
+/* nunchul button codes */
+#define NUNCHUK_BUTTON_Z 0x01
+#define NUNCHUK_BUTTON_C 0x02
+#define NUNCHUK_BUTTON_ALL 0x03
+
+/* classic controller button codes */
+#define CLASSIC_CTRL_BUTTON_UP 0x0001
+#define CLASSIC_CTRL_BUTTON_LEFT 0x0002
+#define CLASSIC_CTRL_BUTTON_ZR 0x0004
+#define CLASSIC_CTRL_BUTTON_X 0x0008
+#define CLASSIC_CTRL_BUTTON_A 0x0010
+#define CLASSIC_CTRL_BUTTON_Y 0x0020
+#define CLASSIC_CTRL_BUTTON_B 0x0040
+#define CLASSIC_CTRL_BUTTON_ZL 0x0080
+#define CLASSIC_CTRL_BUTTON_FULL_R 0x0200
+#define CLASSIC_CTRL_BUTTON_PLUS 0x0400
+#define CLASSIC_CTRL_BUTTON_HOME 0x0800
+#define CLASSIC_CTRL_BUTTON_MINUS 0x1000
+#define CLASSIC_CTRL_BUTTON_FULL_L 0x2000
+#define CLASSIC_CTRL_BUTTON_DOWN 0x4000
+#define CLASSIC_CTRL_BUTTON_RIGHT 0x8000
+#define CLASSIC_CTRL_BUTTON_ALL 0xFEFF
+
+/* guitar hero 3 button codes */
+#define GUITAR_HERO_3_BUTTON_STRUM_UP 0x0001
+#define GUITAR_HERO_3_BUTTON_YELLOW 0x0008
+#define GUITAR_HERO_3_BUTTON_GREEN 0x0010
+#define GUITAR_HERO_3_BUTTON_BLUE 0x0020
+#define GUITAR_HERO_3_BUTTON_RED 0x0040
+#define GUITAR_HERO_3_BUTTON_ORANGE 0x0080
+#define GUITAR_HERO_3_BUTTON_PLUS 0x0400
+#define GUITAR_HERO_3_BUTTON_MINUS 0x1000
+#define GUITAR_HERO_3_BUTTON_STRUM_DOWN 0x4000
+#define GUITAR_HERO_3_BUTTON_ALL 0xFEFF
+
+
+/* wiimote option flags */
+#define WIIUSE_SMOOTHING 0x01
+#define WIIUSE_CONTINUOUS 0x02
+#define WIIUSE_ORIENT_THRESH 0x04
+#define WIIUSE_INIT_FLAGS (WIIUSE_SMOOTHING | WIIUSE_ORIENT_THRESH)
+
+#define WIIUSE_ORIENT_PRECISION 100.0f
+
+/* expansion codes */
+#define EXP_NONE 0
+#define EXP_NUNCHUK 1
+#define EXP_CLASSIC 2
+#define EXP_GUITAR_HERO_3 3
+
+/* IR correction types */
+typedef enum ir_position_t {
+ WIIUSE_IR_ABOVE,
+ WIIUSE_IR_BELOW
+} ir_position_t;
+
+/**
+ * @brief Check if a button is pressed.
+ * @param dev Pointer to a wiimote_t or expansion structure.
+ * @param button The button you are interested in.
+ * @return 1 if the button is pressed, 0 if not.
+ */
+#define IS_PRESSED(dev, button) ((dev->btns & button) == button)
+
+/**
+ * @brief Check if a button is being held.
+ * @param dev Pointer to a wiimote_t or expansion structure.
+ * @param button The button you are interested in.
+ * @return 1 if the button is held, 0 if not.
+ */
+#define IS_HELD(dev, button) ((dev->btns_held & button) == button)
+
+/**
+ * @brief Check if a button is released on this event. \n\n
+ * This does not mean the button is not pressed, it means \n
+ * this button was just now released.
+ * @param dev Pointer to a wiimote_t or expansion structure.
+ * @param button The button you are interested in.
+ * @return 1 if the button is released, 0 if not.
+ *
+ */
+#define IS_RELEASED(dev, button) ((dev->btns_released & button) == button)
+
+/**
+ * @brief Check if a button has just been pressed this event.
+ * @param dev Pointer to a wiimote_t or expansion structure.
+ * @param button The button you are interested in.
+ * @return 1 if the button is pressed, 0 if not.
+ */
+#define IS_JUST_PRESSED(dev, button) (IS_PRESSED(dev, button) && !IS_HELD(dev, button))
+
+/**
+ * @brief Return the IR sensitivity level.
+ * @param wm Pointer to a wiimote_t structure.
+ * @param lvl [out] Pointer to an int that will hold the level setting.
+ * If no level is set 'lvl' will be set to 0.
+ */
+#define WIIUSE_GET_IR_SENSITIVITY(dev, lvl) \
+ do { \
+ if ((wm->state & 0x0200) == 0x0200) *lvl = 1; \
+ else if ((wm->state & 0x0400) == 0x0400) *lvl = 2; \
+ else if ((wm->state & 0x0800) == 0x0800) *lvl = 3; \
+ else if ((wm->state & 0x1000) == 0x1000) *lvl = 4; \
+ else if ((wm->state & 0x2000) == 0x2000) *lvl = 5; \
+ else *lvl = 0; \
+ } while (0)
+
+#define WIIUSE_USING_ACC(wm) ((wm->state & 0x020) == 0x020)
+#define WIIUSE_USING_EXP(wm) ((wm->state & 0x040) == 0x040)
+#define WIIUSE_USING_IR(wm) ((wm->state & 0x080) == 0x080)
+#define WIIUSE_USING_SPEAKER(wm) ((wm->state & 0x100) == 0x100)
+
+#define WIIUSE_IS_LED_SET(wm, num) ((wm->leds & WIIMOTE_LED_##num) == WIIMOTE_LED_##num)
+
+/*
+ * Largest known payload is 21 bytes.
+ * Add 2 for the prefix and round up to a power of 2.
+ */
+#define MAX_PAYLOAD 32
+
+/*
+ * This is left over from an old hack, but it may actually
+ * be a useful feature to keep so it wasn't removed.
+ */
+#ifdef WIN32
+ #define WIIMOTE_DEFAULT_TIMEOUT 10
+ #define WIIMOTE_EXP_TIMEOUT 10
+#endif
+
+typedef unsigned char byte;
+typedef char sbyte;
+
+struct wiimote_t;
+struct vec3b_t;
+struct orient_t;
+struct gforce_t;
+
+
+/**
+ * @brief Callback that handles a read event.
+ *
+ * @param wm Pointer to a wiimote_t structure.
+ * @param data Pointer to the filled data block.
+ * @param len Length in bytes of the data block.
+ *
+ * @see wiiuse_init()
+ *
+ * A registered function of this type is called automatically by the wiiuse
+ * library when the wiimote has returned the full data requested by a previous
+ * call to wiiuse_read_data().
+ */
+typedef void (*wiiuse_read_cb)(struct wiimote_t* wm, byte* data, unsigned short len);
+
+
+/**
+ * @struct read_req_t
+ * @brief Data read request structure.
+ */
+struct read_req_t {
+ wiiuse_read_cb cb; /**< read data callback */
+ byte* buf; /**< buffer where read data is written */
+ unsigned int addr; /**< the offset that the read started at */
+ unsigned short size; /**< the length of the data read */
+ unsigned short wait; /**< num bytes still needed to finish read */
+ byte dirty; /**< set to 1 if not using callback and needs to be cleaned up */
+
+ struct read_req_t* next; /**< next read request in the queue */
+};
+
+
+/**
+ * @struct vec2b_t
+ * @brief Unsigned x,y byte vector.
+ */
+typedef struct vec2b_t {
+ byte x, y;
+} vec2b_t;
+
+
+/**
+ * @struct vec3b_t
+ * @brief Unsigned x,y,z byte vector.
+ */
+typedef struct vec3b_t {
+ byte x, y, z;
+} vec3b_t;
+
+
+/**
+ * @struct vec3f_t
+ * @brief Signed x,y,z float struct.
+ */
+typedef struct vec3f_t {
+ float x, y, z;
+} vec3f_t;
+
+
+/**
+ * @struct orient_t
+ * @brief Orientation struct.
+ *
+ * Yaw, pitch, and roll range from -180 to 180 degrees.
+ */
+typedef struct orient_t {
+ float roll; /**< roll, this may be smoothed if enabled */
+ float pitch; /**< pitch, this may be smoothed if enabled */
+ float yaw;
+
+ float a_roll; /**< absolute roll, unsmoothed */
+ float a_pitch; /**< absolute pitch, unsmoothed */
+} orient_t;
+
+
+/**
+ * @struct gforce_t
+ * @brief Gravity force struct.
+ */
+typedef struct gforce_t {
+ float x, y, z;
+} gforce_t;
+
+
+/**
+ * @struct accel_t
+ * @brief Accelerometer struct. For any device with an accelerometer.
+ */
+typedef struct accel_t {
+ struct vec3b_t cal_zero; /**< zero calibration */
+ struct vec3b_t cal_g; /**< 1g difference around 0cal */
+
+ float st_roll; /**< last smoothed roll value */
+ float st_pitch; /**< last smoothed roll pitch */
+ float st_alpha; /**< alpha value for smoothing [0-1] */
+} accel_t;
+
+
+/**
+ * @struct ir_dot_t
+ * @brief A single IR source.
+ */
+typedef struct ir_dot_t {
+ byte visible; /**< if the IR source is visible */
+
+ unsigned int x; /**< interpolated X coordinate */
+ unsigned int y; /**< interpolated Y coordinate */
+
+ short rx; /**< raw X coordinate (0-1023) */
+ short ry; /**< raw Y coordinate (0-767) */
+
+ byte order; /**< increasing order by x-axis value */
+
+ byte size; /**< size of the IR dot (0-15) */
+} ir_dot_t;
+
+
+/**
+ * @enum aspect_t
+ * @brief Screen aspect ratio.
+ */
+typedef enum aspect_t {
+ WIIUSE_ASPECT_4_3,
+ WIIUSE_ASPECT_16_9
+} aspect_t;
+
+
+/**
+ * @struct ir_t
+ * @brief IR struct. Hold all data related to the IR tracking.
+ */
+typedef struct ir_t {
+ struct ir_dot_t dot[4]; /**< IR dots */
+ byte num_dots; /**< number of dots at this time */
+
+ enum aspect_t aspect; /**< aspect ratio of the screen */
+
+ enum ir_position_t pos; /**< IR sensor bar position */
+
+ unsigned int vres[2]; /**< IR virtual screen resolution */
+ int offset[2]; /**< IR XY correction offset */
+ int state; /**< keeps track of the IR state */
+
+ int ax; /**< absolute X coordinate */
+ int ay; /**< absolute Y coordinate */
+
+ int x; /**< calculated X coordinate */
+ int y; /**< calculated Y coordinate */
+
+ float distance; /**< pixel distance between first 2 dots*/
+ float z; /**< calculated distance */
+} ir_t;
+
+
+/**
+ * @struct joystick_t
+ * @brief Joystick calibration structure.
+ *
+ * The angle \a ang is relative to the positive y-axis into quadrant I
+ * and ranges from 0 to 360 degrees. So if the joystick is held straight
+ * upwards then angle is 0 degrees. If it is held to the right it is 90,
+ * down is 180, and left is 270.
+ *
+ * The magnitude \a mag is the distance from the center to where the
+ * joystick is being held. The magnitude ranges from 0 to 1.
+ * If the joystick is only slightly tilted from the center the magnitude
+ * will be low, but if it is closer to the outter edge the value will
+ * be higher.
+ */
+typedef struct joystick_t {
+ struct vec2b_t max; /**< maximum joystick values */
+ struct vec2b_t min; /**< minimum joystick values */
+ struct vec2b_t center; /**< center joystick values */
+
+ float ang; /**< angle the joystick is being held */
+ float mag; /**< magnitude of the joystick (range 0-1) */
+} joystick_t;
+
+
+/**
+ * @struct nunchuk_t
+ * @brief Nunchuk expansion device.
+ */
+typedef struct nunchuk_t {
+ struct accel_t accel_calib; /**< nunchuk accelerometer calibration */
+ struct joystick_t js; /**< joystick calibration */
+
+ int* flags; /**< options flag (points to wiimote_t.flags) */
+
+ byte btns; /**< what buttons have just been pressed */
+ byte btns_held; /**< what buttons are being held down */
+ byte btns_released; /**< what buttons were just released this */
+
+ float orient_threshold; /**< threshold for orient to generate an event */
+ int accel_threshold; /**< threshold for accel to generate an event */
+
+ struct vec3b_t accel; /**< current raw acceleration data */
+ struct orient_t orient; /**< current orientation on each axis */
+ struct gforce_t gforce; /**< current gravity forces on each axis */
+} nunchuk_t;
+
+
+/**
+ * @struct classic_ctrl_t
+ * @brief Classic controller expansion device.
+ */
+typedef struct classic_ctrl_t {
+ short btns; /**< what buttons have just been pressed */
+ short btns_held; /**< what buttons are being held down */
+ short btns_released; /**< what buttons were just released this */
+
+ float r_shoulder; /**< right shoulder button (range 0-1) */
+ float l_shoulder; /**< left shoulder button (range 0-1) */
+
+ struct joystick_t ljs; /**< left joystick calibration */
+ struct joystick_t rjs; /**< right joystick calibration */
+} classic_ctrl_t;
+
+
+/**
+ * @struct guitar_hero_3_t
+ * @brief Guitar Hero 3 expansion device.
+ */
+typedef struct guitar_hero_3_t {
+ short btns; /**< what buttons have just been pressed */
+ short btns_held; /**< what buttons are being held down */
+ short btns_released; /**< what buttons were just released this */
+
+ float whammy_bar; /**< whammy bar (range 0-1) */
+
+ struct joystick_t js; /**< joystick calibration */
+} guitar_hero_3_t;
+
+
+/**
+ * @struct expansion_t
+ * @brief Generic expansion device plugged into wiimote.
+ */
+typedef struct expansion_t {
+ int type; /**< type of expansion attached */
+
+ union {
+ struct nunchuk_t nunchuk;
+ struct classic_ctrl_t classic;
+ struct guitar_hero_3_t gh3;
+ };
+} expansion_t;
+
+
+/**
+ * @enum win32_bt_stack_t
+ * @brief Available bluetooth stacks for Windows.
+ */
+typedef enum win_bt_stack_t {
+ WIIUSE_STACK_UNKNOWN,
+ WIIUSE_STACK_MS,
+ WIIUSE_STACK_BLUESOLEIL
+} win_bt_stack_t;
+
+
+/**
+ * @struct wiimote_state_t
+ * @brief Significant data from the previous event.
+ */
+typedef struct wiimote_state_t {
+ /* expansion_t */
+ float exp_ljs_ang;
+ float exp_rjs_ang;
+ float exp_ljs_mag;
+ float exp_rjs_mag;
+ unsigned short exp_btns;
+ struct orient_t exp_orient;
+ struct vec3b_t exp_accel;
+ float exp_r_shoulder;
+ float exp_l_shoulder;
+
+ /* ir_t */
+ int ir_ax;
+ int ir_ay;
+ float ir_distance;
+
+ struct orient_t orient;
+ unsigned short btns;
+
+ struct vec3b_t accel;
+} wiimote_state_t;
+
+
+/**
+ * @enum WIIUSE_EVENT_TYPE
+ * @brief Events that wiiuse can generate from a poll.
+ */
+typedef enum WIIUSE_EVENT_TYPE {
+ WIIUSE_NONE = 0,
+ WIIUSE_EVENT,
+ WIIUSE_STATUS,
+ WIIUSE_CONNECT,
+ WIIUSE_DISCONNECT,
+ WIIUSE_UNEXPECTED_DISCONNECT,
+ WIIUSE_READ_DATA,
+ WIIUSE_NUNCHUK_INSERTED,
+ WIIUSE_NUNCHUK_REMOVED,
+ WIIUSE_CLASSIC_CTRL_INSERTED,
+ WIIUSE_CLASSIC_CTRL_REMOVED,
+ WIIUSE_GUITAR_HERO_3_CTRL_INSERTED,
+ WIIUSE_GUITAR_HERO_3_CTRL_REMOVED
+} WIIUSE_EVENT_TYPE;
+
+/**
+ * @struct wiimote_t
+ * @brief Wiimote structure.
+ */
+typedef struct wiimote_t {
+ WCONST int unid; /**< user specified id */
+
+ #ifndef WIN32
+ WCONST bdaddr_t bdaddr; /**< bt address */
+ WCONST char bdaddr_str[18]; /**< readable bt address */
+ WCONST int out_sock; /**< output socket */
+ WCONST int in_sock; /**< input socket */
+ #else
+ WCONST HANDLE dev_handle; /**< HID handle */
+ WCONST OVERLAPPED hid_overlap; /**< overlap handle */
+ WCONST enum win_bt_stack_t stack; /**< type of bluetooth stack to use */
+ WCONST int timeout; /**< read timeout */
+ WCONST byte normal_timeout; /**< normal timeout */
+ WCONST byte exp_timeout; /**< timeout for expansion handshake */
+ #endif
+
+ WCONST int state; /**< various state flags */
+ WCONST byte leds; /**< currently lit leds */
+ WCONST float battery_level; /**< battery level */
+
+ WCONST int flags; /**< options flag */
+
+ WCONST byte handshake_state; /**< the state of the connection handshake */
+
+ WCONST struct read_req_t* read_req; /**< list of data read requests */
+ WCONST struct accel_t accel_calib; /**< wiimote accelerometer calibration */
+ WCONST struct expansion_t exp; /**< wiimote expansion device */
+
+ WCONST struct vec3b_t accel; /**< current raw acceleration data */
+ WCONST struct orient_t orient; /**< current orientation on each axis */
+ WCONST struct gforce_t gforce; /**< current gravity forces on each axis */
+
+ WCONST struct ir_t ir; /**< IR data */
+
+ WCONST unsigned short btns; /**< what buttons have just been pressed */
+ WCONST unsigned short btns_held; /**< what buttons are being held down */
+ WCONST unsigned short btns_released; /**< what buttons were just released this */
+
+ WCONST float orient_threshold; /**< threshold for orient to generate an event */
+ WCONST int accel_threshold; /**< threshold for accel to generate an event */
+
+ WCONST struct wiimote_state_t lstate; /**< last saved state */
+
+ WCONST WIIUSE_EVENT_TYPE event; /**< type of event that occurred */
+ WCONST byte event_buf[MAX_PAYLOAD]; /**< event buffer */
+} wiimote;
+
+
+/*****************************************
+ *
+ * Include API specific stuff
+ *
+ *****************************************/
+
+#ifdef _WIN32
+ #define WIIUSE_EXPORT_DECL __declspec(dllexport)
+ #define WIIUSE_IMPORT_DECL __declspec(dllimport)
+#else
+ #define WIIUSE_EXPORT_DECL
+ #define WIIUSE_IMPORT_DECL
+#endif
+
+#ifdef WIIUSE_COMPILE_LIB
+ #define WIIUSE_EXPORT WIIUSE_EXPORT_DECL
+#else
+ #define WIIUSE_EXPORT WIIUSE_IMPORT_DECL
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* wiiuse.c */
+WIIUSE_EXPORT extern const char* wiiuse_version();
+
+WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes);
+WIIUSE_EXPORT extern void wiiuse_disconnected(struct wiimote_t* wm);
+WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes);
+WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status);
+WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm);
+WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds);
+WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status);
+WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, unsigned short len);
+WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len);
+WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t* wm);
+WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid);
+WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable);
+WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha);
+WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type);
+WIIUSE_EXPORT extern void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold);
+WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm);
+WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout);
+WIIUSE_EXPORT extern void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold);
+
+/* connect.c */
+WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout);
+WIIUSE_EXPORT extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes);
+WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm);
+
+/* events.c */
+WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes);
+
+/* ir.c */
+WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status);
+WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y);
+WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos);
+WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect);
+WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level);
+
+/* nunchuk.c */
+WIIUSE_EXPORT extern void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold);
+WIIUSE_EXPORT extern void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold);
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse_internal.h b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse_internal.h
new file mode 100644
index 0000000..de5c011
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/src/wiiuse_internal.h
@@ -0,0 +1,224 @@
+/*
+ * wiiuse
+ *
+ * Written By:
+ * Michael Laforest < para >
+ * Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ * Copyright 2006-2007
+ *
+ * This file is part of wiiuse.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Header$
+ *
+ */
+
+/**
+ * @file
+ * @brief General internal wiiuse stuff.
+ *
+ * Since Wiiuse is a library, wiiuse.h is a duplicate
+ * of the API header.
+ *
+ * The code that would normally go in that file, but
+ * which is not needed by third party developers,
+ * is put here.
+ *
+ * So wiiuse_internal.h is included by other files
+ * internally, wiiuse.h is included only here.
+ */
+
+#pragma once
+
+#ifndef WIN32
+ #include <arpa/inet.h> /* htons() */
+ #include <bluetooth/bluetooth.h>
+#endif
+
+#include "definitions.h"
+
+/* wiiuse version */
+#define WIIUSE_VERSION "0.12"
+
+/********************
+ *
+ * Wiimote internal codes
+ *
+ ********************/
+
+/* Communication channels */
+#define WM_OUTPUT_CHANNEL 0x11
+#define WM_INPUT_CHANNEL 0x13
+
+#define WM_SET_REPORT 0x50
+
+/* commands */
+#define WM_CMD_LED 0x11
+#define WM_CMD_REPORT_TYPE 0x12
+#define WM_CMD_RUMBLE 0x13
+#define WM_CMD_IR 0x13
+#define WM_CMD_CTRL_STATUS 0x15
+#define WM_CMD_WRITE_DATA 0x16
+#define WM_CMD_READ_DATA 0x17
+#define WM_CMD_IR_2 0x1A
+
+/* input report ids */
+#define WM_RPT_CTRL_STATUS 0x20
+#define WM_RPT_READ 0x21
+#define WM_RPT_WRITE 0x22
+#define WM_RPT_BTN 0x30
+#define WM_RPT_BTN_ACC 0x31
+#define WM_RPT_BTN_ACC_IR 0x33
+#define WM_RPT_BTN_EXP 0x34
+#define WM_RPT_BTN_ACC_EXP 0x35
+#define WM_RPT_BTN_IR_EXP 0x36
+#define WM_RPT_BTN_ACC_IR_EXP 0x37
+
+#define WM_BT_INPUT 0x01
+#define WM_BT_OUTPUT 0x02
+
+/* Identify the wiimote device by its class */
+#define WM_DEV_CLASS_0 0x04
+#define WM_DEV_CLASS_1 0x25
+#define WM_DEV_CLASS_2 0x00
+#define WM_VENDOR_ID 0x057E
+#define WM_PRODUCT_ID 0x0306
+
+/* controller status stuff */
+#define WM_MAX_BATTERY_CODE 0xC8
+
+/* offsets in wiimote memory */
+#define WM_MEM_OFFSET_CALIBRATION 0x16
+#define WM_EXP_MEM_BASE 0x04A40000
+#define WM_EXP_MEM_ENABLE 0x04A40040
+#define WM_EXP_MEM_CALIBR 0x04A40020
+
+#define WM_REG_IR 0x04B00030
+#define WM_REG_IR_BLOCK1 0x04B00000
+#define WM_REG_IR_BLOCK2 0x04B0001A
+#define WM_REG_IR_MODENUM 0x04B00033
+
+/* ir block data */
+#define WM_IR_BLOCK1_LEVEL1 "\x02\x00\x00\x71\x01\x00\x64\x00\xfe"
+#define WM_IR_BLOCK2_LEVEL1 "\xfd\x05"
+#define WM_IR_BLOCK1_LEVEL2 "\x02\x00\x00\x71\x01\x00\x96\x00\xb4"
+#define WM_IR_BLOCK2_LEVEL2 "\xb3\x04"
+#define WM_IR_BLOCK1_LEVEL3 "\x02\x00\x00\x71\x01\x00\xaa\x00\x64"
+#define WM_IR_BLOCK2_LEVEL3 "\x63\x03"
+#define WM_IR_BLOCK1_LEVEL4 "\x02\x00\x00\x71\x01\x00\xc8\x00\x36"
+#define WM_IR_BLOCK2_LEVEL4 "\x35\x03"
+#define WM_IR_BLOCK1_LEVEL5 "\x07\x00\x00\x71\x01\x00\x72\x00\x20"
+#define WM_IR_BLOCK2_LEVEL5 "\x1f\x03"
+
+#define WM_IR_TYPE_BASIC 0x01
+#define WM_IR_TYPE_EXTENDED 0x03
+
+/* controller status flags for the first message byte */
+/* bit 1 is unknown */
+#define WM_CTRL_STATUS_BYTE1_ATTACHMENT 0x02
+#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED 0x04
+#define WM_CTRL_STATUS_BYTE1_IR_ENABLED 0x08
+#define WM_CTRL_STATUS_BYTE1_LED_1 0x10
+#define WM_CTRL_STATUS_BYTE1_LED_2 0x20
+#define WM_CTRL_STATUS_BYTE1_LED_3 0x40
+#define WM_CTRL_STATUS_BYTE1_LED_4 0x80
+
+/* aspect ratio */
+#define WM_ASPECT_16_9_X 660
+#define WM_ASPECT_16_9_Y 370
+#define WM_ASPECT_4_3_X 560
+#define WM_ASPECT_4_3_Y 420
+
+
+/**
+ * Expansion stuff
+ */
+
+/* encrypted expansion id codes (located at 0x04A400FC) */
+#define EXP_ID_CODE_NUNCHUK 0x9A1EFEFE
+#define EXP_ID_CODE_CLASSIC_CONTROLLER 0x9A1EFDFD
+#define EXP_ID_CODE_GUITAR 0x9A1EFDFB
+
+#define EXP_HANDSHAKE_LEN 224
+
+/********************
+ *
+ * End Wiimote internal codes
+ *
+ ********************/
+
+/* wiimote state flags - (some duplicated in wiiuse.h)*/
+#define WIIMOTE_STATE_DEV_FOUND 0x0001
+#define WIIMOTE_STATE_HANDSHAKE 0x0002 /* actual connection exists but no handshake yet */
+#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x0004 /* actual connection exists but no handshake yet */
+#define WIIMOTE_STATE_CONNECTED 0x0008
+#define WIIMOTE_STATE_RUMBLE 0x0010
+#define WIIMOTE_STATE_ACC 0x0020
+#define WIIMOTE_STATE_EXP 0x0040
+#define WIIMOTE_STATE_IR 0x0080
+#define WIIMOTE_STATE_SPEAKER 0x0100
+#define WIIMOTE_STATE_IR_SENS_LVL1 0x0200
+#define WIIMOTE_STATE_IR_SENS_LVL2 0x0400
+#define WIIMOTE_STATE_IR_SENS_LVL3 0x0800
+#define WIIMOTE_STATE_IR_SENS_LVL4 0x1000
+#define WIIMOTE_STATE_IR_SENS_LVL5 0x2000
+
+#define WIIMOTE_INIT_STATES (WIIMOTE_STATE_IR_SENS_LVL3)
+
+/* macro to manage states */
+#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s))
+#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s))
+#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s))
+#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s))
+
+#define WIIMOTE_IS_FLAG_SET(wm, s) ((wm->flags & (s)) == (s))
+#define WIIMOTE_ENABLE_FLAG(wm, s) (wm->flags |= (s))
+#define WIIMOTE_DISABLE_FLAG(wm, s) (wm->flags &= ~(s))
+#define WIIMOTE_TOGGLE_FLAG(wm, s) ((wm->flags & (s)) ? WIIMOTE_DISABLE_FLAG(wm, s) : WIIMOTE_ENABLE_FLAG(wm, s))
+
+#define NUNCHUK_IS_FLAG_SET(wm, s) ((*(wm->flags) & (s)) == (s))
+
+/* misc macros */
+#define WIIMOTE_ID(wm) (wm->unid)
+#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED))
+
+/*
+ * Smooth tilt calculations are computed with the
+ * exponential moving average formula:
+ * St = St_last + (alpha * (tilt - St_last))
+ * alpha is between 0 and 1
+ */
+#define WIIUSE_DEFAULT_SMOOTH_ALPHA 0.07f
+
+#define SMOOTH_ROLL 0x01
+#define SMOOTH_PITCH 0x02
+
+#include "wiiuse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* not part of the api */
+int wiiuse_set_report_type(struct wiimote_t* wm);
+void wiiuse_send_next_pending_read_request(struct wiimote_t* wm);
+int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len);
+int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int offset, unsigned short len);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.cbp b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.cbp
new file mode 100644
index 0000000..a71d3a0
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.cbp
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="wiiuse" />
+ <Option makefile_is_custom="1" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <MakeCommands>
+ <Build command="$make $target" />
+ <CompileFile command="$make $file" />
+ <Clean command="$make clean" />
+ <DistClean command="$make distclean" />
+ </MakeCommands>
+ <Build>
+ <Target title="Release">
+ <Option output="bin/Release/wiiuse" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj/Release/" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Compiler>
+ <Add option="-O2" />
+ </Compiler>
+ <Linker>
+ <Add option="-s" />
+ </Linker>
+ </Target>
+ </Build>
+ <Compiler>
+ <Add option="-Wall" />
+ </Compiler>
+ <Unit filename="CHANGELOG" />
+ <Unit filename="README" />
+ <Unit filename="example-sdl/sdl.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="example/example.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/classic.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/classic.h" />
+ <Unit filename="src/definitions.h" />
+ <Unit filename="src/dynamics.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/dynamics.h" />
+ <Unit filename="src/events.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/events.h" />
+ <Unit filename="src/guitar_hero_3.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/guitar_hero_3.h" />
+ <Unit filename="src/io.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/io.h" />
+ <Unit filename="src/io_nix.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/io_win.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/ir.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/ir.h" />
+ <Unit filename="src/nunchuk.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/nunchuk.h" />
+ <Unit filename="src/os.h" />
+ <Unit filename="src/wiiuse.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="src/wiiuse.h" />
+ <Unit filename="src/wiiuse_internal.h" />
+ <Extensions>
+ <code_completion />
+ <debugger />
+ </Extensions>
+ </Project>
+</CodeBlocks_project_file>
diff --git a/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.layout b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.layout
new file mode 100644
index 0000000..5b74afe
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/wiiuse_v0.12/wiiuse.layout
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <ActiveTarget name="Release" />
+ <File name="CHANGELOG" open="1" top="0" tabpos="7">
+ <Cursor position="0" topLine="0" />
+ </File>
+ <File name="README" open="0" top="0" tabpos="8">
+ <Cursor position="3582" topLine="0" />
+ </File>
+ <File name="example-sdl/sdl.c" open="1" top="0" tabpos="6">
+ <Cursor position="3235" topLine="105" />
+ </File>
+ <File name="example/example.c" open="1" top="0" tabpos="5">
+ <Cursor position="0" topLine="0" />
+ </File>
+ <File name="src/classic.c" open="0" top="0" tabpos="4">
+ <Cursor position="2464" topLine="53" />
+ </File>
+ <File name="src/definitions.h" open="1" top="0" tabpos="9">
+ <Cursor position="1099" topLine="12" />
+ </File>
+ <File name="src/dynamics.c" open="0" top="0" tabpos="10">
+ <Cursor position="3216" topLine="59" />
+ </File>
+ <File name="src/events.c" open="1" top="0" tabpos="4">
+ <Cursor position="2983" topLine="117" />
+ </File>
+ <File name="src/guitar_hero_3.c" open="0" top="0" tabpos="0">
+ <Cursor position="2604" topLine="45" />
+ </File>
+ <File name="src/io.c" open="0" top="0" tabpos="6">
+ <Cursor position="1817" topLine="60" />
+ </File>
+ <File name="src/io_nix.c" open="0" top="0" tabpos="8">
+ <Cursor position="6286" topLine="211" />
+ </File>
+ <File name="src/io_win.c" open="0" top="0" tabpos="9">
+ <Cursor position="4021" topLine="123" />
+ </File>
+ <File name="src/ir.c" open="1" top="0" tabpos="8">
+ <Cursor position="0" topLine="0" />
+ </File>
+ <File name="src/ir.h" open="0" top="0" tabpos="0">
+ <Cursor position="1059" topLine="0" />
+ </File>
+ <File name="src/nunchuk.c" open="0" top="0" tabpos="10">
+ <Cursor position="2454" topLine="43" />
+ </File>
+ <File name="src/nunchuk.h" open="0" top="0" tabpos="0">
+ <Cursor position="1171" topLine="0" />
+ </File>
+ <File name="src/wiiuse.c" open="1" top="0" tabpos="1">
+ <Cursor position="0" topLine="0" />
+ </File>
+ <File name="src/wiiuse.h" open="1" top="1" tabpos="2">
+ <Cursor position="0" topLine="0" />
+ </File>
+ <File name="src/wiiuse_internal.h" open="1" top="0" tabpos="3">
+ <Cursor position="3424" topLine="81" />
+ </File>
+</CodeBlocks_layout_file>
diff --git a/tools/EventClients/Clients/Xbox360Controller/Xbox360Controller.cpp b/tools/EventClients/Clients/Xbox360Controller/Xbox360Controller.cpp
new file mode 100644
index 0000000..caf2870
--- /dev/null
+++ b/tools/EventClients/Clients/Xbox360Controller/Xbox360Controller.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2009-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "StdAfx.h"
+#include "Xbox360Controller.h"
+
+
+Xbox360Controller::Xbox360Controller(int num)
+{
+ this->num = num;
+ for (int i = 0; i < 14; i++)
+ {
+ button_down[i] = false;
+ button_released[i] = false;
+ button_pressed[i] = false;
+ }
+}
+
+XINPUT_STATE Xbox360Controller::getState()
+{
+ // Zeroise the state
+ ZeroMemory(&state, sizeof(XINPUT_STATE));
+
+ // Get the state
+ XInputGetState(num, &state);
+
+ return state;
+}
+
+void Xbox360Controller::updateButton(int num, int button)
+{
+ if (state.Gamepad.wButtons & button)
+ {
+ if (!button_down[num])
+ {
+ button_pressed[num] = true;
+ }
+ button_down[num] = true;
+ } else
+ {
+ if (button_down[num])
+ {
+ button_released[num] = true;
+ }
+ button_down[num] = false;
+ }
+}
+
+bool Xbox360Controller::buttonPressed(int num)
+{
+ return button_pressed[num];
+}
+
+bool Xbox360Controller::buttonReleased(int num)
+{
+ return button_released[num];
+}
+
+void Xbox360Controller::updateState()
+{
+ for (int i = 0; i < 14; i++)
+ {
+ button_released[i] = false;
+ button_pressed[i] = false;
+ }
+ if (isConnected())
+ {
+ XINPUT_STATE s = getState();
+ updateButton(0, XINPUT_GAMEPAD_A);
+ updateButton(1, XINPUT_GAMEPAD_B);
+ updateButton(2, XINPUT_GAMEPAD_X);
+ updateButton(3, XINPUT_GAMEPAD_Y);
+ updateButton(4, XINPUT_GAMEPAD_DPAD_UP);
+ updateButton(5, XINPUT_GAMEPAD_DPAD_DOWN);
+ updateButton(6, XINPUT_GAMEPAD_DPAD_LEFT);
+ updateButton(7, XINPUT_GAMEPAD_DPAD_RIGHT);
+ updateButton(8, XINPUT_GAMEPAD_START);
+ updateButton(9, XINPUT_GAMEPAD_BACK);
+ updateButton(10, XINPUT_GAMEPAD_LEFT_THUMB);
+ updateButton(11, XINPUT_GAMEPAD_RIGHT_THUMB);
+ updateButton(12, XINPUT_GAMEPAD_LEFT_SHOULDER);
+ updateButton(13, XINPUT_GAMEPAD_RIGHT_SHOULDER);
+ }
+}
+
+bool Xbox360Controller::isConnected()
+{
+ // Zeroise the state
+ ZeroMemory(&state, sizeof(XINPUT_STATE));
+
+ // Get the state
+ DWORD Result = XInputGetState(num, &state);
+
+ if(Result == ERROR_SUCCESS)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+bool Xbox360Controller::triggerMoved(int num)
+{
+ if (num == 0)
+ return (state.Gamepad.bRightTrigger &&
+ state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD);
+ return (state.Gamepad.bLeftTrigger &&
+ state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD);
+}
+
+BYTE Xbox360Controller::getTrigger(int num)
+{
+ if (num == 0)
+ return state.Gamepad.bRightTrigger;
+ return state.Gamepad.bLeftTrigger;
+}
+
+bool Xbox360Controller::thumbMoved(int num)
+{
+ switch(num)
+ {
+ case 0:
+ return !(state.Gamepad.sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
+ state.Gamepad.sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
+ case 1:
+ return !(state.Gamepad.sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
+ state.Gamepad.sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
+ case 2:
+ return !(state.Gamepad.sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
+ state.Gamepad.sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
+ case 3:
+ return !(state.Gamepad.sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
+ state.Gamepad.sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
+ }
+
+ return false;
+}
+SHORT Xbox360Controller::getThumb(int num)
+{
+ switch (num)
+ {
+ case 0:
+ return state.Gamepad.sThumbLX;
+ case 1:
+ return state.Gamepad.sThumbLY;
+ case 2:
+ return state.Gamepad.sThumbRX;
+ case 3:
+ return state.Gamepad.sThumbRY;
+ }
+
+ return 0;
+}
+
diff --git a/tools/EventClients/Clients/Xbox360Controller/Xbox360Controller.h b/tools/EventClients/Clients/Xbox360Controller/Xbox360Controller.h
new file mode 100644
index 0000000..d7a9e2a
--- /dev/null
+++ b/tools/EventClients/Clients/Xbox360Controller/Xbox360Controller.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <windows.h>
+#include <XInput.h> // Defines XBOX controller API
+#pragma comment(lib, "XInput.lib") // Library containing necessary 360
+ // functions
+
+class Xbox360Controller
+{
+private:
+ XINPUT_STATE state;
+ int num;
+ bool button_down[14];
+ bool button_pressed[14];
+ bool button_released[14];
+
+ XINPUT_STATE getState();
+ void updateButton(int num, int button);
+public:
+ Xbox360Controller(int num);
+ void updateState();
+ bool isConnected();
+ bool buttonPressed(int num);
+ bool buttonReleased(int num);
+ bool thumbMoved(int num);
+ SHORT getThumb(int num);
+ bool triggerMoved(int num);
+ BYTE getTrigger(int num);
+};
diff --git a/tools/EventClients/Clients/Xbox360Controller/Xbox360EventClient.cpp b/tools/EventClients/Clients/Xbox360Controller/Xbox360EventClient.cpp
new file mode 100644
index 0000000..106befb
--- /dev/null
+++ b/tools/EventClients/Clients/Xbox360Controller/Xbox360EventClient.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2009-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+// Xbox360EventClient.cpp : Defines the entry point for the console application.
+//
+
+#include "stdafx.h"
+#include "Xbox360Controller.h"
+#include "../../lib/c++/xbmcclient.h"
+#pragma comment(lib, "wsock32.lib") // needed for xbmclient.h?
+
+// You can have up to 4 xbox360 controllers on a system
+#define MAX_NUM_CONTROLLERS 4
+
+// global variable :(
+// needed for exit event handler
+CXBMCClient *client;
+
+BOOL exitHandler( DWORD ctrlType )
+{
+ // TODO: Send BYE Packet
+ delete client;
+
+ WSACleanup();
+
+ return FALSE;
+}
+
+void checkTrigger(Xbox360Controller &cont, CXBMCClient *client, int num, const char* name)
+{
+ if (cont.triggerMoved(num))
+ {
+ client->SendButton(name, "XG", 0x20, cont.getTrigger(num) * 128);
+ }
+}
+
+void checkThumb(Xbox360Controller &cont, CXBMCClient *client, int num,
+ const char* leftname, const char* rightname)
+{
+ if (cont.thumbMoved(num))
+ {
+ if (cont.getThumb(num) < 0)
+ {
+ client->SendButton(leftname, "XG", 0x20, -cont.getThumb(num));
+ }
+ else
+ {
+ client->SendButton(rightname, "XG", 0x20, cont.getThumb(num));
+ }
+ }
+}
+
+void checkButton(Xbox360Controller &cont, CXBMCClient *client, int num, const char* name)
+{
+ if (cont.buttonPressed(num))
+ {
+ client->SendButton(name, "XG", 0x02);
+ }
+ else if (cont.buttonReleased(num))
+ {
+ client->SendButton(name, "XG", 0x04);
+ }
+}
+
+void checkAll(Xbox360Controller &cont)
+{
+ if (cont.isConnected())
+ {
+ cont.updateState();
+ checkButton(cont, client, 0, "a");
+ checkButton(cont, client, 1, "b");
+ checkButton(cont, client, 2, "x");
+ checkButton(cont, client, 3, "y");
+ checkButton(cont, client, 4, "dpadup");
+ checkButton(cont, client, 5, "dpaddown");
+ checkButton(cont, client, 6, "dpadleft");
+ checkButton(cont, client, 7, "dpadright");
+ checkButton(cont, client, 8, "start");
+ checkButton(cont, client, 9, "back");
+ checkButton(cont, client, 10, "leftthumbbutton");
+ checkButton(cont, client, 11, "rightthumbbutton");
+ checkButton(cont, client, 12, "white");
+ checkButton(cont, client, 13, "black");
+ checkTrigger(cont, client, 0, "rightanalogtrigger");
+ checkTrigger(cont, client, 1, "leftanalogtrigger");
+ checkThumb(cont, client, 0, "leftthumbstickleft", "leftthumbstickright");
+ checkThumb(cont, client, 1, "leftthumbstickdown", "leftthumbstickup");
+ checkThumb(cont, client, 2, "rightthumbstickleft", "rightthumbstickright");
+ checkThumb(cont, client, 3, "rightthumbstickdown", "rightthumbstickup");
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ char *host = "localhost";
+ char *port = "9777";
+ Xbox360Controller *controllers[MAX_NUM_CONTROLLERS];
+ int i;
+
+ // Get access to all potential controllers
+ for ( i = 0; i < MAX_NUM_CONTROLLERS; i++)
+ {
+ controllers[i] = new Xbox360Controller(i);
+ }
+
+ // Start Winsock stuff
+ WSADATA wsaData;
+ WSAStartup(MAKEWORD(2, 2), &wsaData);
+
+ if ( argc > 3 )
+ {
+ printf("USAGE: %s [HOST [PORT]]\n\nThe event client connects to the XBMC EventServer at HOST:PORT.\
+ Default value for HOST is localhost, default value for port is 9777.\n", argv[0]);
+ return -1;
+ }
+
+ if ( argc > 1 )
+ {
+ host = argv[1];
+ }
+
+ if ( argc > 2 )
+ {
+ port = argv[2];
+ }
+
+ client = new CXBMCClient(host, atoi(port));
+
+ SetConsoleCtrlHandler( (PHANDLER_ROUTINE) exitHandler, TRUE);
+
+ client->SendHELO("Xbox 360 Controller", 0);
+
+ while(true)
+ {
+ // Check each controller for activity
+ for ( i = 0; i < MAX_NUM_CONTROLLERS; i++ )
+ {
+ checkAll(*controllers[i]);
+ }
+ Sleep(10);
+ }
+
+ return 0;
+}
diff --git a/tools/EventClients/Clients/Xbox360Controller/Xbox360EventClient.vcproj b/tools/EventClients/Clients/Xbox360Controller/Xbox360EventClient.vcproj
new file mode 100644
index 0000000..3a5a8b6
--- /dev/null
+++ b/tools/EventClients/Clients/Xbox360Controller/Xbox360EventClient.vcproj
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="Xbox360EventClient"
+ ProjectGUID="{19E7A234-4F29-4828-BBC7-E3564AB57EF0}"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\targetver.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Xbox360Controller.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Xbox360Controller.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Xbox360EventClient.cpp"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/EventClients/Clients/Xbox360Controller/stdafx.cpp b/tools/EventClients/Clients/Xbox360Controller/stdafx.cpp
new file mode 100644
index 0000000..648e7e6
--- /dev/null
+++ b/tools/EventClients/Clients/Xbox360Controller/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// Xbox360EventClient.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/tools/EventClients/Clients/Xbox360Controller/stdafx.h b/tools/EventClients/Clients/Xbox360Controller/stdafx.h
new file mode 100644
index 0000000..b005a83
--- /dev/null
+++ b/tools/EventClients/Clients/Xbox360Controller/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/tools/EventClients/Clients/Xbox360Controller/targetver.h b/tools/EventClients/Clients/Xbox360Controller/targetver.h
new file mode 100644
index 0000000..5697f1a
--- /dev/null
+++ b/tools/EventClients/Clients/Xbox360Controller/targetver.h
@@ -0,0 +1,13 @@
+#pragma once
+
+// The following macros define the minimum required platform. The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
+// your application. The macros work by enabling all features available on platform versions up to and
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
diff --git a/tools/EventClients/README.txt b/tools/EventClients/README.txt
new file mode 100644
index 0000000..51dcab1
--- /dev/null
+++ b/tools/EventClients/README.txt
@@ -0,0 +1,90 @@
+Event Client Examples and PS3 Sixaxis and Blu-Ray Remote Support
+----------------------------------------------------------------
+
+This directory contains 6 sample programs that demonstrate XBMC's
+event server (which is still in development). The programs are in
+Python and C++. XBMC also needs to be running (obviously) so that it
+can receive the events.
+
+- example_button1.py | example_button1.cpp
+- example_button2.py | example_button2.cpp
+- example_notification.py | example_notification.cpp
+
+The first 2 show how button / key presses can be sent to XBMC.
+The third one shows how to display notifications in XBMC.
+
+- xbmcclient.py
+- xbmcclient.h
+
+These are the Python module and C++ header that you can use when
+writing your own programs. It is not yet complete and likely to change
+but is still usable.
+
+Implementation details can be found in the comments in the sample
+programs.
+
+
+PS3 Controller and PS3 Blu-Ray Remote Support
+---------------------------------------------
+
+There is also initial support for the PS3 controller (sixaxis) and the
+PS3 Blu-Ray remote.
+
+Pairing of the PS3 Blu-Ray Remote
+---------------------------------
+
+The remote needs to be paired initially with the 'ps3_remote.py'
+program in this directory which you can continue using if you do not
+want to run 'ps3d.py' as root. The disadvantage of using
+'ps3_remote.py' is that pairing is required on every run. Once initial
+pairing is done, 'ps3d.py', when run as root, will automatically
+detect incoming connections from both the PS3 remote and the Sixaxis
+controller.
+
+Pairing of the PS3 Sixaxis Controller (TODO)
+--------------------------------------------
+
+The pairing of the PS3 controller is not yet handled automatically. It
+can however be done using the program "sixaxis.c" available from:
+
+http://www.pabr.org/sixlinux/sixlinux.en.html
+
+Once pairing for either or both has been done, run the ps3d.py program
+as root after disabling any existing HID servers that might currently
+be running. The program requires root privileges since it listens on
+Bluetooth L2CAP PSMs 17 and 19.
+
+Using the PS3 Sixaxis Controller
+--------------------------------
+
+Currently, all that is supported with the Sixaxis controller is to be able
+emulate the mouse behavior. Hold down the PS button and wave the controller
+around and watch the mouse in XBMC mouse. Tilt it from left to right (along
+your Z axis) to control horizontal motion. Tilt it towards and away from you
+along (along your X axis) to control vertical mouse movement.
+
+That's all for now.
+
+WiiRemote Support
+-----------------
+
+The executable depends on libcwiid and libbluetooth and is compiled using
+# g++ WiiRemote.cpp -lcwiid -o WiiRemote
+The WiiRemote will emulate mouse by default but can be disabled by running with --disable-mouseemulation
+The sensitivity of the mouseemulation can be set using the --deadzone_x or --deadzone_y where the number is
+the percentage of the space is considered "dead", higher means more sensitive.
+Other commands can be listed with --help
+
+The WiiRemote is mappable with keymap.xml where button id's are the following:
+1 = Up
+2 = Down
+3 = Left
+4 = Right
+5 = A
+6 = B
+7 = Minus
+8 = Home
+9 = Plus
+10 = 1
+11 = 2
+The name is by standard WiiRemote but this can be changed with the --joystick-name
diff --git a/tools/EventClients/examples/c#/XBMCDemoClient1.cs b/tools/EventClients/examples/c#/XBMCDemoClient1.cs
new file mode 100644
index 0000000..df74dea
--- /dev/null
+++ b/tools/EventClients/examples/c#/XBMCDemoClient1.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Windows.Forms;
+using XBMC;
+
+namespace XBMCEventClientDemo
+{
+ static class Program
+ {
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main()
+ {
+ EventClient eventClient = new EventClient();
+ eventClient.Connect("127.0.0.1", 9777);
+
+ string iconFile = @"../../icons/icon.png";
+ IconType iconType = IconType.ICON_PNG;
+
+ if !File.Exists(iconFile) {
+ iconFile = @"/usr/share/xbmc/media/icon.png";
+ if !File.Exists(iconFile) {
+ iconType = IconType.ICON_NONE;
+ }
+ }
+
+ eventClient.SendHelo("XBMC Client Demo", iconType, iconFile);
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendNotification("XBMC Client Demo", "Notification Message", iconType, iconFile);
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendButton("dpadup", "XG", ButtonFlagsType.BTN_DOWN | ButtonFlagsType.BTN_NO_REPEAT, 0);
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendPing();
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendMouse(32768, 32768);
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendLog(LogTypeEnum.LOGERROR, "Example error log message from XBMC Client Demo");
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendAction("Mute");
+ System.Threading.Thread.Sleep(1000);
+ eventClient.SendBye();
+ }
+ }
+}
diff --git a/tools/EventClients/examples/c++/example_button1.cpp b/tools/EventClients/examples/c++/example_button1.cpp
new file mode 100644
index 0000000..d96f268
--- /dev/null
+++ b/tools/EventClients/examples/c++/example_button1.cpp
@@ -0,0 +1,65 @@
+#include "../../lib/c++/xbmcclient.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#ifdef _WIN32
+#include <Windows.h> // for sleep
+#else
+#include <unistd.h>
+#endif
+
+int main(int argc, char **argv)
+{
+ /* connect to localhost, port 9777 using a UDP socket
+ this only needs to be done once.
+ by default this is where XBMC will be listening for incoming
+ connections. */
+ CAddress my_addr; // Address => localhost on 9777
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ {
+ printf("Error creating socket\n");
+ return -1;
+ }
+
+ my_addr.Bind(sockfd);
+
+ std::string sIconFile = "../../icons/bluetooth.png";
+ unsigned short usIconType = ICON_PNG;
+
+ std::ifstream file (sIconFile, std::ios::in|std::ios::binary|std::ios::ate);
+ if (!file.is_open())
+ {
+ sIconFile = "/usr/share/pixmaps/kodi/bluetooth.png";
+ file.open(sIconFile, std::ios::in|std::ios::binary|std::ios::ate);
+
+ if (!file.is_open()) {
+ usIconType = ICON_NONE;
+ }
+ else
+ {
+ file.close();
+ }
+ }
+ else
+ {
+ file.close();
+ }
+
+ CPacketHELO HeloPackage("Example Remote", usIconType, sIconFile.c_str());
+ HeloPackage.Send(sockfd, my_addr);
+
+ sleep(5);
+ // press 'S'
+ CPacketBUTTON btn1('S', true);
+ btn1.Send(sockfd, my_addr);
+
+ sleep(2);
+ // press the enter key (13 = enter)
+ CPacketBUTTON btn2(13, true);
+ btn2.Send(sockfd, my_addr);
+
+ // BYE is not required since XBMC would have shut down
+ CPacketBYE bye; // CPacketPing if you want to ping
+ bye.Send(sockfd, my_addr);
+}
diff --git a/tools/EventClients/examples/c++/example_button2.cpp b/tools/EventClients/examples/c++/example_button2.cpp
new file mode 100644
index 0000000..ddb55be
--- /dev/null
+++ b/tools/EventClients/examples/c++/example_button2.cpp
@@ -0,0 +1,75 @@
+#include "../../lib/c++/xbmcclient.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#ifdef _WIN32
+#include <Windows.h> // for sleep
+#else
+#include <unistd.h>
+#endif
+
+int main(int argc, char **argv)
+{
+ /* connect to localhost, port 9777 using a UDP socket
+ this only needs to be done once.
+ by default this is where XBMC will be listening for incoming
+ connections. */
+ CAddress my_addr; // Address => localhost on 9777
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ {
+ printf("Error creating socket\n");
+ return -1;
+ }
+
+ my_addr.Bind(sockfd);
+
+ std::string sIconFile = "../../icons/bluetooth.png";
+ unsigned short usIconType = ICON_PNG;
+
+ std::ifstream file (sIconFile, std::ios::in|std::ios::binary|std::ios::ate);
+ if (!file.is_open())
+ {
+ sIconFile = "/usr/share/pixmaps/kodi/bluetooth.png";
+ file.open(sIconFile, std::ios::in|std::ios::binary|std::ios::ate);
+
+ if (!file.is_open()) {
+ usIconType = ICON_NONE;
+ }
+ else
+ {
+ file.close();
+ }
+ }
+ else
+ {
+ file.close();
+ }
+
+ CPacketHELO HeloPackage("Example Remote", usIconType, sIconFile.c_str());
+ HeloPackage.Send(sockfd, my_addr);
+
+ sleep(5);
+ // Note that we have foo(BUTTON, DEVICEMAP);
+ CPacketBUTTON btn1("dpadup", "XG", 0);
+ btn1.Send(sockfd, my_addr);
+
+ sleep(5);
+
+ CPacketBUTTON btn2(0x28, 0);
+ btn2.Send(sockfd, my_addr);
+
+ sleep(5);
+
+ CPacketBUTTON btn3("right", "KB", 0);
+ btn3.Send(sockfd, my_addr);
+
+ sleep(5);
+ // Release button
+ CPacketBUTTON btn4;
+ btn4.Send(sockfd, my_addr);
+
+ // BYE is not required since XBMC would have shut down
+ CPacketBYE bye; // CPacketPing if you want to ping
+ bye.Send(sockfd, my_addr);
+}
diff --git a/tools/EventClients/examples/c++/example_log.cpp b/tools/EventClients/examples/c++/example_log.cpp
new file mode 100644
index 0000000..ca61cb0
--- /dev/null
+++ b/tools/EventClients/examples/c++/example_log.cpp
@@ -0,0 +1,39 @@
+#include "../../lib/c++/xbmcclient.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#ifdef _WIN32
+#include <Windows.h> // for sleep
+#else
+#include <unistd.h>
+#endif
+
+int main(int argc, char **argv)
+{
+ /* connect to localhost, port 9777 using a UDP socket
+ this only needs to be done once.
+ by default this is where XBMC will be listening for incoming
+ connections. */
+
+ CAddress my_addr; // Address => localhost on 9777
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ {
+ printf("Error creating socket\n");
+ return -1;
+ }
+
+ my_addr.Bind(sockfd);
+ //Normally this is already done by the client
+ CPacketHELO HeloPackage("LOG Test", ICON_NONE);
+ HeloPackage.Send(sockfd, my_addr);
+
+ sleep(5);
+ //This works as XBMC internal CLog::LOG(LOGTYPE, STRING);
+ CPacketLOG packet(LOGERROR, "The Log Message");
+ packet.Send(sockfd, my_addr);
+
+ // BYE is not required since XBMC would have shut down
+ CPacketBYE bye; // CPacketPing if you want to ping
+ bye.Send(sockfd, my_addr);
+}
diff --git a/tools/EventClients/examples/c++/example_mouse.cpp b/tools/EventClients/examples/c++/example_mouse.cpp
new file mode 100644
index 0000000..a0c5832
--- /dev/null
+++ b/tools/EventClients/examples/c++/example_mouse.cpp
@@ -0,0 +1,63 @@
+#include "../../lib/c++/xbmcclient.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#ifdef _WIN32
+#include <Windows.h> // for sleep
+#else
+#include <unistd.h>
+#endif
+
+int main(int argc, char **argv)
+{
+ /* connect to localhost, port 9777 using a UDP socket
+ this only needs to be done once.
+ by default this is where XBMC will be listening for incoming
+ connections. */
+ CAddress my_addr; // Address => localhost on 9777
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ {
+ printf("Error creating socket\n");
+ return -1;
+ }
+
+ my_addr.Bind(sockfd);
+
+ std::string sIconFile = "../../icons/mouse.png";
+ unsigned short usIconType = ICON_PNG;
+
+ std::ifstream file (sIconFile, std::ios::in|std::ios::binary|std::ios::ate);
+ if (!file.is_open())
+ {
+ sIconFile = "/usr/share/pixmaps/kodi/mouse.png";
+ file.open(sIconFile, std::ios::in|std::ios::binary|std::ios::ate);
+
+ if (!file.is_open()) {
+ usIconType = ICON_NONE;
+ }
+ else
+ {
+ file.close();
+ }
+ }
+ else
+ {
+ file.close();
+ }
+
+ CPacketHELO HeloPackage("Example Mouse", usIconType, sIconFile.c_str());
+ HeloPackage.Send(sockfd, my_addr);
+
+ sleep(5);
+
+ for(int i = 0; i < 65536; i++)
+ {
+ CPacketMOUSE mouse(i,i);
+ mouse.Send(sockfd, my_addr);
+ }
+
+ // BYE is not required since XBMC would have shut down
+ CPacketBYE bye; // CPacketPing if you want to ping
+ bye.Send(sockfd, my_addr);
+}
diff --git a/tools/EventClients/examples/c++/example_notification.cpp b/tools/EventClients/examples/c++/example_notification.cpp
new file mode 100644
index 0000000..5cd0657
--- /dev/null
+++ b/tools/EventClients/examples/c++/example_notification.cpp
@@ -0,0 +1,64 @@
+#include "../../lib/c++/xbmcclient.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#ifdef _WIN32
+#include <Windows.h> // for sleep
+#else
+#include <unistd.h>
+#endif
+
+int main(int argc, char **argv)
+{
+ /* connect to localhost, port 9777 using a UDP socket
+ this only needs to be done once.
+ by default this is where XBMC will be listening for incoming
+ connections. */
+
+ CAddress my_addr; // Address => localhost on 9777
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ {
+ printf("Error creating socket\n");
+ return -1;
+ }
+
+ my_addr.Bind(sockfd);
+
+ std::string sIconFile = "../../icons/mail.png";
+ unsigned short usIconType = ICON_PNG;
+
+ std::ifstream file (sIconFile, std::ios::in|std::ios::binary|std::ios::ate);
+ if (!file.is_open())
+ {
+ sIconFile = "/usr/share/pixmaps/kodi/mail.png";
+ file.open(sIconFile, std::ios::in|std::ios::binary|std::ios::ate);
+
+ if (!file.is_open()) {
+ usIconType = ICON_NONE;
+ }
+ else
+ {
+ file.close();
+ }
+ }
+ else
+ {
+ file.close();
+ }
+
+ CPacketHELO HeloPackage("Email Notifier", ICON_NONE);
+ HeloPackage.Send(sockfd, my_addr);
+
+ sleep(5);
+
+ CPacketNOTIFICATION packet("New Mail!", // caption
+ "RE: Check this out", // message
+ usIconType, // optional icon type
+ sIconFile.c_str()); // icon file (local)
+ packet.Send(sockfd, my_addr);
+
+ // BYE is not required since XBMC would have shut down
+ CPacketBYE bye; // CPacketPing if you want to ping
+ bye.Send(sockfd, my_addr);
+}
diff --git a/tools/EventClients/examples/java/XBMCDemoClient1.java b/tools/EventClients/examples/java/XBMCDemoClient1.java
new file mode 100644
index 0000000..5bb2821
--- /dev/null
+++ b/tools/EventClients/examples/java/XBMCDemoClient1.java
@@ -0,0 +1,70 @@
+package org.xbmc.eventclient.demo;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+
+import org.xbmc.eventclient.XBMCClient;
+
+/**
+ * Simple Demo EventClient
+ * @author Stefan Agner
+ *
+ */
+public class XBMCDemoClient1 {
+
+ /**
+ * Simple Demo EventClient
+ * @param args
+ */
+ public static void main(String[] args) throws IOException, InterruptedException {
+ InetAddress host = Inet4Address.getByAddress(new byte[] { (byte)127, 0, 0, 1 } );
+
+ Thread.sleep(20000);
+
+ String iconFile = "/usr/share/xbmc/media/icon.png";
+
+ if (! new File(iconFile).exists()) {
+ iconFile = "../../icons/icon.png";
+
+ if (! new File(iconFile).exists()) {
+ iconFile = "";
+ }
+ }
+
+ XBMCClient oXBMCClient = null;
+
+ if (iconFile != "") {
+ oXBMCClient = new XBMCClient(host, 9777, "My Client", iconFile);
+ } else {
+ oXBMCClient = new XBMCClient(host, 9777, "My Client");
+ }
+
+ Thread.sleep(7000);
+
+ oXBMCClient.sendNotification("My Title", "My Message");
+
+
+ Thread.sleep(7000);
+
+ oXBMCClient.sendButton("KB", "escape", false, true, false, (short)0 , (byte)0);
+
+
+ Thread.sleep(7000);
+ oXBMCClient.sendButton("KB", "escape", true, true, false, (short)0 , (byte)0);
+ oXBMCClient.sendNotification("My Title", "Escape sent");
+
+ Thread.sleep(1000);
+
+ oXBMCClient.sendButton("KB", "escape", true, false, false, (short)0 , (byte)0);
+ oXBMCClient.sendNotification("My Title", "Escape released");
+
+ Thread.sleep(7000);
+ oXBMCClient.sendLog((byte)0, "My Client disconnects....");
+ oXBMCClient.sendNotification("My Title", "Client will disconnect");
+ oXBMCClient.stopClient();
+
+ }
+
+}
diff --git a/tools/EventClients/examples/python/example_action.py b/tools/EventClients/examples/python/example_action.py
new file mode 100755
index 0000000..b87fc29
--- /dev/null
+++ b/tools/EventClients/examples/python/example_action.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+
+# This is a simple example showing how you can send a key press event
+# to XBMC using the XBMCClient class
+
+import os
+from socket import *
+import sys
+
+if os.path.exists("../../lib/python"):
+ # try loading modules from source directory
+ sys.path.append("../../lib/python")
+
+ from xbmcclient import *
+
+ ICON_PATH = "../../icons/"
+else:
+ # fallback to system wide modules
+
+ from kodi.xbmcclient import *
+ from kodi.defs import *
+
+def main():
+
+ host = "localhost"
+ port = 9777
+
+ # Create an XBMCClient object and connect
+ xbmc = XBMCClient("Example Remote", ICON_PATH + "/bluetooth.png")
+ xbmc.connect()
+
+ # send a up key press using the xbox gamepad map "XG" and button
+ # name "dpadup" ( see PacketBUTTON doc for more details)
+ try:
+ xbmc.send_action(sys.argv[2], ACTION_BUTTON)
+ except:
+ try:
+ xbmc.send_action(sys.argv[1], ACTION_EXECBUILTIN)
+ except Exception as e:
+ print(str(e))
+ xbmc.send_action("ActivateWindow(ShutdownMenu)")
+
+
+ # ok we're done, close the connection
+ # Note that closing the connection clears any repeat key that is
+ # active. So in this example, the actual release button event above
+ # need not have been sent.
+ xbmc.close()
+
+if __name__=="__main__":
+ main()
diff --git a/tools/EventClients/examples/python/example_button1.py b/tools/EventClients/examples/python/example_button1.py
new file mode 100755
index 0000000..abdfe49
--- /dev/null
+++ b/tools/EventClients/examples/python/example_button1.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+
+# This is a simple example showing how you can send 2 button events
+# to XBMC in a queued fashion to shut it down.
+
+# Queued button events are not repeatable.
+
+# The basic idea is to create single packets and shoot them to XBMC
+# The provided library implements some of the support commands and
+# takes care of creating the actual packet. Using it is as simple
+# as creating an object with the required constructor arguments and
+# sending it through a socket.
+
+# Currently, only keyboard keys are supported so the key codes used
+# below are the same key codes used in guilib/common/SDLKeyboard.cpp
+
+# In effect, anything that can be done with the keyboard can be done
+# using the event client.
+
+# import the XBMC client library
+# NOTE: The library is not complete yet but is usable at this stage.
+
+import os
+from socket import *
+import sys
+
+if os.path.exists("../../lib/python"):
+ # try loading modules from source directory
+ sys.path.append("../../lib/python")
+
+ from xbmcclient import *
+
+ ICON_PATH = "../../icons/"
+else:
+ # fallback to system wide modules
+
+ from kodi.xbmcclient import *
+ from kodi.defs import *
+
+def main():
+ import time
+ import sys
+
+ # connect to localhost, port 9777 using a UDP socket
+ # this only needs to be done once.
+ # by default this is where XBMC will be listening for incoming
+ # connections.
+ host = "localhost"
+ port = 9777
+ addr = (host, port)
+ sock = socket(AF_INET,SOCK_DGRAM)
+
+ # First packet must be HELO (no it's not a typo) and can contain an icon
+ # 'icon_type' can be one of ICON_NONE, ICON_PNG, ICON_JPG or ICON_GIF
+ packet = PacketHELO(devicename="Example Remote",
+ icon_type=ICON_PNG,
+ icon_file=ICON_PATH + "/bluetooth.png")
+ packet.send(sock, addr)
+
+ # IMPORTANT: After a HELO packet is sent, the client needs to "ping" XBMC
+ # at least once every 60 seconds or else the client will time out.
+ # Every valid packet sent to XBMC acts as a ping, however if no valid
+ # packets NEED to be sent (eg. the user hasn't pressed a key in 50 seconds)
+ # then you can use the PacketPING class to send a ping packet (which is
+ # basically just an empty packet). See below.
+
+ # Once a client times out, it will need to reissue the HELO packet.
+ # Currently, since this is a unidirectional protocol, there is no way
+ # for the client to know if it has timed out.
+
+ # wait for notification window to close (in XBMC)
+ time.sleep(5)
+
+ # press 'S'
+ packet = PacketBUTTON(code='S', queue=1)
+ packet.send(sock, addr)
+
+ # wait for a few seconds
+ time.sleep(2)
+
+ # press the enter key (13 = enter)
+ packet = PacketBUTTON(code=13, queue=1)
+ packet.send(sock, addr)
+
+ # BYE is not required since XBMC would have shut down
+ packet = PacketBYE() # PacketPING if you want to ping
+ packet.send(sock, addr)
+
+if __name__=="__main__":
+ main()
diff --git a/tools/EventClients/examples/python/example_button2.py b/tools/EventClients/examples/python/example_button2.py
new file mode 100755
index 0000000..bb91704
--- /dev/null
+++ b/tools/EventClients/examples/python/example_button2.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+
+# This is a simple example showing how you can send a key press event
+# to XBMC in a non-queued fashion to achieve a button pressed down
+# event i.e. a key press that repeats.
+
+# The repeat interval is currently hard coded in XBMC but that might
+# change in the future.
+
+# NOTE: Read the comments in 'example_button1.py' for a more detailed
+# explanation.
+
+import os
+from socket import *
+import sys
+
+if os.path.exists("../../lib/python"):
+ # try loading modules from source directory
+ sys.path.append("../../lib/python")
+
+ from xbmcclient import *
+
+ ICON_PATH = "../../icons/"
+else:
+ # fallback to system wide modules
+
+ from kodi.xbmcclient import *
+ from kodi.defs import *
+
+def main():
+ import time
+ import sys
+
+ host = "localhost"
+ port = 9777
+ addr = (host, port)
+
+ sock = socket(AF_INET,SOCK_DGRAM)
+
+ # First packet must be HELO and can contain an icon
+ packet = PacketHELO("Example Remote", ICON_PNG,
+ ICON_PATH + "/bluetooth.png")
+ packet.send(sock, addr)
+
+ # wait for notification window to close (in XBMC)
+ time.sleep(5)
+
+ # send a up key press using the xbox gamepad map "XG" and button
+ # name "dpadup" ( see PacketBUTTON doc for more details)
+ packet = PacketBUTTON(map_name="XG", button_name="dpadup")
+ packet.send(sock, addr)
+
+ # wait for a few seconds to see its effect
+ time.sleep(5)
+
+ # send a down key press using the raw keyboard code
+ packet = PacketBUTTON(code=0x28)
+ packet.send(sock, addr)
+
+ # wait for a few seconds to see its effect
+ time.sleep(5)
+
+ # send a right key press using the keyboard map "KB" and button
+ # name "right"
+ packet = PacketBUTTON(map_name="KB", button_name="right")
+ packet.send(sock, addr)
+
+ # wait for a few seconds to see its effect
+ time.sleep(5)
+
+ # that's enough, release the button. During release, button code
+ # doesn't matter.
+ packet = PacketBUTTON(code=0x28, down=0)
+ packet.send(sock, addr)
+
+ # ok we're done, close the connection
+ # Note that closing the connection clears any repeat key that is
+ # active. So in this example, the actual release button event above
+ # need not have been sent.
+ packet = PacketBYE()
+ packet.send(sock, addr)
+
+if __name__=="__main__":
+ main()
diff --git a/tools/EventClients/examples/python/example_mouse.py b/tools/EventClients/examples/python/example_mouse.py
new file mode 100755
index 0000000..7c43782
--- /dev/null
+++ b/tools/EventClients/examples/python/example_mouse.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+
+# This is a simple example showing how you can send mouse movement
+# events to XBMC.
+
+# NOTE: Read the comments in 'example_button1.py' for a more detailed
+# explanation.
+
+import os
+from socket import *
+import sys
+
+if os.path.exists("../../lib/python"):
+ # try loading modules from source directory
+ sys.path.append("../../lib/python")
+
+ from xbmcclient import *
+
+ ICON_PATH = "../../icons/"
+else:
+ # fallback to system wide modules
+
+ from kodi.xbmcclient import *
+ from kodi.defs import *
+
+def main():
+ import time
+ import sys
+
+ host = "localhost"
+ port = 9777
+ addr = (host, port)
+
+ sock = socket(AF_INET,SOCK_DGRAM)
+
+ # First packet must be HELO and can contain an icon
+ packet = PacketHELO("Example Mouse", ICON_PNG,
+ ICON_PATH + "/mouse.png")
+ packet.send(sock, addr)
+
+ # wait for notification window to close (in XBMC)
+ time.sleep(2)
+
+ # send mouse events to take cursor from top left to bottom right of the screen
+ # here 0 to 65535 will map to XBMC's screen width and height.
+ # Specifying absolute mouse coordinates is unsupported currently.
+ for i in range(0, 65535, 2):
+ packet = PacketMOUSE(i,i)
+ packet.send(sock, addr)
+
+ # ok we're done, close the connection
+ packet = PacketBYE()
+ packet.send(sock, addr)
+
+if __name__=="__main__":
+ main()
diff --git a/tools/EventClients/examples/python/example_notification.py b/tools/EventClients/examples/python/example_notification.py
new file mode 100755
index 0000000..fd1a82e
--- /dev/null
+++ b/tools/EventClients/examples/python/example_notification.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+
+# This is a simple example showing how you can show a notification
+# window with a custom icon inside XBMC. It could be used by mail
+# monitoring apps, calendar apps, etc.
+
+import os
+from socket import *
+import sys
+
+if os.path.exists("../../lib/python"):
+ # try loading modules from source directory
+ sys.path.append("../../lib/python")
+
+ from xbmcclient import *
+
+ ICON_PATH = "../../icons/"
+else:
+ # fallback to system wide modules
+
+ from kodi.xbmcclient import *
+ from kodi.defs import *
+
+def main():
+ import time
+ import sys
+
+ host = "localhost"
+ port = 9777
+ addr = (host, port)
+ sock = socket(AF_INET,SOCK_DGRAM)
+
+ packet = PacketHELO("Email Notifier", ICON_NONE)
+ packet.send(sock, addr)
+
+ # wait for 5 seconds
+ time.sleep (5)
+
+ packet = PacketNOTIFICATION("New Mail!", # caption
+ "RE: Check this out", # message
+ ICON_PNG, # optional icon type
+ ICON_PATH + "/mail.png") # icon file (local)
+ packet.send(sock, addr)
+
+ packet = PacketBYE()
+ packet.send(sock, addr)
+
+if __name__=="__main__":
+ main()
diff --git a/tools/EventClients/examples/python/example_simple.py b/tools/EventClients/examples/python/example_simple.py
new file mode 100755
index 0000000..2d807e8
--- /dev/null
+++ b/tools/EventClients/examples/python/example_simple.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python3
+
+# This is a simple example showing how you can send a key press event
+# to XBMC using the XBMCClient class
+
+import os
+from socket import *
+import sys
+import time
+
+if os.path.exists("../../lib/python"):
+ # try loading modules from source directory
+ sys.path.append("../../lib/python")
+
+ from xbmcclient import *
+
+ ICON_PATH = "../../icons/"
+else:
+ # fallback to system wide modules
+
+ from kodi.xbmcclient import *
+ from kodi.defs import *
+
+def main():
+
+ host = "localhost"
+ port = 9777
+
+ # Create an XBMCClient object and connect
+ xbmc = XBMCClient("Example Remote", ICON_PATH + "/bluetooth.png")
+ xbmc.connect()
+
+ # wait for notification window to close (in XBMC) (optional)
+ time.sleep(5)
+
+ # send a up key press using the xbox gamepad map "XG" and button
+ # name "dpadup" ( see PacketBUTTON doc for more details)
+ xbmc.send_button(map="XG", button="dpadup")
+
+ # wait for a few seconds to see its effect
+ time.sleep(5)
+
+ # send a right key press using the keyboard map "KB" and button
+ # name "right"
+ xbmc.send_keyboard_button("right")
+
+ # wait for a few seconds to see its effect
+ time.sleep(5)
+
+ # that's enough, release the button.
+ xbmc.release_button()
+
+ # ok we're done, close the connection
+ # Note that closing the connection clears any repeat key that is
+ # active. So in this example, the actual release button event above
+ # need not have been sent.
+ xbmc.close()
+
+if __name__=="__main__":
+ main()
diff --git a/tools/EventClients/icons/bluetooth.png b/tools/EventClients/icons/bluetooth.png
new file mode 100644
index 0000000..6b5837e
--- /dev/null
+++ b/tools/EventClients/icons/bluetooth.png
Binary files differ
diff --git a/tools/EventClients/icons/mail.png b/tools/EventClients/icons/mail.png
new file mode 100644
index 0000000..8f4ea85
--- /dev/null
+++ b/tools/EventClients/icons/mail.png
Binary files differ
diff --git a/tools/EventClients/icons/mouse.png b/tools/EventClients/icons/mouse.png
new file mode 100644
index 0000000..0d0e588
--- /dev/null
+++ b/tools/EventClients/icons/mouse.png
Binary files differ
diff --git a/tools/EventClients/icons/phone.png b/tools/EventClients/icons/phone.png
new file mode 100644
index 0000000..43fb7fe
--- /dev/null
+++ b/tools/EventClients/icons/phone.png
Binary files differ
diff --git a/tools/EventClients/lib/c#/EventClient.cs b/tools/EventClients/lib/c#/EventClient.cs
new file mode 100644
index 0000000..fe2615b
--- /dev/null
+++ b/tools/EventClients/lib/c#/EventClient.cs
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+
+namespace XBMC
+{
+
+ public enum IconType
+ {
+ ICON_NONE = 0x00,
+ ICON_JPEG = 0x01,
+ ICON_PNG = 0x02,
+ ICON_GIF = 0x03
+ }
+
+ public enum ButtonFlagsType
+ {
+ BTN_USE_NAME = 0x01,
+ BTN_DOWN = 0x02,
+ BTN_UP = 0x04,
+ BTN_USE_AMOUNT = 0x08,
+ BTN_QUEUE = 0x10,
+ BTN_NO_REPEAT = 0x20,
+ BTN_VKEY = 0x40,
+ BTN_AXIS = 0x80
+ }
+
+ public enum MouseFlagsType
+ {
+ MS_ABSOLUTE = 0x01
+ }
+
+ public enum LogTypeEnum
+ {
+ LOGDEBUG = 0,
+ LOGINFO = 1,
+ LOGNOTICE = 2,
+ LOGWARNING = 3,
+ LOGERROR = 4,
+ LOGSEVERE = 5,
+ LOGFATAL = 6,
+ LOGNONE = 7
+ }
+
+ public enum ActionType
+ {
+ ACTION_EXECBUILTIN = 0x01,
+ ACTION_BUTTON = 0x02
+ }
+
+ public class EventClient
+ {
+
+ /************************************************************************/
+ /* Written by Peter Tribe aka EqUiNox (TeamBlackbolt) */
+ /* Based upon XBMC's xbmcclient.cpp class */
+ /************************************************************************/
+
+ private enum PacketType
+ {
+ PT_HELO = 0x01,
+ PT_BYE = 0x02,
+ PT_BUTTON = 0x03,
+ PT_MOUSE = 0x04,
+ PT_PING = 0x05,
+ PT_BROADCAST = 0x06, //Currently not implemented
+ PT_NOTIFICATION = 0x07,
+ PT_BLOB = 0x08,
+ PT_LOG = 0x09,
+ PT_ACTION = 0x0A,
+ PT_DEBUG = 0xFF //Currently not implemented
+ }
+
+ private const int STD_PORT = 9777;
+ private const int MAX_PACKET_SIZE = 1024;
+ private const int HEADER_SIZE = 32;
+ private const int MAX_PAYLOAD_SIZE = MAX_PACKET_SIZE - HEADER_SIZE;
+ private const byte MAJOR_VERSION = 2;
+ private const byte MINOR_VERSION = 0;
+
+ private uint uniqueToken;
+ private Socket socket;
+
+ public bool Connect(string Address)
+ {
+ return Connect(Address, STD_PORT, (uint)System.DateTime.Now.TimeOfDay.Milliseconds);
+ }
+
+ public bool Connect(string Address, int Port)
+ {
+ return Connect(Address, Port, (uint)System.DateTime.Now.TimeOfDay.Milliseconds);
+ }
+
+
+ public bool Connect(string Address, int Port, uint UID)
+ {
+ try
+ {
+ if (socket != null) Disconnect();
+ uniqueToken = UID;
+ socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+
+// For compilation with .net framework 1.0 or 1.1
+// define the FRAMEWORK_1_x conditional compilation constant in the project
+// or add /define:FRAMEWORK_1_x to the csc.exe command line
+#if FRAMEWORK_1_x
+ socket.Connect(Dns.GetHostByName(Address).AddressList[0].ToString(), Port);
+#else
+ socket.Connect(Address, Port);
+#endif
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ public bool Connected
+ {
+ get
+ {
+ if (socket == null) return false;
+ return socket.Connected;
+ }
+ }
+
+ public void Disconnect()
+ {
+ try
+ {
+ if (socket != null)
+ {
+ socket.Shutdown(SocketShutdown.Both);
+ socket.Close();
+ socket = null;
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ private byte[] Header(PacketType PacketType, int NumberOfPackets, int CurrentPacket, int PayloadSize)
+ {
+
+ byte[] header = new byte[HEADER_SIZE];
+
+ header[0] = (byte)'X';
+ header[1] = (byte)'B';
+ header[2] = (byte)'M';
+ header[3] = (byte)'C';
+
+ header[4] = MAJOR_VERSION;
+ header[5] = MINOR_VERSION;
+
+ if (CurrentPacket == 1)
+ {
+ header[6] = (byte)(((ushort)PacketType & 0xff00) >> 8);
+ header[7] = (byte)((ushort)PacketType & 0x00ff);
+ }
+ else
+ {
+ header[6] = (byte)(((ushort)PacketType.PT_BLOB & 0xff00) >> 8);
+ header[7] = (byte)((ushort)PacketType.PT_BLOB & 0x00ff);
+ }
+
+ header[8] = (byte)((CurrentPacket & 0xff000000) >> 24);
+ header[9] = (byte)((CurrentPacket & 0x00ff0000) >> 16);
+ header[10] = (byte)((CurrentPacket & 0x0000ff00) >> 8);
+ header[11] = (byte)(CurrentPacket & 0x000000ff);
+
+ header[12] = (byte)((NumberOfPackets & 0xff000000) >> 24);
+ header[13] = (byte)((NumberOfPackets & 0x00ff0000) >> 16);
+ header[14] = (byte)((NumberOfPackets & 0x0000ff00) >> 8);
+ header[15] = (byte)(NumberOfPackets & 0x000000ff);
+
+ header[16] = (byte)((PayloadSize & 0xff00) >> 8);
+ header[17] = (byte)(PayloadSize & 0x00ff);
+
+ header[18] = (byte)((uniqueToken & 0xff000000) >> 24);
+ header[19] = (byte)((uniqueToken & 0x00ff0000) >> 16);
+ header[20] = (byte)((uniqueToken & 0x0000ff00) >> 8);
+ header[21] = (byte)(uniqueToken & 0x000000ff);
+
+ return header;
+
+ }
+
+ private bool Send(PacketType PacketType, byte[] Payload)
+ {
+ try
+ {
+
+ bool successful = true;
+ int packetCount = (Payload.Length / MAX_PAYLOAD_SIZE) + 1;
+ int bytesToSend = 0;
+ int bytesSent = 0;
+ int bytesLeft = Payload.Length;
+
+ for (int Package = 1; Package <= packetCount; Package++)
+ {
+
+ if (bytesLeft > MAX_PAYLOAD_SIZE)
+ {
+ bytesToSend = MAX_PAYLOAD_SIZE;
+ bytesLeft -= bytesToSend;
+ }
+ else
+ {
+ bytesToSend = bytesLeft;
+ bytesLeft = 0;
+ }
+
+ byte[] header = Header(PacketType, packetCount, Package, bytesToSend);
+ byte[] packet = new byte[MAX_PACKET_SIZE];
+
+ Array.Copy(header, 0, packet, 0, header.Length);
+ Array.Copy(Payload, bytesSent, packet, header.Length, bytesToSend);
+
+ int sendSize = socket.Send(packet, header.Length + bytesToSend, SocketFlags.None);
+
+ if (sendSize != (header.Length + bytesToSend))
+ {
+ successful = false;
+ break;
+ }
+
+ bytesSent += bytesToSend;
+
+ }
+
+ return successful;
+
+ }
+ catch
+ {
+
+ return false;
+
+ }
+
+ }
+
+ /************************************************************************/
+ /* SendHelo - Payload format */
+ /* %s - device name (max 128 chars) */
+ /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */
+ /* %s - my port ( 0=>not listening ) */
+ /* %d - reserved1 ( 0 ) */
+ /* %d - reserved2 ( 0 ) */
+ /* XX - imagedata ( can span multiple packets ) */
+ /************************************************************************/
+ public bool SendHelo(string DevName, IconType IconType, string IconFile)
+ {
+
+ byte[] icon = new byte[0];
+ if (IconType != IconType.ICON_NONE)
+ icon = File.ReadAllBytes(IconFile);
+
+ byte[] payload = new byte[DevName.Length + 12 + icon.Length];
+
+ int offset = 0;
+
+ for (int i = 0; i < DevName.Length; i++)
+ payload[offset++] = (byte)DevName[i];
+ payload[offset++] = (byte)'\0';
+
+ payload[offset++] = (byte)IconType;
+
+ payload[offset++] = (byte)0;
+ payload[offset++] = (byte)'\0';
+
+ for (int i = 0; i < 8; i++)
+ payload[offset++] = (byte)0;
+
+ Array.Copy(icon, 0, payload, DevName.Length + 12, icon.Length);
+
+ return Send(PacketType.PT_HELO, payload);
+
+ }
+
+ public bool SendHelo(string DevName)
+ {
+ return SendHelo(DevName, IconType.ICON_NONE, "");
+ }
+
+ /************************************************************************/
+ /* SendNotification - Payload format */
+ /* %s - caption */
+ /* %s - message */
+ /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */
+ /* %d - reserved ( 0 ) */
+ /* XX - imagedata ( can span multiple packets ) */
+ /************************************************************************/
+ public bool SendNotification(string Caption, string Message, IconType IconType, string IconFile)
+ {
+
+ byte[] icon = new byte[0];
+ if (IconType != IconType.ICON_NONE)
+ icon = File.ReadAllBytes(IconFile);
+
+ byte[] payload = new byte[Caption.Length + Message.Length + 7 + icon.Length];
+
+ int offset = 0;
+
+ for (int i = 0; i < Caption.Length; i++)
+ payload[offset++] = (byte)Caption[i];
+ payload[offset++] = (byte)'\0';
+
+ for (int i = 0; i < Message.Length; i++)
+ payload[offset++] = (byte)Message[i];
+ payload[offset++] = (byte)'\0';
+
+ payload[offset++] = (byte)IconType;
+
+ for (int i = 0; i < 4; i++)
+ payload[offset++] = (byte)0;
+
+ Array.Copy(icon, 0, payload, Caption.Length + Message.Length + 7, icon.Length);
+
+ return Send(PacketType.PT_NOTIFICATION, payload);
+
+ }
+
+ public bool SendNotification(string Caption, string Message)
+ {
+ return SendNotification(Caption, Message, IconType.ICON_NONE, "");
+ }
+
+ /************************************************************************/
+ /* SendButton - Payload format */
+ /* %i - button code */
+ /* %i - flags 0x01 => use button map/name instead of code */
+ /* 0x02 => btn down */
+ /* 0x04 => btn up */
+ /* 0x08 => use amount */
+ /* 0x10 => queue event */
+ /* 0x20 => do not repeat */
+ /* 0x40 => virtual key */
+ /* 0x80 => axis key */
+ /* %i - amount ( 0 => 65k maps to -1 => 1 ) */
+ /* %s - device map (case sensitive and required if flags & 0x01) */
+ /* "KB" - Standard keyboard map */
+ /* "XG" - Xbox Gamepad */
+ /* "R1" - Xbox Remote */
+ /* "R2" - Xbox Universal Remote */
+ /* "LI:devicename" - valid LIRC device map where 'devicename' */
+ /* is the actual name of the LIRC device */
+ /* "JS<num>:joyname" - valid Joystick device map where */
+ /* 'joyname' is the name specified in */
+ /* the keymap. JS only supports button code */
+ /* and not button name currently (!0x01). */
+ /* %s - button name (required if flags & 0x01) */
+ /************************************************************************/
+ private bool SendButton(string Button, ushort ButtonCode, string DeviceMap, ButtonFlagsType Flags, short Amount)
+ {
+
+ if (Button.Length != 0)
+ {
+ if ((Flags & ButtonFlagsType.BTN_USE_NAME) == 0)
+ Flags |= ButtonFlagsType.BTN_USE_NAME;
+ ButtonCode = 0;
+ }
+ else
+ Button = "";
+
+ if (Amount > 0)
+ {
+ if ((Flags & ButtonFlagsType.BTN_USE_AMOUNT) == 0)
+ Flags |= ButtonFlagsType.BTN_USE_AMOUNT;
+ }
+
+ if ((Flags & ButtonFlagsType.BTN_DOWN) == 0 && (Flags & ButtonFlagsType.BTN_UP) == 0)
+ Flags |= ButtonFlagsType.BTN_DOWN;
+
+ byte[] payload = new byte[Button.Length + DeviceMap.Length + 8];
+
+ int offset = 0;
+
+ payload[offset++] = (byte)((ButtonCode & 0xff00) >> 8);
+ payload[offset++] = (byte)(ButtonCode & 0x00ff);
+
+ payload[offset++] = (byte)(((ushort)Flags & 0xff00) >> 8);
+ payload[offset++] = (byte)((ushort)Flags & 0x00ff);
+
+ payload[offset++] = (byte)((Amount & 0xff00) >> 8);
+ payload[offset++] = (byte)(Amount & 0x00ff);
+
+ for (int i = 0; i < DeviceMap.Length; i++)
+ payload[offset++] = (byte)DeviceMap[i];
+ payload[offset++] = (byte)'\0';
+
+ for (int i = 0; i < Button.Length; i++)
+ payload[offset++] = (byte)Button[i];
+ payload[offset++] = (byte)'\0';
+
+ return Send(PacketType.PT_BUTTON, payload);
+
+ }
+
+ public bool SendButton(string Button, string DeviceMap, ButtonFlagsType Flags, short Amount)
+ {
+ return SendButton(Button, 0, DeviceMap, Flags, Amount);
+ }
+
+ public bool SendButton(string Button, string DeviceMap, ButtonFlagsType Flags)
+ {
+ return SendButton(Button, 0, DeviceMap, Flags, 0);
+ }
+
+ public bool SendButton(ushort ButtonCode, string DeviceMap, ButtonFlagsType Flags, short Amount)
+ {
+ return SendButton("", ButtonCode, DeviceMap, Flags, Amount);
+ }
+
+ public bool SendButton(ushort ButtonCode, string DeviceMap, ButtonFlagsType Flags)
+ {
+ return SendButton("", ButtonCode, DeviceMap, Flags, 0);
+ }
+
+ public bool SendButton(ushort ButtonCode, ButtonFlagsType Flags, short Amount)
+ {
+ return SendButton("", ButtonCode, "", Flags, Amount);
+ }
+
+ public bool SendButton(ushort ButtonCode, ButtonFlagsType Flags)
+ {
+ return SendButton("", ButtonCode, "", Flags, 0);
+ }
+
+ public bool SendButton()
+ {
+ return SendButton("", 0, "", ButtonFlagsType.BTN_UP, 0);
+ }
+
+ /************************************************************************/
+ /* SendPing - No payload */
+ /************************************************************************/
+ public bool SendPing()
+ {
+ byte[] payload = new byte[0];
+ return Send(PacketType.PT_PING, payload);
+ }
+
+ /************************************************************************/
+ /* SendBye - No payload */
+ /************************************************************************/
+ public bool SendBye()
+ {
+ byte[] payload = new byte[0];
+ return Send(PacketType.PT_BYE, payload);
+ }
+
+ /************************************************************************/
+ /* SendMouse - Payload format */
+ /* %c - flags */
+ /* - 0x01 absolute position */
+ /* %i - mousex (0-65535 => maps to screen width) */
+ /* %i - mousey (0-65535 => maps to screen height) */
+ /************************************************************************/
+ public bool SendMouse(ushort X, ushort Y, MouseFlagsType Flags)
+ {
+
+ byte[] payload = new byte[9];
+
+ int offset = 0;
+
+ payload[offset++] = (byte)Flags;
+
+ payload[offset++] = (byte)((X & 0xff00) >> 8);
+ payload[offset++] = (byte)(X & 0x00ff);
+
+ payload[offset++] = (byte)((Y & 0xff00) >> 8);
+ payload[offset++] = (byte)(Y & 0x00ff);
+
+ return Send(PacketType.PT_MOUSE, payload);
+
+ }
+
+ public bool SendMouse(ushort X, ushort Y)
+ {
+ return SendMouse(X, Y, MouseFlagsType.MS_ABSOLUTE);
+ }
+
+ /************************************************************************/
+ /* SendLog - Payload format */
+ /* %c - log type */
+ /* %s - message */
+ /************************************************************************/
+ public bool SendLog(LogTypeEnum LogLevel, string Message)
+ {
+
+ byte[] payload = new byte[Message.Length + 2];
+
+ int offset = 0;
+
+ payload[offset++] = (byte)LogLevel;
+
+ for (int i = 0; i < Message.Length; i++)
+ payload[offset++] = (byte)Message[i];
+ payload[offset++] = (byte)'\0';
+
+ return Send(PacketType.PT_LOG, payload);
+
+ }
+
+ /************************************************************************/
+ /* SendAction - Payload format */
+ /* %c - action type */
+ /* %s - action message */
+ /************************************************************************/
+ public bool SendAction(ActionType Action, string Message)
+ {
+
+ byte[] payload = new byte[Message.Length + 2];
+
+ int offset = 0;
+
+ payload[offset++] = (byte)Action;
+
+ for (int i = 0; i < Message.Length; i++)
+ payload[offset++] = (byte)Message[i];
+ payload[offset++] = (byte)'\0';
+
+ return Send(PacketType.PT_ACTION, payload);
+
+ }
+
+ public bool SendAction(string Message)
+ {
+ return SendAction(ActionType.ACTION_EXECBUILTIN, Message);
+ }
+
+ }
+}
diff --git a/tools/EventClients/lib/c++/xbmcclient.h b/tools/EventClients/lib/c++/xbmcclient.h
new file mode 100644
index 0000000..ef9afc5
--- /dev/null
+++ b/tools/EventClients/lib/c++/xbmcclient.h
@@ -0,0 +1,823 @@
+/*
+ * Copyright (C) 2008-2015 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Kodi; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#endif
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <time.h>
+
+#define STD_PORT 9777
+
+#define MS_ABSOLUTE 0x01
+//#define MS_RELATIVE 0x02
+
+#define BTN_USE_NAME 0x01
+#define BTN_DOWN 0x02
+#define BTN_UP 0x04
+#define BTN_USE_AMOUNT 0x08
+#define BTN_QUEUE 0x10
+#define BTN_NO_REPEAT 0x20
+#define BTN_VKEY 0x40
+#define BTN_AXIS 0x80
+
+#define PT_HELO 0x01
+#define PT_BYE 0x02
+#define PT_BUTTON 0x03
+#define PT_MOUSE 0x04
+#define PT_PING 0x05
+#define PT_BROADCAST 0x06
+#define PT_NOTIFICATION 0x07
+#define PT_BLOB 0x08
+#define PT_LOG 0x09
+#define PT_ACTION 0x0A
+#define PT_DEBUG 0xFF
+
+#define ICON_NONE 0x00
+#define ICON_JPEG 0x01
+#define ICON_PNG 0x02
+#define ICON_GIF 0x03
+
+#define MAX_PACKET_SIZE 1024
+#define HEADER_SIZE 32
+#define MAX_PAYLOAD_SIZE (MAX_PACKET_SIZE - HEADER_SIZE)
+
+#define MAJOR_VERSION 2
+#define MINOR_VERSION 0
+
+#define LOGDEBUG 0
+#define LOGINFO 1
+#define LOGNOTICE 2
+#define LOGWARNING 3
+#define LOGERROR 4
+#define LOGSEVERE 5
+#define LOGFATAL 6
+#define LOGNONE 7
+
+#define ACTION_EXECBUILTIN 0x01
+#define ACTION_BUTTON 0x02
+
+class CAddress
+{
+private:
+ struct sockaddr_in m_Addr;
+public:
+ CAddress(int Port = STD_PORT)
+ {
+ m_Addr.sin_family = AF_INET;
+ m_Addr.sin_port = htons(Port);
+ m_Addr.sin_addr.s_addr = INADDR_ANY;
+ memset(m_Addr.sin_zero, '\0', sizeof m_Addr.sin_zero);
+ }
+
+ CAddress(const char *Address, int Port = STD_PORT)
+ {
+ m_Addr.sin_port = htons(Port);
+
+ struct hostent *h;
+ if (Address == NULL || (h=gethostbyname(Address)) == NULL)
+ {
+ if (Address != NULL)
+ printf("Error: Get host by name\n");
+
+ m_Addr.sin_addr.s_addr = INADDR_ANY;
+ m_Addr.sin_family = AF_INET;
+ }
+ else
+ {
+ m_Addr.sin_family = h->h_addrtype;
+ m_Addr.sin_addr = *((struct in_addr *)h->h_addr);
+ }
+ memset(m_Addr.sin_zero, '\0', sizeof m_Addr.sin_zero);
+ }
+
+ void SetPort(int port)
+ {
+ m_Addr.sin_port = htons(port);
+ }
+
+ const sockaddr *GetAddress()
+ {
+ return ((struct sockaddr *)&m_Addr);
+ }
+
+ bool Bind(int Sockfd)
+ {
+ return (bind(Sockfd, (struct sockaddr *)&m_Addr, sizeof m_Addr) == 0);
+ }
+};
+
+class XBMCClientUtils
+{
+public:
+ XBMCClientUtils() = default;
+ ~XBMCClientUtils() = default;
+ static unsigned int GetUniqueIdentifier()
+ {
+ static time_t id = time(NULL);
+ return id;
+ }
+
+ static void Clean()
+ {
+ #ifdef _WIN32
+ WSACleanup();
+ #endif
+ }
+
+ static bool Initialize()
+ {
+ #ifdef _WIN32
+ WSADATA wsaData;
+ if (WSAStartup(MAKEWORD(1, 1), &wsaData))
+ return false;
+ #endif
+ return true;
+ }
+};
+
+class CPacket
+{
+/* Base class that implements a single event packet.
+
+ - Generic packet structure (maximum 1024 bytes per packet)
+ - Header is 32 bytes long, so 992 bytes available for payload
+ - large payloads can be split into multiple packets using H4 and H5
+ H5 should contain total no. of packets in such a case
+ - H6 contains length of P1, which is limited to 992 bytes
+ - if H5 is 0 or 1, then H4 will be ignored (single packet msg)
+ - H7 must be set to zeros for now
+
+ -----------------------------
+ | -H1 Signature ("XBMC") | - 4 x CHAR 4B
+ | -H2 Version (eg. 2.0) | - 2 x UNSIGNED CHAR 2B
+ | -H3 PacketType | - 1 x UNSIGNED SHORT 2B
+ | -H4 Sequence number | - 1 x UNSIGNED LONG 4B
+ | -H5 No. of packets in msg | - 1 x UNSIGNED LONG 4B
+ | -H6 Payload size | - 1 x UNSIGNED SHORT 2B
+ | -H7 Client's unique token | - 1 x UNSIGNED LONG 4B
+ | -H8 Reserved | - 10 x UNSIGNED CHAR 10B
+ |---------------------------|
+ | -P1 payload | -
+ -----------------------------
+*/
+public:
+ CPacket()
+ {
+ m_PacketType = 0;
+ }
+ virtual ~CPacket() = default;
+
+ bool Send(int Socket, CAddress &Addr, unsigned int UID = XBMCClientUtils::GetUniqueIdentifier())
+ {
+ if (m_Payload.empty())
+ ConstructPayload();
+ bool SendSuccessful = true;
+ int NbrOfPackages = (m_Payload.size() / MAX_PAYLOAD_SIZE) + 1;
+ int Send = 0;
+ int Sent = 0;
+ int Left = m_Payload.size();
+ for (int Package = 1; Package <= NbrOfPackages; Package++)
+ {
+ if (Left > MAX_PAYLOAD_SIZE)
+ {
+ Send = MAX_PAYLOAD_SIZE;
+ Left -= Send;
+ }
+ else
+ {
+ Send = Left;
+ Left = 0;
+ }
+
+ ConstructHeader(m_PacketType, NbrOfPackages, Package, Send, UID, m_Header);
+ char t[MAX_PACKET_SIZE];
+ int i, j;
+ for (i = 0; i < 32; i++)
+ t[i] = m_Header[i];
+
+ for (j = 0; j < Send; j++)
+ t[(32 + j)] = m_Payload[j + Sent];
+
+ int rtn = sendto(Socket, t, (32 + Send), 0, Addr.GetAddress(), sizeof(struct sockaddr));
+
+ if (rtn != (32 + Send))
+ SendSuccessful = false;
+
+ Sent += Send;
+ }
+ return SendSuccessful;
+ }
+protected:
+ char m_Header[HEADER_SIZE];
+ unsigned short m_PacketType;
+
+ std::vector<char> m_Payload;
+
+ static void ConstructHeader(int PacketType, int NumberOfPackets, int CurrentPacket, unsigned short PayloadSize, unsigned int UniqueToken, char *Header)
+ {
+ sprintf(Header, "XBMC");
+ for (int i = 4; i < HEADER_SIZE; i++)
+ Header[i] = 0;
+ Header[4] = MAJOR_VERSION;
+ Header[5] = MINOR_VERSION;
+ if (CurrentPacket == 1)
+ {
+ Header[6] = ((PacketType & 0xff00) >> 8);
+ Header[7] = (PacketType & 0x00ff);
+ }
+ else
+ {
+ Header[6] = ((PT_BLOB & 0xff00) >> 8);
+ Header[7] = (PT_BLOB & 0x00ff);
+ }
+ Header[8] = ((CurrentPacket & 0xff000000) >> 24);
+ Header[9] = ((CurrentPacket & 0x00ff0000) >> 16);
+ Header[10] = ((CurrentPacket & 0x0000ff00) >> 8);
+ Header[11] = (CurrentPacket & 0x000000ff);
+
+ Header[12] = ((NumberOfPackets & 0xff000000) >> 24);
+ Header[13] = ((NumberOfPackets & 0x00ff0000) >> 16);
+ Header[14] = ((NumberOfPackets & 0x0000ff00) >> 8);
+ Header[15] = (NumberOfPackets & 0x000000ff);
+
+ Header[16] = ((PayloadSize & 0xff00) >> 8);
+ Header[17] = (PayloadSize & 0x00ff);
+
+ Header[18] = ((UniqueToken & 0xff000000) >> 24);
+ Header[19] = ((UniqueToken & 0x00ff0000) >> 16);
+ Header[20] = ((UniqueToken & 0x0000ff00) >> 8);
+ Header[21] = (UniqueToken & 0x000000ff);
+ }
+
+ virtual void ConstructPayload()
+ { }
+};
+
+class CPacketHELO : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %s - device name (max 128 chars) */
+ /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */
+ /* %s - my port ( 0=>not listening ) */
+ /* %d - reserved1 ( 0 ) */
+ /* %d - reserved2 ( 0 ) */
+ /* XX - imagedata ( can span multiple packets ) */
+ /************************************************************************/
+private:
+ std::vector<char> m_DeviceName;
+ unsigned short m_IconType;
+ char *m_IconData;
+ unsigned short m_IconSize;
+public:
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ for (unsigned int i = 0; i < m_DeviceName.size(); i++)
+ m_Payload.push_back(m_DeviceName[i]);
+
+ m_Payload.push_back('\0');
+
+ m_Payload.push_back(m_IconType);
+
+ m_Payload.push_back(0);
+ m_Payload.push_back('\0');
+
+ for (int j = 0; j < 8; j++)
+ m_Payload.push_back(0);
+
+ for (int ico = 0; ico < m_IconSize; ico++)
+ m_Payload.push_back(m_IconData[ico]);
+ }
+
+ CPacketHELO(const char *DevName, unsigned short IconType, const char *IconFile = NULL) : CPacket()
+ {
+ m_PacketType = PT_HELO;
+
+ unsigned int len = strlen(DevName);
+ for (unsigned int i = 0; i < len; i++)
+ m_DeviceName.push_back(DevName[i]);
+
+ m_IconType = IconType;
+
+ if (IconType == ICON_NONE || IconFile == NULL)
+ {
+ m_IconData = NULL;
+ m_IconSize = 0;
+ return;
+ }
+
+ std::ifstream::pos_type size;
+
+ std::ifstream file (IconFile, std::ios::in|std::ios::binary|std::ios::ate);
+ if (file.is_open())
+ {
+ size = file.tellg();
+ m_IconData = new char [size];
+ file.seekg (0, std::ios::beg);
+ file.read (m_IconData, size);
+ file.close();
+ m_IconSize = size;
+ }
+ else
+ {
+ m_IconType = ICON_NONE;
+ m_IconSize = 0;
+ }
+ }
+
+ ~CPacketHELO() override
+ {
+ m_DeviceName.clear();
+ delete[] m_IconData;
+ }
+};
+
+class CPacketNOTIFICATION : public CPacket
+{
+ /************************************************************************/
+ /* Payload format: */
+ /* %s - caption */
+ /* %s - message */
+ /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */
+ /* %d - reserved ( 0 ) */
+ /* XX - imagedata ( can span multiple packets ) */
+ /************************************************************************/
+private:
+ std::vector<char> m_Title;
+ std::vector<char> m_Message;
+ unsigned short m_IconType;
+ char *m_IconData;
+ unsigned short m_IconSize;
+public:
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ for (unsigned int i = 0; i < m_Title.size(); i++)
+ m_Payload.push_back(m_Title[i]);
+
+ m_Payload.push_back('\0');
+
+ for (unsigned int i = 0; i < m_Message.size(); i++)
+ m_Payload.push_back(m_Message[i]);
+
+ m_Payload.push_back('\0');
+
+ m_Payload.push_back(m_IconType);
+
+ for (int i = 0; i < 4; i++)
+ m_Payload.push_back(0);
+
+ for (int ico = 0; ico < m_IconSize; ico++)
+ m_Payload.push_back(m_IconData[ico]);
+ }
+
+ CPacketNOTIFICATION(const char *Title, const char *Message, unsigned short IconType, const char *IconFile = NULL) : CPacket()
+ {
+ m_PacketType = PT_NOTIFICATION;
+ m_IconData = NULL;
+ m_IconSize = 0;
+ unsigned int len = 0;
+ if (Title != NULL)
+ {
+ len = strlen(Title);
+ for (unsigned int i = 0; i < len; i++)
+ m_Title.push_back(Title[i]);
+ }
+
+ if (Message != NULL)
+ {
+ len = strlen(Message);
+ for (unsigned int i = 0; i < len; i++)
+ m_Message.push_back(Message[i]);
+ }
+ m_IconType = IconType;
+
+ if (IconType == ICON_NONE || IconFile == NULL)
+ return;
+
+ std::ifstream::pos_type size;
+
+ std::ifstream file (IconFile, std::ios::in|std::ios::binary|std::ios::ate);
+ if (file.is_open())
+ {
+ size = file.tellg();
+ m_IconData = new char [size];
+ file.seekg (0, std::ios::beg);
+ file.read (m_IconData, size);
+ file.close();
+ m_IconSize = size;
+ }
+ else
+ m_IconType = ICON_NONE;
+ }
+
+ ~CPacketNOTIFICATION() override
+ {
+ m_Title.clear();
+ m_Message.clear();
+ delete[] m_IconData;
+ }
+};
+
+class CPacketBUTTON : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %i - button code */
+ /* %i - flags 0x01 => use button map/name instead of code */
+ /* 0x02 => btn down */
+ /* 0x04 => btn up */
+ /* 0x08 => use amount */
+ /* 0x10 => queue event */
+ /* 0x20 => do not repeat */
+ /* 0x40 => virtual key */
+ /* 0x40 => axis key */
+ /* %i - amount ( 0 => 65k maps to -1 => 1 ) */
+ /* %s - device map (case sensitive and required if flags & 0x01) */
+ /* "KB" - Standard keyboard map */
+ /* "XG" - Xbox Gamepad */
+ /* "R1" - Xbox Remote */
+ /* "R2" - Xbox Universal Remote */
+ /* "LI:devicename" - valid LIRC device map where 'devicename' */
+ /* is the actual name of the LIRC device */
+ /* "JS<num>:joyname" - valid Joystick device map where */
+ /* 'joyname' is the name specified in */
+ /* the keymap. JS only supports button code */
+ /* and not button name currently (!0x01). */
+ /* %s - button name (required if flags & 0x01) */
+ /************************************************************************/
+private:
+ std::vector<char> m_DeviceMap;
+ std::vector<char> m_Button;
+ unsigned short m_ButtonCode;
+ unsigned short m_Amount;
+ unsigned short m_Flags;
+public:
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ if (m_Button.size() != 0)
+ {
+ if (!(m_Flags & BTN_USE_NAME)) // If the BTN_USE_NAME isn't flagged for some reason
+ m_Flags |= BTN_USE_NAME;
+ m_ButtonCode = 0;
+ }
+ else
+ m_Button.clear();
+
+ if (m_Amount > 0)
+ {
+ if (!(m_Flags & BTN_USE_AMOUNT))
+ m_Flags |= BTN_USE_AMOUNT;
+ }
+ if (!((m_Flags & BTN_DOWN) || (m_Flags & BTN_UP))) //If none of them are tagged.
+ m_Flags |= BTN_DOWN;
+
+ m_Payload.push_back(((m_ButtonCode & 0xff00) >> 8));
+ m_Payload.push_back( (m_ButtonCode & 0x00ff));
+
+ m_Payload.push_back(((m_Flags & 0xff00) >> 8) );
+ m_Payload.push_back( (m_Flags & 0x00ff));
+
+ m_Payload.push_back(((m_Amount & 0xff00) >> 8) );
+ m_Payload.push_back( (m_Amount & 0x00ff));
+
+
+ for (unsigned int i = 0; i < m_DeviceMap.size(); i++)
+ m_Payload.push_back(m_DeviceMap[i]);
+
+ m_Payload.push_back('\0');
+
+ for (unsigned int i = 0; i < m_Button.size(); i++)
+ m_Payload.push_back(m_Button[i]);
+
+ m_Payload.push_back('\0');
+ }
+
+ CPacketBUTTON(const char *Button, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) : CPacket()
+ {
+ m_PacketType = PT_BUTTON;
+ m_Flags = Flags;
+ m_ButtonCode = 0;
+ m_Amount = Amount;
+
+ unsigned int len = strlen(DeviceMap);
+ for (unsigned int i = 0; i < len; i++)
+ m_DeviceMap.push_back(DeviceMap[i]);
+
+ len = strlen(Button);
+ for (unsigned int i = 0; i < len; i++)
+ m_Button.push_back(Button[i]);
+ }
+
+ CPacketBUTTON(unsigned short ButtonCode, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) : CPacket()
+ {
+ m_PacketType = PT_BUTTON;
+ m_Flags = Flags;
+ m_ButtonCode = ButtonCode;
+ m_Amount = Amount;
+
+ unsigned int len = strlen(DeviceMap);
+ for (unsigned int i = 0; i < len; i++)
+ m_DeviceMap.push_back(DeviceMap[i]);
+ }
+
+ CPacketBUTTON(unsigned short ButtonCode, unsigned short Flags, unsigned short Amount = 0) : CPacket()
+ {
+ m_PacketType = PT_BUTTON;
+ m_Flags = Flags;
+ m_ButtonCode = ButtonCode;
+ m_Amount = Amount;
+ }
+
+ // Used to send a release event
+ CPacketBUTTON() : CPacket()
+ {
+ m_PacketType = PT_BUTTON;
+ m_Flags = BTN_UP;
+ m_Amount = 0;
+ m_ButtonCode = 0;
+ }
+
+ ~CPacketBUTTON() override
+ {
+ m_DeviceMap.clear();
+ m_Button.clear();
+ }
+
+ inline unsigned short GetFlags() { return m_Flags; }
+ inline unsigned short GetButtonCode() { return m_ButtonCode; }
+};
+
+class CPacketPING : public CPacket
+{
+ /************************************************************************/
+ /* no payload */
+ /************************************************************************/
+public:
+ CPacketPING() : CPacket()
+ {
+ m_PacketType = PT_PING;
+ }
+ ~CPacketPING() override = default;
+};
+
+class CPacketBYE : public CPacket
+{
+ /************************************************************************/
+ /* no payload */
+ /************************************************************************/
+public:
+ CPacketBYE() : CPacket()
+ {
+ m_PacketType = PT_BYE;
+ }
+ ~CPacketBYE() override = default;
+};
+
+class CPacketMOUSE : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %c - flags */
+ /* - 0x01 absolute position */
+ /* %i - mousex (0-65535 => maps to screen width) */
+ /* %i - mousey (0-65535 => maps to screen height) */
+ /************************************************************************/
+private:
+ unsigned short m_X;
+ unsigned short m_Y;
+ unsigned char m_Flag;
+public:
+ CPacketMOUSE(int X, int Y, unsigned char Flag = MS_ABSOLUTE)
+ {
+ m_PacketType = PT_MOUSE;
+ m_Flag = Flag;
+ m_X = X;
+ m_Y = Y;
+ }
+
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ m_Payload.push_back(m_Flag);
+
+ m_Payload.push_back(((m_X & 0xff00) >> 8));
+ m_Payload.push_back( (m_X & 0x00ff));
+
+ m_Payload.push_back(((m_Y & 0xff00) >> 8));
+ m_Payload.push_back( (m_Y & 0x00ff));
+ }
+
+ ~CPacketMOUSE() override = default;
+};
+
+class CPacketLOG : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %c - log type */
+ /* %s - message */
+ /************************************************************************/
+private:
+ std::vector<char> m_Message;
+ unsigned char m_LogLevel;
+ bool m_AutoPrintf;
+public:
+ CPacketLOG(int LogLevel, const char *Message, bool AutoPrintf = true)
+ {
+ m_PacketType = PT_LOG;
+
+ unsigned int len = strlen(Message);
+ for (unsigned int i = 0; i < len; i++)
+ m_Message.push_back(Message[i]);
+
+ m_LogLevel = LogLevel;
+ m_AutoPrintf = AutoPrintf;
+ }
+
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ m_Payload.push_back( (m_LogLevel & 0x00ff) );
+
+ if (m_AutoPrintf)
+ {
+ char* str=&m_Message[0];
+ printf("%s\n", str);
+ }
+ for (unsigned int i = 0; i < m_Message.size(); i++)
+ m_Payload.push_back(m_Message[i]);
+
+ m_Payload.push_back('\0');
+ }
+
+ ~CPacketLOG() override = default;
+};
+
+class CPacketACTION : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %c - action type */
+ /* %s - action message */
+ /************************************************************************/
+private:
+ unsigned char m_ActionType;
+ std::vector<char> m_Action;
+public:
+ CPacketACTION(const char *Action, unsigned char ActionType = ACTION_EXECBUILTIN)
+ {
+ m_PacketType = PT_ACTION;
+
+ m_ActionType = ActionType;
+ unsigned int len = strlen(Action);
+ for (unsigned int i = 0; i < len; i++)
+ m_Action.push_back(Action[i]);
+ }
+
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ m_Payload.push_back(m_ActionType);
+ for (unsigned int i = 0; i < m_Action.size(); i++)
+ m_Payload.push_back(m_Action[i]);
+
+ m_Payload.push_back('\0');
+ }
+
+ ~CPacketACTION() override = default;
+};
+
+class CXBMCClient
+{
+private:
+ CAddress m_Addr;
+ int m_Socket;
+ unsigned int m_UID;
+public:
+ CXBMCClient(const char *IP = "127.0.0.1", int Port = 9777, int Socket = -1, unsigned int UID = 0)
+ {
+ m_Addr = CAddress(IP, Port);
+ if (Socket == -1)
+ m_Socket = socket(AF_INET, SOCK_DGRAM, 0);
+ else
+ m_Socket = Socket;
+
+ if (UID)
+ m_UID = UID;
+ else
+ m_UID = XBMCClientUtils::GetUniqueIdentifier();
+ }
+
+ void SendNOTIFICATION(const char *Title, const char *Message, unsigned short IconType, const char *IconFile = NULL)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketNOTIFICATION notification(Title, Message, IconType, IconFile);
+ notification.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendHELO(const char *DevName, unsigned short IconType, const char *IconFile = NULL)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketHELO helo(DevName, IconType, IconFile);
+ helo.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendButton(const char *Button, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketBUTTON button(Button, DeviceMap, Flags, Amount);
+ button.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendButton(unsigned short ButtonCode, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketBUTTON button(ButtonCode, DeviceMap, Flags, Amount);
+ button.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendButton(unsigned short ButtonCode, unsigned Flags, unsigned short Amount = 0)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketBUTTON button(ButtonCode, Flags, Amount);
+ button.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendMOUSE(int X, int Y, unsigned char Flag = MS_ABSOLUTE)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketMOUSE mouse(X, Y, Flag);
+ mouse.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendLOG(int LogLevel, const char *Message, bool AutoPrintf = true)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketLOG log(LogLevel, Message, AutoPrintf);
+ log.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendACTION(const char *ActionMessage, int ActionType = ACTION_EXECBUILTIN)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketACTION action(ActionMessage, ActionType);
+ action.Send(m_Socket, m_Addr, m_UID);
+ }
+};
+
diff --git a/tools/EventClients/lib/java/build.xml b/tools/EventClients/lib/java/build.xml
new file mode 100644
index 0000000..fe25bde
--- /dev/null
+++ b/tools/EventClients/lib/java/build.xml
@@ -0,0 +1,72 @@
+<project default="jar" name="JXBMCEventClient">
+ <description description="JXBMCEventClient"/>
+ <target name="init">
+ <tstamp/>
+ <property name="srcdir" value="${basedir}/src"/>
+ <property name="classdir" value="${basedir}/classes"/>
+ <property name="apidir" value="${basedir}/doc/api"/>
+ <property name="libdir" value="/usr/local/share/java/classes"/>
+ <property name="projectname" value="JXBMCEventClient"/>
+ <property name="jarfile" value="${projectname}.jar"/>
+ <property name="distdir" value="${basedir}/../dist"/>
+ <fileset id="eventclient.files" dir="${classdir}" includes="**/*"/>
+ <path id="classpath">
+ <pathelement location="${libdir}/junit.jar" />
+ </path>
+ </target>
+
+
+ <target name="jar" depends="compile">
+ <jar jarfile="${jarfile}" index="true">
+ <fileset refid="eventclient.files"/>
+ </jar>
+ </target>
+
+ <target name="dist" depends="jar, javadoc">
+ <fail unless="version">use: ant dist -Dversion=x.x</fail>
+ <mkdir dir="${distdir}"/>
+ <copy todir="${distdir}/doc">
+ <fileset dir="${apidir}"/>
+ </copy>
+ <property name="filename" value="${projectname}-${version}"/>
+ <copy file="${jarfile}" tofile="${distdir}/${projectname}-${version}.jar" />
+ <tar destfile="${distdir}/${filename}.tar.gz" compression="gzip">
+ <tarfileset dir="${basedir}" prefix="${filename}">
+ <exclude name="classes/**"/>
+ <exclude name="**/CVS"/>
+ <exclude name="**/.*"/>
+ <exclude name="${jarfile}"/>
+ <exclude name="doc/**"/>
+ </tarfileset>
+ </tar>
+ </target>
+
+ <target name="compile" depends="init" description="Compiles all classes">
+ <mkdir dir="${classdir}"/>
+ <javac debug="yes" deprecation="true" destdir="${classdir}" srcdir="${srcdir}" classpathref="classpath"/>
+ </target>
+
+ <target name="javadoc" depends="init">
+ <mkdir dir="${apidir}"/>
+ <javadoc
+ packagenames="org.xbmc.eventclient.*"
+ sourcepath="${srcdir}"
+ defaultexcludes="yes"
+ destdir="${apidir}"
+ author="true"
+ version="true"
+ use="true"
+ private="false"
+ windowtitle="${projectname} API"
+ classpathref="classpath">
+ <link href="http://java.sun.com/j2se/1.4.2/docs/api/"/>
+ </javadoc>
+ </target>
+
+ <target name="clean" depends="init" description="cleans all classes and jars">
+ <delete dir="${classdir}"/>
+ <delete dir="${apidir}"/>
+ <delete file="${jarfile}"/>
+ </target>
+
+</project>
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/Packet.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/Packet.java
new file mode 100644
index 0000000..09507cb
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/Packet.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+
+/**
+ * XBMC Event Client Class
+ * <p>
+ * Implementation of XBMC's UDP based input system.
+ * A set of classes that abstract the various packets that the event server
+ * currently supports. In addition, there's also a class, XBMCClient, that
+ * provides functions that sends the various packets. Use XBMCClient if you
+ * don't need complete control over packet structure.
+ * </p>
+ * <p>
+ * The basic workflow involves:
+ * <ol>
+ * <li>Send a HELO packet</li>
+ * <li>Send x number of valid packets</li>
+ * <li>Send a BYE packet</li>
+ * </ol>
+ * </p>
+ * <p>
+ * IMPORTANT NOTE ABOUT TIMEOUTS:
+ * A client is considered to be timed out if XBMC doesn't received a packet
+ * at least once every 60 seconds. To "ping" XBMC with an empty packet use
+ * PacketPING or XBMCClient.ping(). See the documentation for details.
+ * </p>
+ * <p>
+ * Base class that implements a single event packet.
+ * - Generic packet structure (maximum 1024 bytes per packet)
+ * - Header is 32 bytes long, so 992 bytes available for payload
+ * - large payloads can be split into multiple packets using H4 and H5
+ * H5 should contain total no. of packets in such a case
+ * - H6 contains length of P1, which is limited to 992 bytes
+ * - if H5 is 0 or 1, then H4 will be ignored (single packet msg)
+ * - H7 must be set to zeros for now
+ * </p>
+ * <pre>
+ * -----------------------------
+ * | -H1 Signature ("XBMC") | - 4 x CHAR 4B
+ * | -H2 Version (eg. 2.0) | - 2 x UNSIGNED CHAR 2B
+ * | -H3 PacketType | - 1 x UNSIGNED SHORT 2B
+ * | -H4 Sequence number | - 1 x UNSIGNED LONG 4B
+ * | -H5 No. of packets in msg | - 1 x UNSIGNED LONG 4B
+ * | -H6 Payloadsize of packet | - 1 x UNSIGNED SHORT 2B
+ * | -H7 Client's unique token | - 1 x UNSIGNED LONG 4B
+ * | -H8 Reserved | - 10 x UNSIGNED CHAR 10B
+ * |---------------------------|
+ * | -P1 payload | -
+ * -----------------------------
+ * </pre>
+ * @author Stefan Agner
+ *
+ */
+public abstract class Packet {
+
+ private byte[] sig;
+ private byte[] payload = new byte[0];
+ private byte minver;
+ private byte majver;
+
+ private short packettype;
+
+
+ private final static short MAX_PACKET_SIZE = 1024;
+ private final static short HEADER_SIZE = 32;
+ private final static short MAX_PAYLOAD_SIZE = MAX_PACKET_SIZE - HEADER_SIZE;
+
+ protected final static byte PT_HELO = 0x01;
+ protected final static byte PT_BYE = 0x02;
+ protected final static byte PT_BUTTON = 0x03;
+ protected final static byte PT_MOUSE = 0x04;
+ protected final static byte PT_PING = 0x05;
+ protected final static byte PT_BROADCAST = 0x06;
+ protected final static byte PT_NOTIFICATION = 0x07;
+ protected final static byte PT_BLOB = 0x08;
+ protected final static byte PT_LOG = 0x09;
+ protected final static byte PT_ACTION = 0x0A;
+ protected final static byte PT_DEBUG = (byte)0xFF;
+
+ public final static byte ICON_NONE = 0x00;
+ public final static byte ICON_JPEG = 0x01;
+ public final static byte ICON_PNG = 0x02;
+ public final static byte ICON_GIF = 0x03;
+
+ private static int uid = (int)(Math.random()*Integer.MAX_VALUE);
+
+ /**
+ * This is an Abstract class and cannot be instanced. Please use one of the Packet implementation Classes
+ * (PacketXXX).
+ *
+ * Implements an XBMC Event Client Packet. Type is to be specified at creation time, Payload can be added
+ * with the various appendPayload methods. Packet can be sent through UDP-Socket with method "send".
+ * @param packettype Type of Packet (PT_XXX)
+ */
+ protected Packet(short packettype)
+ {
+ sig = new byte[] {'X', 'B', 'M', 'C' };
+ minver = 0;
+ majver = 2;
+ this.packettype = packettype;
+ }
+
+ /**
+ * Appends a String to the payload (terminated with 0x00)
+ * @param payload Payload as String
+ */
+ protected void appendPayload(String payload)
+ {
+ byte[] payloadarr = payload.getBytes();
+ int oldpayloadsize = this.payload.length;
+ byte[] oldpayload = this.payload;
+ this.payload = new byte[oldpayloadsize+payloadarr.length+1]; // Create new Array with more place (+1 for string terminator)
+ System.arraycopy(oldpayload, 0, this.payload, 0, oldpayloadsize);
+ System.arraycopy(payloadarr, 0, this.payload, oldpayloadsize, payloadarr.length);
+ }
+
+ /**
+ * Appends a single Byte to the payload
+ * @param payload Payload
+ */
+ protected void appendPayload(byte payload)
+ {
+ appendPayload(new byte[] { payload });
+ }
+
+ /**
+ * Appends a Byte-Array to the payload
+ * @param payloadarr Payload
+ */
+ protected void appendPayload(byte[] payloadarr)
+ {
+ int oldpayloadsize = this.payload.length;
+ byte[] oldpayload = this.payload;
+ this.payload = new byte[oldpayloadsize+payloadarr.length];
+ System.arraycopy(oldpayload, 0, this.payload, 0, oldpayloadsize);
+ System.arraycopy(payloadarr, 0, this.payload, oldpayloadsize, payloadarr.length);
+ }
+
+ /**
+ * Appends an integer to the payload
+ * @param i Payload
+ */
+ protected void appendPayload(int i) {
+ appendPayload(intToByteArray(i));
+ }
+
+ /**
+ * Appends a short to the payload
+ * @param s Payload
+ */
+ protected void appendPayload(short s) {
+ appendPayload(shortToByteArray(s));
+ }
+
+ /**
+ * Get Number of Packets which will be sent with current Payload...
+ * @return Number of Packets
+ */
+ public int getNumPackets()
+ {
+ return (int)((payload.length + (MAX_PAYLOAD_SIZE - 1)) / MAX_PAYLOAD_SIZE);
+ }
+
+ /**
+ * Get Header for a specific Packet in this sequence...
+ * @param seq Current sequence number
+ * @param maxseq Maximal sequence number
+ * @param actpayloadsize Payloadsize of this packet
+ * @return Byte-Array with Header information (currently 32-Byte long, see HEADER_SIZE)
+ */
+ private byte[] getHeader(int seq, int maxseq, short actpayloadsize)
+ {
+ byte[] header = new byte[HEADER_SIZE];
+ System.arraycopy(sig, 0, header, 0, 4);
+ header[4] = majver;
+ header[5] = minver;
+ byte[] packettypearr = shortToByteArray(this.packettype);
+ System.arraycopy(packettypearr, 0, header, 6, 2);
+ byte[] seqarr = intToByteArray(seq);
+ System.arraycopy(seqarr, 0, header, 8, 4);
+ byte[] maxseqarr = intToByteArray(maxseq);
+ System.arraycopy(maxseqarr, 0, header, 12, 4);
+ byte[] payloadsize = shortToByteArray(actpayloadsize);
+ System.arraycopy(payloadsize, 0, header, 16, 2);
+ byte[] uid = intToByteArray(Packet.uid);
+ System.arraycopy(uid, 0, header, 18, 4);
+ byte[] reserved = new byte[10];
+ System.arraycopy(reserved, 0, header, 22, 10);
+
+ return header;
+ }
+
+ /**
+ * Generates the whole UDP-Message with Header and Payload of a specific Packet in sequence
+ * @param seq Current sequence number
+ * @return Byte-Array with UDP-Message
+ */
+ private byte[] getUDPMessage(int seq)
+ {
+ int maxseq = (int)((payload.length + (MAX_PAYLOAD_SIZE - 1)) / MAX_PAYLOAD_SIZE);
+ if(seq > maxseq)
+ return null;
+
+ short actpayloadsize;
+
+ if(seq == maxseq)
+ actpayloadsize = (short)(payload.length%MAX_PAYLOAD_SIZE);
+
+ else
+ actpayloadsize = (short)MAX_PAYLOAD_SIZE;
+
+ byte[] pack = new byte[HEADER_SIZE+actpayloadsize];
+
+ System.arraycopy(getHeader(seq, maxseq, actpayloadsize), 0, pack, 0, HEADER_SIZE);
+ System.arraycopy(payload, (seq-1)*MAX_PAYLOAD_SIZE, pack, HEADER_SIZE, actpayloadsize);
+
+ return pack;
+ }
+
+ /**
+ * Sends this packet to the EventServer
+ * @param adr Address of the EventServer
+ * @param port Port of the EventServer
+ * @throws IOException
+ */
+ public void send(InetAddress adr, int port) throws IOException
+ {
+ int maxseq = getNumPackets();
+ DatagramSocket s = new DatagramSocket();
+
+ // For each Packet in Sequence...
+ for(int seq=1;seq<=maxseq;seq++)
+ {
+ // Get Message and send them...
+ byte[] pack = getUDPMessage(seq);
+ DatagramPacket p = new DatagramPacket(pack, pack.length);
+ p.setAddress(adr);
+ p.setPort(port);
+ s.send(p);
+ }
+ }
+
+ /**
+ * Helper Method to convert an integer to a Byte array
+ * @param value
+ * @return Byte-Array
+ */
+ private static final byte[] intToByteArray(int value) {
+ return new byte[] {
+ (byte)(value >>> 24),
+ (byte)(value >>> 16),
+ (byte)(value >>> 8),
+ (byte)value};
+ }
+
+ /**
+ * Helper Method to convert an short to a Byte array
+ * @param value
+ * @return Byte-Array
+ */
+ private static final byte[] shortToByteArray(short value) {
+ return new byte[] {
+ (byte)(value >>> 8),
+ (byte)value};
+ }
+
+
+}
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketACTION.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketACTION.java
new file mode 100644
index 0000000..eb597a2
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketACTION.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+/**
+ * XBMC Event Client Class
+ *
+ * An ACTION packet tells XBMC to do the action specified, based on the type it knows were it needs to be sent.
+ * The idea is that this will be as in scripting/skining and keymapping, just triggered from afar.
+ * @author Stefan Agner
+ *
+ */
+public class PacketACTION extends Packet {
+
+ public final static byte ACTION_EXECBUILTIN = 0x01;
+ public final static byte ACTION_BUTTON = 0x02;
+
+
+ /**
+ * An ACTION packet tells XBMC to do the action specified, based on the type it knows were it needs to be sent.
+ * @param actionmessage Actionmessage (as in scripting/skinning)
+ */
+ public PacketACTION(String actionmessage)
+ {
+ super(PT_ACTION);
+ byte actiontype = ACTION_EXECBUILTIN;
+ appendPayload(actionmessage, actiontype);
+ }
+
+ /**
+ * An ACTION packet tells XBMC to do the action specified, based on the type it knows were it needs to be sent.
+ * @param actionmessage Actionmessage (as in scripting/skinning)
+ * @param actiontype Actiontype (ACTION_EXECBUILTIN or ACTION_BUTTON)
+ */
+ public PacketACTION(String actionmessage, byte actiontype)
+ {
+ super(PT_ACTION);
+ appendPayload(actionmessage, actiontype);
+ }
+
+ private void appendPayload(String actionmessage, byte actiontype)
+ {
+ appendPayload(actiontype);
+ appendPayload(actionmessage);
+ }
+}
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBUTTON.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBUTTON.java
new file mode 100644
index 0000000..de25a2c
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBUTTON.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+/**
+ * XBMC Event Client Class
+ *
+ * A button packet send a key press or release event to XBMC
+ * @author Stefan Agner
+ *
+ */
+public class PacketBUTTON extends Packet {
+
+ protected final static byte BT_USE_NAME = 0x01;
+ protected final static byte BT_DOWN = 0x02;
+ protected final static byte BT_UP = 0x04;
+ protected final static byte BT_USE_AMOUNT = 0x08;
+ protected final static byte BT_QUEUE = 0x10;
+ protected final static byte BT_NO_REPEAT = 0x20;
+ protected final static byte BT_VKEY = 0x40;
+ protected final static byte BT_AXIS = (byte)0x80;
+ protected final static byte BT_AXISSINGLE = (byte)0x100;
+
+ /**
+ * A button packet send a key press or release event to XBMC
+ * @param code raw button code (default: 0)
+ * @param repeat this key press should repeat until released (default: 1)
+ * Note that queued pressed cannot repeat.
+ * @param down if this is 1, it implies a press event, 0 implies a release
+ * event. (default: 1)
+ * @param queue a queued key press means that the button event is
+ * executed just once after which the next key press is processed.
+ * It can be used for macros. Currently there is no support for
+ * time delays between queued presses. (default: 0)
+ * @param amount unimplemented for now; in the future it will be used for
+ * specifying magnitude of analog key press events
+ * @param axis
+ */
+ public PacketBUTTON(short code, boolean repeat, boolean down, boolean queue, short amount, byte axis)
+ {
+ super(PT_BUTTON);
+ String map_name = "";
+ String button_name = "";
+ short flags = 0;
+ appendPayload(code, map_name, button_name, repeat, down, queue, amount, axis, flags);
+ }
+
+ /**
+ * A button packet send a key press or release event to XBMC
+ * @param map_name a combination of map_name and button_name refers to a
+ * mapping in the user's Keymap.xml or Lircmap.xml.
+ * map_name can be one of the following:
+ * <ul>
+ * <li>"KB" => standard keyboard map ( <keyboard> section )</li>
+ * <li>"XG" => xbox gamepad map ( <gamepad> section )</li>
+ * <li>"R1" => xbox remote map ( <remote> section )</li>
+ * <li>"R2" => xbox universal remote map ( <universalremote> section )</li>
+ * <li>"LI:devicename" => LIRC remote map where 'devicename' is the
+ * actual device's name</li></ul>
+ * @param button_name a button name defined in the map specified in map_name.
+ * For example, if map_name is "KB" referring to the <keyboard> section in Keymap.xml
+ * then, valid button_names include "printscreen", "minus", "x", etc.
+ * @param repeat this key press should repeat until released (default: 1)
+ * Note that queued pressed cannot repeat.
+ * @param down if this is 1, it implies a press event, 0 implies a release
+ * event. (default: 1)
+ * @param queue a queued key press means that the button event is
+ * executed just once after which the next key press is processed.
+ * It can be used for macros. Currently there is no support for
+ * time delays between queued presses. (default: 0)
+ * @param amount unimplemented for now; in the future it will be used for
+ * specifying magnitude of analog key press events
+ * @param axis
+ */
+ public PacketBUTTON(String map_name, String button_name, boolean repeat, boolean down, boolean queue, short amount, byte axis)
+ {
+ super(PT_BUTTON);
+ short code = 0;
+ short flags = BT_USE_NAME;
+ appendPayload(code, map_name, button_name, repeat, down, queue, amount, axis, flags);
+ }
+
+ /**
+ * Appends Payload for a Button Packet (this method is used by the different Constructors of this Packet)
+ * @param code raw button code (default: 0)
+ * @param map_name a combination of map_name and button_name refers to a
+ * mapping in the user's Keymap.xml or Lircmap.xml.
+ * map_name can be one of the following:
+ * <ul>
+ * <li>"KB" => standard keyboard map ( <keyboard> section )</li>
+ * <li>"XG" => xbox gamepad map ( <gamepad> section )</li>
+ * <li>"R1" => xbox remote map ( <remote> section )</li>
+ * <li>"R2" => xbox universal remote map ( <universalremote> section )</li>
+ * <li>"LI:devicename" => LIRC remote map where 'devicename' is the
+ * actual device's name</li></ul>
+ * @param button_name a button name defined in the map specified in map_name.
+ * For example, if map_name is "KB" referring to the <keyboard> section in Keymap.xml
+ * then, valid button_names include "printscreen", "minus", "x", etc.
+ * @param repeat this key press should repeat until released (default: 1)
+ * Note that queued pressed cannot repeat.
+ * @param down if this is 1, it implies a press event, 0 implies a release
+ * event. (default: 1)
+ * @param queue a queued key press means that the button event is
+ * executed just once after which the next key press is processed.
+ * It can be used for macros. Currently there is no support for
+ * time delays between queued presses. (default: 0)
+ * @param amount unimplemented for now; in the future it will be used for
+ * specifying magnitude of analog key press events
+ * @param axis
+ * @param flags Packet specific flags
+ */
+ private void appendPayload(short code, String map_name, String button_name, boolean repeat, boolean down, boolean queue, short amount, byte axis, short flags)
+ {
+ if(amount>0)
+ flags |= BT_USE_AMOUNT;
+ else
+ amount = 0;
+
+ if(down)
+ flags |= BT_DOWN;
+ else
+ flags |= BT_UP;
+
+ if(!repeat)
+ flags |= BT_NO_REPEAT;
+
+ if(queue)
+ flags |= BT_QUEUE;
+
+ if(axis == 1)
+ flags |= BT_AXISSINGLE;
+ else if (axis == 2)
+ flags |= BT_AXIS;
+
+
+ appendPayload(code);
+ appendPayload(flags);
+ appendPayload(amount);
+ appendPayload(map_name);
+ appendPayload(button_name);
+ }
+}
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBYE.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBYE.java
new file mode 100644
index 0000000..e63a2c6
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketBYE.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+/**
+ * XBMC Event Client Class
+ *
+ * A BYE packet terminates the connection to XBMC.
+ * @author Stefan Agner
+ *
+ */
+public class PacketBYE extends Packet
+{
+
+ /**
+ * A BYE packet terminates the connection to XBMC.
+ */
+ public PacketBYE()
+ {
+ super(PT_BYE);
+ }
+}
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketHELO.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketHELO.java
new file mode 100644
index 0000000..95e8fa9
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketHELO.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+import java.nio.charset.Charset;
+
+/**
+ * XBMC Event Client Class
+ *
+ * A HELO packet establishes a valid connection to XBMC. It is the
+ * first packet that should be sent.
+ * @author Stefan Agner
+ *
+ */
+public class PacketHELO extends Packet {
+
+
+ /**
+ * A HELO packet establishes a valid connection to XBMC.
+ * @param devicename Name of the device which connects to XBMC
+ */
+ public PacketHELO(String devicename)
+ {
+ super(PT_HELO);
+ this.appendPayload(devicename);
+ this.appendPayload(ICON_NONE);
+ this.appendPayload((short)0); // port no
+ this.appendPayload(0); // reserved1
+ this.appendPayload(0); // reserved2
+ }
+
+ /**
+ * A HELO packet establishes a valid connection to XBMC.
+ * @param devicename Name of the device which connects to XBMC
+ * @param iconType Type of the icon (Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF)
+ * @param iconData The icon as a Byte-Array
+ */
+ public PacketHELO(String devicename, byte iconType, byte[] iconData)
+ {
+ super(PT_HELO);
+ this.appendPayload(devicename);
+ this.appendPayload(iconType);
+ this.appendPayload((short)0); // port no
+ this.appendPayload(0); // reserved1
+ this.appendPayload(0); // reserved2
+ this.appendPayload(iconData); // reserved2
+ }
+
+}
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketLOG.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketLOG.java
new file mode 100644
index 0000000..b0d59bb
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketLOG.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+/**
+ * XBMC Event Client Class
+ *
+ * A LOG packet tells XBMC to log the message to xbmc.log with the loglevel as specified.
+ * @author Stefan Agner
+ *
+ */
+public class PacketLOG extends Packet {
+
+ /**
+ * A LOG packet tells XBMC to log the message to xbmc.log with the loglevel as specified.
+ * @param loglevel the loglevel, follows XBMC standard.
+ * <ul>
+ * <li>0 = DEBUG</li>
+ * <li>1 = INFO</li>
+ * <li>2 = NOTICE</li>
+ * <li>3 = WARNING</li>
+ * <li>4 = ERROR</li>
+ * <li>5 = SEVERE</li>
+ * </ul>
+ * @param logmessage the message to log
+ */
+ public PacketLOG(byte loglevel, String logmessage)
+ {
+ super(PT_LOG);
+ appendPayload(loglevel);
+ appendPayload(logmessage);
+ }
+}
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketMOUSE.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketMOUSE.java
new file mode 100644
index 0000000..816e1a7
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketMOUSE.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+/**
+ * XBMC Event Client Class
+ *
+ * A MOUSE packets sets the mouse position in XBMC
+ * @author Stefan Agner
+ *
+ */
+public class PacketMOUSE extends Packet {
+
+ protected final static byte MS_ABSOLUTE = 0x01;
+
+ /**
+ * A MOUSE packets sets the mouse position in XBMC
+ * @param x horizontal position ranging from 0 to 65535
+ * @param y vertical position ranging from 0 to 65535
+ */
+ public PacketMOUSE(int x, int y)
+ {
+ super(PT_MOUSE);
+ byte flags = 0;
+ flags |= MS_ABSOLUTE;
+ appendPayload(flags);
+ appendPayload((short)x);
+ appendPayload((short)y);
+ }
+}
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketNOTIFICATION.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketNOTIFICATION.java
new file mode 100644
index 0000000..7089ad6
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketNOTIFICATION.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+/**
+ * XBMC Event Client Class
+ *
+ * This packet displays a notification window in XBMC. It can contain
+ * a caption, a message and an icon.
+ * @author Stefan Agner
+ *
+ */
+public class PacketNOTIFICATION extends Packet {
+
+ /**
+ * This packet displays a notification window in XBMC.
+ * @param title Message title
+ * @param message The actual message
+ * @param iconType Type of the icon (Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF)
+ * @param iconData The icon as a Byte-Array
+ */
+ public PacketNOTIFICATION(String title, String message, byte iconType, byte[] iconData)
+ {
+ super(PT_NOTIFICATION);
+ appendPayload(title, message, iconType, iconData);
+ }
+
+ /**
+ * This packet displays a notification window in XBMC.
+ * @param title Message title
+ * @param message The actual message
+ */
+ public PacketNOTIFICATION(String title, String message)
+ {
+ super(PT_NOTIFICATION);
+ appendPayload(title, message, Packet.ICON_NONE, null);
+ }
+
+ /**
+ * Appends the payload to the packet...
+ * @param title Message title
+ * @param message The actual message
+ * @param iconType Type of the icon (Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF)
+ * @param iconData The icon as a Byte-Array
+ */
+ private void appendPayload(String title, String message, byte iconType, byte[] iconData)
+ {
+ appendPayload(title);
+ appendPayload(message);
+ appendPayload(iconType);
+ appendPayload(0); // reserved
+ if(iconData!=null)
+ appendPayload(iconData);
+
+ }
+}
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketPING.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketPING.java
new file mode 100644
index 0000000..2afbd8d
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/PacketPING.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+/**
+ * XBMC Event Client Class
+ *
+ * A PING packet tells XBMC that the client is still alive. All valid
+ * packets act as ping (not just this one). A client needs to ping
+ * XBMC at least once in 60 seconds or it will time
+ * @author Stefan Agner
+ *
+ */
+public class PacketPING extends Packet {
+ /**
+ * A PING packet tells XBMC that the client is still alive.
+ */
+ public PacketPING()
+ {
+ super(PT_PING);
+ }
+}
diff --git a/tools/EventClients/lib/java/src/org/xbmc/eventclient/XBMCClient.java b/tools/EventClients/lib/java/src/org/xbmc/eventclient/XBMCClient.java
new file mode 100644
index 0000000..322ebf1
--- /dev/null
+++ b/tools/EventClients/lib/java/src/org/xbmc/eventclient/XBMCClient.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2008-2013 Team XBMC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.xbmc.eventclient;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+
+/**
+ * XBMC Event Client Class
+ *
+ * Implements an XBMC-Client. This class can be used to implement your own application which
+ * should act as a Input device for XBMC. Also starts a Ping-Thread, which tells the XBMC EventServer
+ * that the client is alive. Therefore if you close your application you SHOULD call stopClient()!
+ * @author Stefan Agner
+ *
+ */
+public class XBMCClient
+{
+ private boolean hasIcon = false;
+ private String deviceName;
+ private PingThread oPingThread;
+ private byte iconType = Packet.ICON_PNG;
+ private byte[] iconData;
+ private InetAddress hostAddress;
+ private int hostPort;
+
+ /**
+ * Starts a XBMC EventClient.
+ * @param hostAddress Address of the Host running XBMC
+ * @param hostPort Port of the Host running XBMC (default 9777)
+ * @param deviceName Name of the Device
+ * @param iconFile Path to the Iconfile (PNG, JPEG or GIF)
+ * @throws IOException
+ */
+ public XBMCClient(InetAddress hostAddress, int hostPort, String deviceName, String iconFile) throws IOException
+ {
+ byte iconType = Packet.ICON_PNG;
+ // Assume png as icon type
+ if(iconFile.toLowerCase().endsWith(".jpeg"))
+ iconType = Packet.ICON_JPEG;
+ if(iconFile.toLowerCase().endsWith(".jpg"))
+ iconType = Packet.ICON_JPEG;
+ if(iconFile.toLowerCase().endsWith(".gif"))
+ iconType = Packet.ICON_GIF;
+
+ // Read the icon file to the byte array...
+ FileInputStream iconFileStream = new FileInputStream(iconFile);
+ byte[] iconData = new byte[iconFileStream.available()];
+ iconFileStream.read(iconData);
+
+ hasIcon = true;
+
+ // Call start-Method...
+ startClient(hostAddress, hostPort, deviceName, iconType, iconData);
+ }
+
+
+ /**
+ * Starts a XBMC EventClient.
+ * @param hostAddress Address of the Host running XBMC
+ * @param hostPort Port of the Host running XBMC (default 9777)
+ * @param deviceName Name of the Device
+ * @param iconType Type of the icon file (see Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF)
+ * @param iconData The icon itself as a Byte-Array
+ * @throws IOException
+ */
+ public XBMCClient(InetAddress hostAddress, int hostPort, String deviceName, byte iconType, byte[] iconData) throws IOException
+ {
+ hasIcon = true;
+ startClient(hostAddress, hostPort, deviceName, iconType, iconData);
+ }
+
+ /**
+ * Starts a XBMC EventClient without an icon.
+ * @param hostAddress Address of the Host running XBMC
+ * @param hostPort Port of the Host running XBMC (default 9777)
+ * @param deviceName Name of the Device
+ * @throws IOException
+ */
+ public XBMCClient(InetAddress hostAddress, int hostPort, String deviceName) throws IOException
+ {
+ hasIcon = false;
+ byte iconType = Packet.ICON_NONE;
+ byte[] iconData = null;
+ startClient(hostAddress, hostPort, deviceName, iconType, iconData);
+ }
+
+
+ /**
+ * Starts a XBMC EventClient.
+ * @param hostAddress Address of the Host running XBMC
+ * @param hostPort Port of the Host running XBMC (default 9777)
+ * @param deviceName Name of the Device
+ * @param iconType Type of the icon file (see Packet.ICON_PNG, Packet.ICON_JPEG or Packet.ICON_GIF)
+ * @param iconData The icon itself as a Byte-Array
+ * @throws IOException
+ */
+ private void startClient(InetAddress hostAddress, int hostPort, String deviceName, byte iconType, byte[] iconData) throws IOException
+ {
+ // Save host address and port
+ this.hostAddress = hostAddress;
+ this.hostPort = hostPort;
+ this.deviceName = deviceName;
+
+ this.iconType = iconType;
+ this.iconData = iconData;
+
+ // Send Hello Packet...
+ PacketHELO p;
+ if(hasIcon)
+ p = new PacketHELO(deviceName, iconType, iconData);
+ else
+ p = new PacketHELO(deviceName);
+
+ p.send(hostAddress, hostPort);
+
+ // Start Thread (for Ping packets...)
+ oPingThread = new PingThread(hostAddress, hostPort, 20000);
+ oPingThread.start();
+ }
+
+ /**
+ * Stops the XBMC EventClient (especially the Ping-Thread)
+ * @throws IOException
+ */
+ public void stopClient() throws IOException
+ {
+ // Stop Ping-Thread...
+ oPingThread.giveup();
+ oPingThread.interrupt();
+
+ PacketBYE p = new PacketBYE();
+ p.send(hostAddress, hostPort);
+ }
+
+
+ /**
+ * Displays a notification window in XBMC.
+ * @param title Message title
+ * @param message The actual message
+ */
+ public void sendNotification(String title, String message) throws IOException
+ {
+ PacketNOTIFICATION p;
+ if(hasIcon)
+ p = new PacketNOTIFICATION(title, message, iconType, iconData);
+ else
+ p = new PacketNOTIFICATION(title, message);
+ p.send(hostAddress, hostPort);
+ }
+
+ /**
+ * Sends a Button event
+ * @param code raw button code (default: 0)
+ * @param repeat this key press should repeat until released (default: 1)
+ * Note that queued pressed cannot repeat.
+ * @param down if this is 1, it implies a press event, 0 implies a release
+ * event. (default: 1)
+ * @param queue a queued key press means that the button event is
+ * executed just once after which the next key press is processed.
+ * It can be used for macros. Currently there is no support for
+ * time delays between queued presses. (default: 0)
+ * @param amount unimplemented for now; in the future it will be used for
+ * specifying magnitude of analog key press events
+ * @param axis
+ */
+ public void sendButton(short code, boolean repeat, boolean down, boolean queue, short amount, byte axis) throws IOException
+ {
+ PacketBUTTON p = new PacketBUTTON(code, repeat, down, queue, amount, axis);
+ p.send(hostAddress, hostPort);
+ }
+
+ /**
+ * Sends a Button event
+ * @param map_name a combination of map_name and button_name refers to a
+ * mapping in the user's Keymap.xml or Lircmap.xml.
+ * map_name can be one of the following:
+ * <ul>
+ * <li>"KB" => standard keyboard map ( <keyboard> section )</li>
+ * <li>"XG" => xbox gamepad map ( <gamepad> section )</li>
+ * <li>"R1" => xbox remote map ( <remote> section )</li>
+ * <li>"R2" => xbox universal remote map ( <universalremote> section )</li>
+ * <li>"LI:devicename" => LIRC remote map where 'devicename' is the
+ * actual device's name</li></ul>
+ * @param button_name a button name defined in the map specified in map_name.
+ * For example, if map_name is "KB" referring to the <keyboard> section in Keymap.xml
+ * then, valid button_names include "printscreen", "minus", "x", etc.
+ * @param repeat this key press should repeat until released (default: 1)
+ * Note that queued pressed cannot repeat.
+ * @param down if this is 1, it implies a press event, 0 implies a release
+ * event. (default: 1)
+ * @param queue a queued key press means that the button event is
+ * executed just once after which the next key press is processed.
+ * It can be used for macros. Currently there is no support for
+ * time delays between queued presses. (default: 0)
+ * @param amount unimplemented for now; in the future it will be used for
+ * specifying magnitude of analog key press events
+ * @param axis
+ */
+ public void sendButton(String map_name, String button_name, boolean repeat, boolean down, boolean queue, short amount, byte axis) throws IOException
+ {
+ PacketBUTTON p = new PacketBUTTON(map_name, button_name, repeat, down, queue, amount, axis);
+ p.send(hostAddress, hostPort);
+ }
+
+ /**
+ * Sets the mouse position in XBMC
+ * @param x horizontal position ranging from 0 to 65535
+ * @param y vertical position ranging from 0 to 65535
+ */
+ public void sendMouse(int x, int y) throws IOException
+ {
+ PacketMOUSE p = new PacketMOUSE(x, y);
+ p.send(hostAddress, hostPort);
+ }
+
+ /**
+ * Sends a ping to the XBMC EventServer
+ * @throws IOException
+ */
+ public void ping() throws IOException
+ {
+ PacketPING p = new PacketPING();
+ p.send(hostAddress, hostPort);
+ }
+
+ /**
+ * Tells XBMC to log the message to xbmc.log with the loglevel as specified.
+ * @param loglevel the loglevel, follows XBMC standard.
+ * <ul>
+ * <li>0 = DEBUG</li>
+ * <li>1 = INFO</li>
+ * <li>2 = NOTICE</li>
+ * <li>3 = WARNING</li>
+ * <li>4 = ERROR</li>
+ * <li>5 = SEVERE</li>
+ * </ul>
+ * @param logmessage the message to log
+ */
+ public void sendLog(byte loglevel, String logmessage) throws IOException
+ {
+ PacketLOG p = new PacketLOG(loglevel, logmessage);
+ p.send(hostAddress, hostPort);
+ }
+
+ /**
+ * Tells XBMC to do the action specified, based on the type it knows were it needs to be sent.
+ * @param actionmessage Actionmessage (as in scripting/skinning)
+ */
+ public void sendAction(String actionmessage) throws IOException
+ {
+ PacketACTION p = new PacketACTION(actionmessage);
+ p.send(hostAddress, hostPort);
+ }
+
+ /**
+ * Implements a PingThread which tells XBMC EventServer that the Client is alive (this should
+ * be done at least every 60 seconds!
+ * @author Stefan Agner
+ *
+ */
+ class PingThread extends Thread
+ {
+ private InetAddress hostAddress;
+ private int hostPort;
+ private int sleepTime;
+ private boolean giveup = false;
+
+ public PingThread(InetAddress hostAddress, int hostPort, int sleepTime)
+ {
+ super("XBMC EventClient Ping-Thread");
+ this.hostAddress = hostAddress;
+ this.hostPort = hostPort;
+ this.sleepTime = sleepTime;
+ }
+
+ public void giveup()
+ {
+ giveup = true;
+ }
+
+ public void run()
+ {
+ while(!giveup)
+ {
+ try {
+ PacketPING p = new PacketPING();
+ p.send(hostAddress, hostPort);
+ } catch (IOException e) {
+
+ e.printStackTrace();
+ }
+
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+}
diff --git a/tools/EventClients/lib/python/__init__.py b/tools/EventClients/lib/python/__init__.py
new file mode 100644
index 0000000..7deecc4
--- /dev/null
+++ b/tools/EventClients/lib/python/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+# File intentionally left blank
diff --git a/tools/EventClients/lib/python/bt/__init__.py b/tools/EventClients/lib/python/bt/__init__.py
new file mode 100644
index 0000000..7deecc4
--- /dev/null
+++ b/tools/EventClients/lib/python/bt/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+# File intentionally left blank
diff --git a/tools/EventClients/lib/python/bt/bt.py b/tools/EventClients/lib/python/bt/bt.py
new file mode 100644
index 0000000..979ebf2
--- /dev/null
+++ b/tools/EventClients/lib/python/bt/bt.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2008-2013 Team XBMC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+BLUEZ=0
+
+try:
+ import bluetooth
+ BLUEZ=1
+except:
+ try:
+ import lightblue
+ except:
+ print("ERROR: You need to have either LightBlue or PyBluez installed\n"\
+ " in order to use this program.")
+ print("- PyBluez (Linux / Windows XP) http://org.csail.mit.edu/pybluez/")
+ print("- LightBlue (Mac OS X / Linux) http://lightblue.sourceforge.net/")
+ exit()
+
+def bt_create_socket():
+ if BLUEZ:
+ sock = bluetooth.BluetoothSocket(bluetooth.L2CAP)
+ else:
+ sock = lightblue.socket(lightblue.L2CAP)
+ return sock
+
+def bt_create_rfcomm_socket():
+ if BLUEZ:
+ sock = bluetooth.BluetoothSocket( bluetooth.RFCOMM )
+ sock.bind(("",bluetooth.PORT_ANY))
+ else:
+ sock = lightblue.socket(lightblue.RFCOMM)
+ sock.bind(("",0))
+ return sock
+
+def bt_discover_devices():
+ if BLUEZ:
+ nearby = bluetooth.discover_devices()
+ else:
+ nearby = lightblue.finddevices()
+ return nearby
+
+def bt_lookup_name(bdaddr):
+ if BLUEZ:
+ bname = bluetooth.lookup_name( bdaddr )
+ else:
+ bname = bdaddr[1]
+ return bname
+
+def bt_lookup_addr(bdaddr):
+ if BLUEZ:
+ return bdaddr
+ else:
+ return bdaddr[0]
+
+def bt_advertise(name, uuid, socket):
+ if BLUEZ:
+ bluetooth.advertise_service( socket, name,
+ service_id = uuid,
+ service_classes = [ uuid, bluetooth.SERIAL_PORT_CLASS ],
+ profiles = [ bluetooth.SERIAL_PORT_PROFILE ] )
+ else:
+ lightblue.advertise(name, socket, lightblue.RFCOMM)
+
+def bt_stop_advertising(socket):
+ if BLUEZ:
+ stop_advertising(socket)
+ else:
+ lightblue.stopadvertise(socket)
diff --git a/tools/EventClients/lib/python/bt/hid.py b/tools/EventClients/lib/python/bt/hid.py
new file mode 100644
index 0000000..c065054
--- /dev/null
+++ b/tools/EventClients/lib/python/bt/hid.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2008-2013 Team XBMC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from bluetooth import *
+import fcntl
+import bluetooth._bluetooth as _bt
+import array
+
+class HID:
+ def __init__(self, bdaddress=None):
+ self.cport = 0x11 # HID's control PSM
+ self.iport = 0x13 # HID' interrupt PSM
+ self.backlog = 1
+
+ self.address = ""
+ if bdaddress:
+ self.address = bdaddress
+
+ # create the HID control socket
+ self.csock = BluetoothSocket( L2CAP )
+ self.csock.bind((self.address, self.cport))
+ set_l2cap_mtu(self.csock, 64)
+ self.csock.settimeout(2)
+ self.csock.listen(self.backlog)
+
+ # create the HID interrupt socket
+ self.isock = BluetoothSocket( L2CAP )
+ self.isock.bind((self.address, self.iport))
+ set_l2cap_mtu(self.isock, 64)
+ self.isock.settimeout(2)
+ self.isock.listen(self.backlog)
+
+ self.connected = False
+
+
+ def listen(self):
+ try:
+ (self.client_csock, self.caddress) = self.csock.accept()
+ print("Accepted Control connection from %s" % self.caddress[0])
+ (self.client_isock, self.iaddress) = self.isock.accept()
+ print("Accepted Interrupt connection from %s" % self.iaddress[0])
+ self.connected = True
+ return True
+ except Exception as e:
+ self.connected = False
+ return False
+
+ def get_local_address(self):
+ hci = BluetoothSocket( HCI )
+ fd = hci.fileno()
+ buf = array.array('B', [0] * 96)
+ fcntl.ioctl(fd, _bt.HCIGETDEVINFO, buf, 1)
+ data = struct.unpack_from("H8s6B", buf.tostring())
+ return data[2:8][::-1]
+
+ def get_control_socket(self):
+ if self.connected:
+ return (self.client_csock, self.caddress)
+ else:
+ return None
+
+
+ def get_interrupt_socket(self):
+ if self.connected:
+ return (self.client_isock, self.iaddress)
+ else:
+ return None
diff --git a/tools/EventClients/lib/python/ps3/__init__.py b/tools/EventClients/lib/python/ps3/__init__.py
new file mode 100644
index 0000000..7deecc4
--- /dev/null
+++ b/tools/EventClients/lib/python/ps3/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+# File intentionally left blank
diff --git a/tools/EventClients/lib/python/ps3/keymaps.py b/tools/EventClients/lib/python/ps3/keymaps.py
new file mode 100644
index 0000000..99c6e04
--- /dev/null
+++ b/tools/EventClients/lib/python/ps3/keymaps.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2008-2013 Team XBMC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# PS3 Remote and Controller Keymaps
+
+keymap_remote = {
+ "16": 'power' ,#EJECT
+ "64": None ,#AUDIO
+ "65": None ,#ANGLE
+ "63": 'subtitle' ,#SUBTITLE
+ "0f": None ,#CLEAR
+ "28": None ,#TIME
+
+ "00": 'one' ,#1
+ "01": 'two' ,#2
+ "02": 'three' ,#3
+ "03": 'four' ,#4
+ "04": 'five' ,#5
+ "05": 'six' ,#6
+ "06": 'seven' ,#7
+ "07": 'eight' ,#8
+ "08": 'nine' ,#9
+ "09": 'zero' ,#0
+
+ "81": 'mytv' ,#RED
+ "82": 'mymusic' ,#GREEN
+ "80": 'mypictures' ,#BLUE
+ "83": 'myvideo' ,#YELLOW
+
+ "70": 'display' ,#DISPLAY
+ "1a": None ,#TOP MENU
+ "40": 'menu' ,#POP UP/MENU
+ "0e": None ,#RETURN
+
+ "5c": 'menu' ,#OPTIONS/TRIANGLE
+ "5d": 'back' ,#BACK/CIRCLE
+ "5e": 'info' ,#X
+ "5f": 'title' ,#VIEW/SQUARE
+
+ "54": 'up' ,#UP
+ "55": 'right' ,#RIGHT
+ "56": 'down' ,#DOWN
+ "57": 'left' ,#LEFT
+ "0b": 'select' ,#ENTER
+
+ "5a": 'volumeplus' ,#L1
+ "58": 'volumeminus' ,#L2
+ "51": 'Mute' ,#L3
+ "5b": 'pageplus' ,#R1
+ "59": 'pageminus' ,#R2
+ "52": None ,#R3
+
+ "43": None ,#PLAYSTATION
+ "50": None ,#SELECT
+ "53": None ,#START
+
+ "33": 'reverse' ,#<-SCAN
+ "34": 'forward' ,# SCAN->
+ "30": 'skipminus' ,#PREV
+ "31": 'skipplus' ,#NEXT
+ "60": None ,#<-SLOW/STEP
+ "61": None ,# SLOW/STEP->
+ "32": 'play' ,#PLAY
+ "38": 'stop' ,#STOP
+ "39": 'pause' ,#PAUSE
+ }
+
diff --git a/tools/EventClients/lib/python/ps3/sixaxis.py b/tools/EventClients/lib/python/ps3/sixaxis.py
new file mode 100644
index 0000000..b4899f6
--- /dev/null
+++ b/tools/EventClients/lib/python/ps3/sixaxis.py
@@ -0,0 +1,372 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2008-2013 Team XBMC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import time
+import sys
+import struct
+import math
+import binascii
+from bluetooth import set_l2cap_mtu
+
+SX_SELECT = 1 << 0
+SX_L3 = 1 << 1
+SX_R3 = 1 << 2
+SX_START = 1 << 3
+SX_DUP = 1 << 4
+SX_DRIGHT = 1 << 5
+SX_DDOWN = 1 << 6
+SX_DLEFT = 1 << 7
+SX_L2 = 1 << 8
+SX_R2 = 1 << 9
+SX_L1 = 1 << 10
+SX_R1 = 1 << 11
+SX_TRIANGLE = 1 << 12
+SX_CIRCLE = 1 << 13
+SX_X = 1 << 14
+SX_SQUARE = 1 << 15
+SX_POWER = 1 << 16
+
+SX_LSTICK_X = 0
+SX_LSTICK_Y = 1
+SX_RSTICK_X = 2
+SX_RSTICK_Y = 3
+
+# (map, key, amount index, axis)
+keymap_sixaxis = {
+ SX_X : ('XG', 'A', 0, 0),
+ SX_CIRCLE : ('XG', 'B', 0, 0),
+ SX_SQUARE : ('XG', 'X', 0, 0),
+ SX_TRIANGLE : ('XG', 'Y', 0, 0),
+
+ SX_DUP : ('XG', 'dpadup', 0, 0),
+ SX_DDOWN : ('XG', 'dpaddown', 0, 0),
+ SX_DLEFT : ('XG', 'dpadleft', 0, 0),
+ SX_DRIGHT : ('XG', 'dpadright', 0, 0),
+
+ SX_START : ('XG', 'start', 0, 0),
+ SX_SELECT : ('XG', 'back', 0, 0),
+
+ SX_R1 : ('XG', 'white', 0, 0),
+ SX_R2 : ('XG', 'rightanalogtrigger', 6, 1),
+ SX_L2 : ('XG', 'leftanalogtrigger', 5, 1),
+ SX_L1 : ('XG', 'black', 0, 0),
+
+ SX_L3 : ('XG', 'leftthumbbutton', 0, 0),
+ SX_R3 : ('XG', 'rightthumbbutton', 0, 0),
+}
+
+# (data index, left map, left action, right map, right action)
+axismap_sixaxis = {
+ SX_LSTICK_X : ('XG', 'leftthumbstickleft' , 'leftthumbstickright'),
+ SX_LSTICK_Y : ('XG', 'leftthumbstickup' , 'leftthumbstickdown'),
+ SX_RSTICK_X : ('XG', 'rightthumbstickleft', 'rightthumbstickright'),
+ SX_RSTICK_Y : ('XG', 'rightthumbstickup' , 'rightthumbstickdown'),
+}
+
+# to make sure all combination keys are checked first
+# we sort the keymap's button codes in reverse order
+# this guarantees that any bit combined button code
+# will be processed first
+keymap_sixaxis_keys = keymap_sixaxis.keys()
+keymap_sixaxis_keys.sort()
+keymap_sixaxis_keys.reverse()
+
+def getkeys(bflags):
+ keys = [];
+ for k in keymap_sixaxis_keys:
+ if (k & bflags) == k:
+ keys.append(k)
+ bflags = bflags & ~k
+ return keys;
+
+
+def normalize(val):
+ upperlimit = 65281
+ lowerlimit = 2
+ val_range = upperlimit - lowerlimit
+ offset = 10000
+
+ val = (val + val_range / 2) % val_range
+ upperlimit -= offset
+ lowerlimit += offset
+
+ if val < lowerlimit:
+ val = lowerlimit
+ if val > upperlimit:
+ val = upperlimit
+
+ val = ((float(val) - offset) / (float(upperlimit) -
+ lowerlimit)) * 65535.0
+ if val <= 0:
+ val = 1
+ return val
+
+def normalize_axis(val, deadzone):
+
+ val = float(val) - 127.5
+ val = val / 127.5
+
+ if abs(val) < deadzone:
+ return 0.0
+
+ if val > 0.0:
+ val = (val - deadzone) / (1.0 - deadzone)
+ else:
+ val = (val + deadzone) / (1.0 - deadzone)
+
+ return 65536.0 * val
+
+def normalize_angle(val, valrange):
+ valrange *= 2
+
+ val = val / valrange
+ if val > 1.0:
+ val = 1.0
+ if val < -1.0:
+ val = -1.0
+ return (val + 0.5) * 65535.0
+
+def average(array):
+ val = 0
+ for i in array:
+ val += i
+ return val / len(array)
+
+def smooth(arr, val):
+ cnt = len(arr)
+ arr.insert(0, val)
+ arr.pop(cnt)
+ return average(arr)
+
+def set_l2cap_mtu2(sock, mtu):
+ SOL_L2CAP = 6
+ L2CAP_OPTIONS = 1
+
+ s = sock.getsockopt (SOL_L2CAP, L2CAP_OPTIONS, 12)
+ o = list( struct.unpack ("HHHBBBH", s) )
+ o[0] = o[1] = mtu
+ s = struct.pack ("HHHBBBH", *o)
+ try:
+ sock.setsockopt (SOL_L2CAP, L2CAP_OPTIONS, s)
+ except:
+ print("Warning: Unable to set mtu")
+
+class sixaxis():
+
+ def __init__(self, xbmc, control_sock, interrupt_sock):
+
+ self.xbmc = xbmc
+ self.num_samples = 16
+ self.sumx = [0] * self.num_samples
+ self.sumy = [0] * self.num_samples
+ self.sumr = [0] * self.num_samples
+ self.axis_amount = [0, 0, 0, 0]
+
+ self.released = set()
+ self.pressed = set()
+ self.pending = set()
+ self.held = set()
+ self.psflags = 0
+ self.psdown = 0
+ self.mouse_enabled = 0
+
+ set_l2cap_mtu2(control_sock, 64)
+ set_l2cap_mtu2(interrupt_sock, 64)
+ time.sleep(0.25) # If we ask to quickly here, it sometimes doesn't start
+
+ # sixaxis needs this to enable it
+ # 0x53 => HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE
+ control_sock.send("\x53\xf4\x42\x03\x00\x00")
+ data = control_sock.recv(1)
+ # This command will turn on the gyro and set the leds
+ # I wonder if turning on the gyro makes it draw more current??
+ # it's probably a flag somewhere in the following command
+
+ # HID Command: HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUTPUT
+ # HID Report:1
+ bytes = [0x52, 0x1]
+ bytes.extend([0x00, 0x00, 0x00])
+ bytes.extend([0xFF, 0x72])
+ bytes.extend([0x00, 0x00, 0x00, 0x00])
+ bytes.extend([0x02]) # 0x02 LED1, 0x04 LED2 ... 0x10 LED4
+ # The following sections should set the blink frequency of
+ # the leds on the controller, but i've not figured out how.
+ # These values where suggested in a mailing list, but no explanation
+ # for how they should be combined to the 5 bytes per led
+ #0xFF = 0.5Hz
+ #0x80 = 1Hz
+ #0x40 = 2Hz
+ bytes.extend([0xFF, 0x00, 0x01, 0x00, 0x01]) #LED4 [0xff, 0xff, 0x10, 0x10, 0x10]
+ bytes.extend([0xFF, 0x00, 0x01, 0x00, 0x01]) #LED3 [0xff, 0x40, 0x08, 0x10, 0x10]
+ bytes.extend([0xFF, 0x00, 0x01, 0x00, 0x01]) #LED2 [0xff, 0x00, 0x10, 0x30, 0x30]
+ bytes.extend([0xFF, 0x00, 0x01, 0x00, 0x01]) #LED1 [0xff, 0x00, 0x10, 0x40, 0x10]
+ bytes.extend([0x00, 0x00, 0x00, 0x00, 0x00])
+ bytes.extend([0x00, 0x00, 0x00, 0x00, 0x00])
+
+ control_sock.send(struct.pack("42B", *bytes))
+ data = control_sock.recv(1)
+
+ def __del__(self):
+ self.close()
+
+ def close(self):
+
+ for key in (self.held | self.pressed):
+ (mapname, action, amount, axis) = keymap_sixaxis[key]
+ self.xbmc.send_button_state(map=mapname, button=action, amount=0, down=0, axis=axis)
+ self.held = set()
+ self.pressed = set()
+
+
+ def process_socket(self, isock):
+ data = isock.recv(50)
+ if data == None:
+ return False
+ return self.process_data(data)
+
+
+ def process_data(self, data):
+ if len(data) < 3:
+ return False
+
+ # make sure this is the correct report
+ if struct.unpack("BBB", data[0:3]) != (0xa1, 0x01, 0x00):
+ return False
+
+ if len(data) >= 48:
+ v1 = struct.unpack("h", data[42:44])
+ v2 = struct.unpack("h", data[44:46])
+ v3 = struct.unpack("h", data[46:48])
+ else:
+ v1 = [0,0]
+ v2 = [0,0]
+ v3 = [0,0]
+
+ if len(data) >= 50:
+ v4 = struct.unpack("h", data[48:50])
+ else:
+ v4 = [0,0]
+
+ ax = float(v1[0])
+ ay = float(v2[0])
+ az = float(v3[0])
+ rz = float(v4[0])
+ at = math.sqrt(ax*ax + ay*ay + az*az)
+
+ bflags = struct.unpack("<I", data[3:7])[0]
+ if len(data) > 27:
+ pressure = struct.unpack("BBBBBBBBBBBB", data[15:27])
+ else:
+ pressure = [0,0,0,0,0,0,0,0,0,0,0,0,0]
+
+ roll = -math.atan2(ax, math.sqrt(ay*ay + az*az))
+ pitch = math.atan2(ay, math.sqrt(ax*ax + az*az))
+
+ pitch -= math.radians(20);
+
+ xpos = normalize_angle(roll, math.radians(30))
+ ypos = normalize_angle(pitch, math.radians(30))
+
+
+ axis = struct.unpack("BBBB", data[7:11])
+ return self.process_input(bflags, pressure, axis, xpos, ypos)
+
+ def process_input(self, bflags, pressure, axis, xpos, ypos):
+
+ xval = smooth(self.sumx, xpos)
+ yval = smooth(self.sumy, ypos)
+
+ analog = False
+ for i in range(4):
+ config = axismap_sixaxis[i]
+ self.axis_amount[i] = self.send_singleaxis(axis[i], self.axis_amount[i], config[0], config[1], config[2])
+ if self.axis_amount[i] != 0:
+ analog = True
+
+ # send the mouse position to xbmc
+ if self.mouse_enabled == 1:
+ self.xbmc.send_mouse_position(xval, yval)
+
+ if (bflags & SX_POWER) == SX_POWER:
+ if self.psdown:
+ if (time.time() - self.psdown) > 5:
+
+ for key in (self.held | self.pressed):
+ (mapname, action, amount, axis) = keymap_sixaxis[key]
+ self.xbmc.send_button_state(map=mapname, button=action, amount=0, down=0, axis=axis)
+
+ raise Exception("PS3 Sixaxis powering off, user request")
+ else:
+ self.psdown = time.time()
+ else:
+ if self.psdown:
+ self.mouse_enabled = 1 - self.mouse_enabled
+ self.psdown = 0
+
+ keys = set(getkeys(bflags))
+ self.released = (self.pressed | self.held) - keys
+ self.held = (self.pressed | self.held) - self.released
+ self.pressed = (keys - self.held) & self.pending
+ self.pending = (keys - self.held)
+
+ for key in self.released:
+ (mapname, action, amount, axis) = keymap_sixaxis[key]
+ self.xbmc.send_button_state(map=mapname, button=action, amount=0, down=0, axis=axis)
+
+ for key in self.held:
+ (mapname, action, amount, axis) = keymap_sixaxis[key]
+ if amount > 0:
+ amount = pressure[amount-1] * 256
+ self.xbmc.send_button_state(map=mapname, button=action, amount=amount, down=1, axis=axis)
+
+ for key in self.pressed:
+ (mapname, action, amount, axis) = keymap_sixaxis[key]
+ if amount > 0:
+ amount = pressure[amount-1] * 256
+ self.xbmc.send_button_state(map=mapname, button=action, amount=amount, down=1, axis=axis)
+
+ if analog or keys or self.mouse_enabled:
+ return True
+ else:
+ return False
+
+
+ def send_singleaxis(self, axis, last_amount, mapname, action_min, action_pos):
+ amount = normalize_axis(axis, 0.30)
+ if last_amount < 0:
+ last_action = action_min
+ elif last_amount > 0:
+ last_action = action_pos
+ else:
+ last_action = None
+
+ if amount < 0:
+ new_action = action_min
+ elif amount > 0:
+ new_action = action_pos
+ else:
+ new_action = None
+
+ if last_action and new_action != last_action:
+ self.xbmc.send_button_state(map=mapname, button=last_action, amount=0, axis=1)
+
+ if new_action and amount != last_amount:
+ self.xbmc.send_button_state(map=mapname, button=new_action, amount=abs(amount), axis=1)
+
+ return amount
diff --git a/tools/EventClients/lib/python/ps3/sixpair.py b/tools/EventClients/lib/python/ps3/sixpair.py
new file mode 100755
index 0000000..01f11c8
--- /dev/null
+++ b/tools/EventClients/lib/python/ps3/sixpair.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import sys
+import usb
+
+vendor = 0x054c
+product = 0x0268
+timeout = 5000
+passed_value = 0x03f5
+
+def find_sixaxes():
+ res = []
+ for bus in usb.busses():
+ for dev in bus.devices:
+ if dev.idVendor == vendor and dev.idProduct == product:
+ res.append(dev)
+ return res
+
+def find_interface(dev):
+ for cfg in dev.configurations:
+ for itf in cfg.interfaces:
+ for alt in itf:
+ if alt.interfaceClass == 3:
+ return alt
+ raise Exception("Unable to find interface")
+
+def mac_to_string(mac):
+ return "%02x:%02x:%02x:%02x:%02x:%02x" % (mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
+
+def set_pair_filename(dirname, filename, mac):
+ for bus in usb.busses():
+ if int(bus.dirname) == int(dirname):
+ for dev in bus.devices:
+ if int(dev.filename) == int(filename):
+ if dev.idVendor == vendor and dev.idProduct == product:
+ update_pair(dev, mac)
+ return
+ else:
+ raise Exception("Device is not a sixaxis")
+ raise Exception("Device not found")
+
+
+def set_pair(dev, mac):
+ itf = find_interface(dev)
+ handle = dev.open()
+
+ msg = (0x01, 0x00) + mac;
+
+ try:
+ handle.detachKernelDriver(itf.interfaceNumber)
+ except usb.USBError:
+ pass
+
+ handle.claimInterface(itf.interfaceNumber)
+ try:
+ handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS | usb.RECIP_INTERFACE
+ , usb.REQ_SET_CONFIGURATION, msg, passed_value, itf.interfaceNumber, timeout)
+ finally:
+ handle.releaseInterface()
+
+
+def get_pair(dev):
+ itf = find_interface(dev)
+ handle = dev.open()
+
+ try:
+ handle.detachKernelDriver(itf.interfaceNumber)
+ except usb.USBError:
+ pass
+
+ handle.claimInterface(itf.interfaceNumber)
+ try:
+ msg = handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE
+ , usb.REQ_CLEAR_FEATURE, 8, passed_value, itf.interfaceNumber, timeout)
+ finally:
+ handle.releaseInterface()
+ return msg[2:8]
+
+def set_pair_all(mac):
+ devs = find_sixaxes()
+ for dev in devs:
+ update_pair(dev, mac)
+
+def update_pair(dev, mac):
+ old = get_pair(dev)
+ if old != mac:
+ print("Re-pairing sixaxis from:" + mac_to_string(old) + " to:" + mac_to_string(mac))
+ set_pair(dev, mac)
+
+if __name__=="__main__":
+ devs = find_sixaxes()
+
+ mac = None
+ if len(sys.argv) > 1:
+ try:
+ mac = sys.argv[1].split(':')
+ mac = tuple([int(x, 16) for x in mac])
+ if len(mac) != 6:
+ print("Invalid length of HCI address, should be 6 parts")
+ mac = None
+ except:
+ print("Failed to parse HCI address")
+ mac = None
+
+ for dev in devs:
+ if mac:
+ update_pair(dev, mac)
+ else:
+ print("Found sixaxis paired to: " + mac_to_string(get_pair(dev)))
+
+
+
+
diff --git a/tools/EventClients/lib/python/ps3/sixwatch.py b/tools/EventClients/lib/python/ps3/sixwatch.py
new file mode 100755
index 0000000..553829b
--- /dev/null
+++ b/tools/EventClients/lib/python/ps3/sixwatch.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import pyudev
+import sixpair
+import threading
+
+vendor = 0x054c
+product = 0x0268
+
+
+def main(mac):
+ context = pyudev.Context()
+ monitor = pyudev.Monitor.from_netlink(context)
+ monitor.filter_by(subsystem="usb")
+ for action, device in monitor:
+ if 'ID_VENDOR_ID' in device and 'ID_MODEL_ID' in device:
+ if device['ID_VENDOR_ID'] == '054c' and device['ID_MODEL_ID'] == '0268':
+ if action == 'add':
+ print("Detected sixaxis connected by usb")
+ try:
+ sixpair.set_pair_filename(device.attributes['busnum'], device.attributes['devnum'], mac)
+ except Exception as e:
+ print("Failed to check pairing of sixaxis: " + str(e))
+ pass
+
+
+
+if __name__=="__main__":
+ main((0,0,0,0,0,0))
+
diff --git a/tools/EventClients/lib/python/xbmcclient.py b/tools/EventClients/lib/python/xbmcclient.py
new file mode 100644
index 0000000..548c443
--- /dev/null
+++ b/tools/EventClients/lib/python/xbmcclient.py
@@ -0,0 +1,639 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2008-2013 Team XBMC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+"""
+Implementation of XBMC's UDP based input system.
+
+A set of classes that abstract the various packets that the event server
+currently supports. In addition, there's also a class, XBMCClient, that
+provides functions that sends the various packets. Use XBMCClient if you
+don't need complete control over packet structure.
+
+The basic workflow involves:
+
+1. Send a HELO packet
+2. Send x number of valid packets
+3. Send a BYE packet
+
+IMPORTANT NOTE ABOUT TIMEOUTS:
+A client is considered to be timed out if XBMC doesn't received a packet
+at least once every 60 seconds. To "ping" XBMC with an empty packet use
+PacketPING or XBMCClient.ping(). See the documentation for details.
+"""
+
+from __future__ import unicode_literals, print_function, absolute_import, division
+
+__author__ = "d4rk@xbmc.org"
+__version__ = "0.1.0"
+
+import sys
+if sys.version_info.major == 2:
+ str = unicode
+from struct import pack
+from socket import socket, AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_BROADCAST
+import time
+
+MAX_PACKET_SIZE = 1024
+HEADER_SIZE = 32
+MAX_PAYLOAD_SIZE = MAX_PACKET_SIZE - HEADER_SIZE
+UNIQUE_IDENTIFICATION = (int)(time.time())
+
+PT_HELO = 0x01
+PT_BYE = 0x02
+PT_BUTTON = 0x03
+PT_MOUSE = 0x04
+PT_PING = 0x05
+PT_BROADCAST = 0x06
+PT_NOTIFICATION = 0x07
+PT_BLOB = 0x08
+PT_LOG = 0x09
+PT_ACTION = 0x0A
+PT_DEBUG = 0xFF
+
+ICON_NONE = 0x00
+ICON_JPEG = 0x01
+ICON_PNG = 0x02
+ICON_GIF = 0x03
+
+BT_USE_NAME = 0x01
+BT_DOWN = 0x02
+BT_UP = 0x04
+BT_USE_AMOUNT = 0x08
+BT_QUEUE = 0x10
+BT_NO_REPEAT = 0x20
+BT_VKEY = 0x40
+BT_AXIS = 0x80
+BT_AXISSINGLE = 0x100
+
+MS_ABSOLUTE = 0x01
+
+LOGDEBUG = 0x00
+LOGINFO = 0x01
+LOGWARNING = 0x02
+LOGERROR = 0x03
+LOGFATAL = 0x04
+LOGNONE = 0x05
+
+ACTION_EXECBUILTIN = 0x01
+ACTION_BUTTON = 0x02
+
+######################################################################
+# Helper Functions
+######################################################################
+
+def format_string(msg):
+ """ """
+ return msg.encode('utf-8') + b"\0"
+
+def format_uint32(num):
+ """ """
+ return pack ("!I", num)
+
+def format_uint16(num):
+ """ """
+ if num<0:
+ num = 0
+ elif num>65535:
+ num = 65535
+ return pack ("!H", num)
+
+
+######################################################################
+# Packet Classes
+######################################################################
+
+class Packet:
+ """Base class that implements a single event packet.
+
+ - Generic packet structure (maximum 1024 bytes per packet)
+ - Header is 32 bytes long, so 992 bytes available for payload
+ - large payloads can be split into multiple packets using H4 and H5
+ H5 should contain total no. of packets in such a case
+ - H6 contains length of P1, which is limited to 992 bytes
+ - if H5 is 0 or 1, then H4 will be ignored (single packet msg)
+ - H7 must be set to zeros for now
+
+ -----------------------------
+ | -H1 Signature ("XBMC") | - 4 x CHAR 4B
+ | -H2 Version (eg. 2.0) | - 2 x UNSIGNED CHAR 2B
+ | -H3 PacketType | - 1 x UNSIGNED SHORT 2B
+ | -H4 Sequence number | - 1 x UNSIGNED LONG 4B
+ | -H5 No. of packets in msg | - 1 x UNSIGNED LONG 4B
+ | -H7 Client's unique token | - 1 x UNSIGNED LONG 4B
+ | -H8 Reserved | - 10 x UNSIGNED CHAR 10B
+ |---------------------------|
+ | -P1 payload | -
+ -----------------------------
+ """
+ def __init__(self):
+ self.sig = b"XBMC"
+ self.minver = 0
+ self.majver = 2
+ self.seq = 1
+ self.maxseq = 1
+ self.payloadsize = 0
+ self.uid = UNIQUE_IDENTIFICATION
+ self.reserved = b"\0" * 10
+ self.payload = b""
+
+ def append_payload(self, blob):
+ """Append to existing payload
+
+ Arguments:
+ blob -- binary data to append to the current payload
+ """
+ if isinstance(blob, str):
+ blob = blob.encode()
+ self.set_payload(self.payload + blob)
+
+
+ def set_payload(self, payload):
+ """Set the payload for this packet
+
+ Arguments:
+ payload -- binary data that contains the payload
+ """
+ if isinstance(payload, str):
+ payload = payload.encode()
+ self.payload = payload
+ self.payloadsize = len(self.payload)
+ self.maxseq = int((self.payloadsize + (MAX_PAYLOAD_SIZE - 1)) / MAX_PAYLOAD_SIZE)
+
+
+ def num_packets(self):
+ """ Return the number of packets required for payload """
+ return self.maxseq
+
+ def get_header(self, packettype=-1, seq=1, maxseq=1, payload_size=0):
+ """Construct a header and return as string
+
+ Keyword arguments:
+ packettype -- valid packet types are PT_HELO, PT_BYE, PT_BUTTON,
+ PT_MOUSE, PT_PING, PT_BORADCAST, PT_NOTIFICATION,
+ PT_BLOB, PT_DEBUG
+ seq -- the sequence of this packet for a multi packet message
+ (default 1)
+ maxseq -- the total number of packets for a multi packet message
+ (default 1)
+ payload_size -- the size of the payload of this packet (default 0)
+ """
+ if packettype < 0:
+ packettype = self.packettype
+ header = self.sig
+ header += chr(self.majver).encode()
+ header += chr(self.minver).encode()
+ header += format_uint16(packettype)
+ header += format_uint32(seq)
+ header += format_uint32(maxseq)
+ header += format_uint16(payload_size)
+ header += format_uint32(self.uid)
+ header += self.reserved
+ return header
+
+ def get_payload_size(self, seq):
+ """Returns the calculated payload size for the particular packet
+
+ Arguments:
+ seq -- the sequence number
+ """
+ if self.maxseq == 1:
+ return self.payloadsize
+
+ if seq < self.maxseq:
+ return MAX_PAYLOAD_SIZE
+
+ return self.payloadsize % MAX_PAYLOAD_SIZE
+
+
+ def get_udp_message(self, packetnum=1):
+ """Construct the UDP message for the specified packetnum and return
+ as string
+
+ Keyword arguments:
+ packetnum -- the packet no. for which to construct the message
+ (default 1)
+ """
+ if packetnum > self.num_packets() or packetnum < 1:
+ return b""
+ header = b""
+ if packetnum==1:
+ header = self.get_header(self.packettype, packetnum, self.maxseq,
+ self.get_payload_size(packetnum))
+ else:
+ header = self.get_header(PT_BLOB, packetnum, self.maxseq,
+ self.get_payload_size(packetnum))
+
+ payload = self.payload[ (packetnum-1) * MAX_PAYLOAD_SIZE :
+ (packetnum-1) * MAX_PAYLOAD_SIZE+
+ self.get_payload_size(packetnum) ]
+ return header + payload
+
+ def send(self, sock, addr, uid=UNIQUE_IDENTIFICATION):
+ """Send the entire message to the specified socket and address.
+
+ Arguments:
+ sock -- datagram socket object (socket.socket)
+ addr -- address, port pair (eg: ("127.0.0.1", 9777) )
+ uid -- unique identification
+ """
+ self.uid = uid
+ for a in range ( 0, self.num_packets() ):
+ sock.sendto(self.get_udp_message(a+1), addr)
+
+
+class PacketHELO (Packet):
+ """A HELO packet
+
+ A HELO packet establishes a valid connection to XBMC. It is the
+ first packet that should be sent.
+ """
+ def __init__(self, devicename=None, icon_type=ICON_NONE, icon_file=None):
+ """
+ Keyword arguments:
+ devicename -- the string that identifies the client
+ icon_type -- one of ICON_NONE, ICON_JPEG, ICON_PNG, ICON_GIF
+ icon_file -- location of icon file with respect to current working
+ directory if icon_type is not ICON_NONE
+ """
+ Packet.__init__(self)
+ self.packettype = PT_HELO
+ self.icontype = icon_type
+ self.set_payload ( format_string(devicename)[0:128] )
+ self.append_payload( chr (icon_type) )
+ self.append_payload( format_uint16 (0) ) # port no
+ self.append_payload( format_uint32 (0) ) # reserved1
+ self.append_payload( format_uint32 (0) ) # reserved2
+ if icon_type != ICON_NONE and icon_file:
+ with open(icon_file, 'rb') as f:
+ self.append_payload(f.read())
+
+
+class PacketNOTIFICATION (Packet):
+ """A NOTIFICATION packet
+
+ This packet displays a notification window in XBMC. It can contain
+ a caption, a message and an icon.
+ """
+ def __init__(self, title, message, icon_type=ICON_NONE, icon_file=None):
+ """
+ Keyword arguments:
+ title -- the notification caption / title
+ message -- the main text of the notification
+ icon_type -- one of ICON_NONE, ICON_JPEG, ICON_PNG, ICON_GIF
+ icon_file -- location of icon file with respect to current working
+ directory if icon_type is not ICON_NONE
+ """
+ Packet.__init__(self)
+ self.packettype = PT_NOTIFICATION
+ self.title = title
+ self.message = message
+ self.set_payload ( format_string(title) )
+ self.append_payload( format_string(message) )
+ self.append_payload( chr (icon_type) )
+ self.append_payload( format_uint32 (0) ) # reserved
+ if icon_type != ICON_NONE and icon_file:
+ with open(icon_file, 'rb') as f:
+ self.append_payload(f.read())
+
+class PacketBUTTON (Packet):
+ """A BUTTON packet
+
+ A button packet send a key press or release event to XBMC
+ """
+ def __init__(self, code=0, repeat=1, down=1, queue=0,
+ map_name="", button_name="", amount=0, axis=0):
+ """
+ Keyword arguments:
+ code -- raw button code (default: 0)
+ repeat -- this key press should repeat until released (default: 1)
+ Note that queued pressed cannot repeat.
+ down -- if this is 1, it implies a press event, 0 implies a release
+ event. (default: 1)
+ queue -- a queued key press means that the button event is
+ executed just once after which the next key press is
+ processed. It can be used for macros. Currently there
+ is no support for time delays between queued presses.
+ (default: 0)
+ map_name -- a combination of map_name and button_name refers to a
+ mapping in the user's Keymap.xml or Lircmap.xml.
+ map_name can be one of the following:
+ "KB" => standard keyboard map ( <keyboard> section )
+ "XG" => xbox gamepad map ( <gamepad> section )
+ "R1" => xbox remote map ( <remote> section )
+ "R2" => xbox universal remote map ( <universalremote>
+ section )
+ "LI:devicename" => LIRC remote map where 'devicename' is the
+ actual device's name
+ button_name -- a button name defined in the map specified in map_name.
+ For example, if map_name is "KB" referring to the
+ <keyboard> section in Keymap.xml then, valid
+ button_names include "printscreen", "minus", "x", etc.
+ amount -- unimplemented for now; in the future it will be used for
+ specifying magnitude of analog key press events
+ """
+ Packet.__init__(self)
+ self.flags = 0
+ self.packettype = PT_BUTTON
+ if type (code ) == str:
+ code = ord(code)
+
+ # assign code only if we don't have a map and button name
+ if not (map_name and button_name):
+ self.code = code
+ else:
+ self.flags |= BT_USE_NAME
+ self.code = 0
+ if (amount != None):
+ self.flags |= BT_USE_AMOUNT
+ self.amount = int(amount)
+ else:
+ self.amount = 0
+
+ if down:
+ self.flags |= BT_DOWN
+ else:
+ self.flags |= BT_UP
+ if not repeat:
+ self.flags |= BT_NO_REPEAT
+ if queue:
+ self.flags |= BT_QUEUE
+ if axis == 1:
+ self.flags |= BT_AXISSINGLE
+ elif axis == 2:
+ self.flags |= BT_AXIS
+
+ self.set_payload ( format_uint16(self.code) )
+ self.append_payload( format_uint16(self.flags) )
+ self.append_payload( format_uint16(self.amount) )
+ self.append_payload( format_string (map_name) )
+ self.append_payload( format_string (button_name) )
+
+class PacketMOUSE (Packet):
+ """A MOUSE packet
+
+ A MOUSE packets sets the mouse position in XBMC
+ """
+ def __init__(self, x, y):
+ """
+ Arguments:
+ x -- horizontal position ranging from 0 to 65535
+ y -- vertical position ranging from 0 to 65535
+
+ The range will be mapped to the screen width and height in XBMC
+ """
+ Packet.__init__(self)
+ self.packettype = PT_MOUSE
+ self.flags = MS_ABSOLUTE
+ self.append_payload( chr (self.flags) )
+ self.append_payload( format_uint16(x) )
+ self.append_payload( format_uint16(y) )
+
+class PacketBYE (Packet):
+ """A BYE packet
+
+ A BYE packet terminates the connection to XBMC.
+ """
+ def __init__(self):
+ Packet.__init__(self)
+ self.packettype = PT_BYE
+
+
+class PacketPING (Packet):
+ """A PING packet
+
+ A PING packet tells XBMC that the client is still alive. All valid
+ packets act as ping (not just this one). A client needs to ping
+ XBMC at least once in 60 seconds or it will time out.
+ """
+ def __init__(self):
+ Packet.__init__(self)
+ self.packettype = PT_PING
+
+class PacketLOG (Packet):
+ """A LOG packet
+
+ A LOG packet tells XBMC to log the message to xbmc.log with the loglevel as specified.
+ """
+ def __init__(self, loglevel=0, logmessage="", autoprint=True):
+ """
+ Keyword arguments:
+ loglevel -- the loglevel, follows XBMC standard.
+ logmessage -- the message to log
+ autoprint -- if the logmessage should automatically be printed to stdout
+ """
+ Packet.__init__(self)
+ self.packettype = PT_LOG
+ self.append_payload( chr (loglevel) )
+ self.append_payload( format_string(logmessage) )
+ if (autoprint):
+ print(logmessage)
+
+class PacketACTION (Packet):
+ """An ACTION packet
+
+ An ACTION packet tells XBMC to do the action specified, based on the type it knows were it needs to be sent.
+ The idea is that this will be as in scripting/skining and keymapping, just triggered from afar.
+ """
+ def __init__(self, actionmessage="", actiontype=ACTION_EXECBUILTIN):
+ """
+ Keyword arguments:
+ loglevel -- the loglevel, follows XBMC standard.
+ logmessage -- the message to log
+ autoprint -- if the logmessage should automatically be printed to stdout
+ """
+ Packet.__init__(self)
+ self.packettype = PT_ACTION
+ self.append_payload( chr (actiontype) )
+ self.append_payload( format_string(actionmessage) )
+
+######################################################################
+# XBMC Client Class
+######################################################################
+
+class XBMCClient:
+ """An XBMC event client"""
+
+ def __init__(self, name ="", icon_file=None, broadcast=False, uid=UNIQUE_IDENTIFICATION,
+ ip="127.0.0.1"):
+ """
+ Keyword arguments:
+ name -- Name of the client
+ icon_file -- location of an icon file, if any (png, jpg or gif)
+ uid -- unique identification
+ """
+ self.name = str(name)
+ self.icon_file = icon_file
+ self.icon_type = self._get_icon_type(icon_file)
+ self.ip = ip
+ self.port = 9777
+ self.sock = socket(AF_INET,SOCK_DGRAM)
+ if broadcast:
+ self.sock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
+ self.uid = uid
+
+
+ def connect(self, ip=None, port=None):
+ """Initialize connection to XBMC
+ ip -- IP Address of XBMC
+ port -- port that the event server on XBMC is listening on
+ """
+ if ip:
+ self.ip = ip
+ if port:
+ self.port = int(port)
+ self.addr = (self.ip, self.port)
+ packet = PacketHELO(self.name, self.icon_type, self.icon_file)
+ packet.send(self.sock, self.addr, self.uid)
+
+
+ def close(self):
+ """Close the current connection"""
+ packet = PacketBYE()
+ packet.send(self.sock, self.addr, self.uid)
+
+
+ def ping(self):
+ """Send a PING packet"""
+ packet = PacketPING()
+ packet.send(self.sock, self.addr, self.uid)
+
+
+ def send_notification(self, title="", message="", icon_file=None):
+ """Send a notification to the connected XBMC
+ Keyword Arguments:
+ title -- The title/heading for the notification
+ message -- The message to be displayed
+ icon_file -- location of an icon file, if any (png, jpg, gif)
+ """
+ self.connect()
+ packet = PacketNOTIFICATION(title, message,
+ self._get_icon_type(icon_file),
+ icon_file)
+ packet.send(self.sock, self.addr, self.uid)
+
+
+ def send_keyboard_button(self, button=None):
+ """Send a keyboard event to XBMC
+ Keyword Arguments:
+ button -- name of the keyboard button to send (same as in Keymap.xml)
+ """
+ if not button:
+ return
+ self.send_button(map="KB", button=button)
+
+
+ def send_remote_button(self, button=None):
+ """Send a remote control event to XBMC
+ Keyword Arguments:
+ button -- name of the remote control button to send (same as in Keymap.xml)
+ """
+ if not button:
+ return
+ self.send_button(map="R1", button=button)
+
+
+ def release_button(self):
+ """Release all buttons"""
+ packet = PacketBUTTON(code=0x01, down=0)
+ packet.send(self.sock, self.addr, self.uid)
+
+
+ def send_button(self, map="", button="", amount=0):
+ """Send a button event to XBMC
+ Keyword arguments:
+ map -- a combination of map_name and button_name refers to a
+ mapping in the user's Keymap.xml or Lircmap.xml.
+ map_name can be one of the following:
+ "KB" => standard keyboard map ( <keyboard> section )
+ "XG" => xbox gamepad map ( <gamepad> section )
+ "R1" => xbox remote map ( <remote> section )
+ "R2" => xbox universal remote map ( <universalremote>
+ section )
+ "LI:devicename" => LIRC remote map where 'devicename' is the
+ actual device's name
+ button -- a button name defined in the map specified in map, above.
+ For example, if map is "KB" referring to the <keyboard>
+ section in Keymap.xml then, valid buttons include
+ "printscreen", "minus", "x", etc.
+ """
+ packet = PacketBUTTON(map_name=str(map), button_name=str(button), amount=amount)
+ packet.send(self.sock, self.addr, self.uid)
+
+ def send_button_state(self, map="", button="", amount=0, down=0, axis=0):
+ """Send a button event to XBMC
+ Keyword arguments:
+ map -- a combination of map_name and button_name refers to a
+ mapping in the user's Keymap.xml or Lircmap.xml.
+ map_name can be one of the following:
+ "KB" => standard keyboard map ( <keyboard> section )
+ "XG" => xbox gamepad map ( <gamepad> section )
+ "R1" => xbox remote map ( <remote> section )
+ "R2" => xbox universal remote map ( <universalremote>
+ section )
+ "LI:devicename" => LIRC remote map where 'devicename' is the
+ actual device's name
+ button -- a button name defined in the map specified in map, above.
+ For example, if map is "KB" referring to the <keyboard>
+ section in Keymap.xml then, valid buttons include
+ "printscreen", "minus", "x", etc.
+ """
+ if axis:
+ down = int(amount != 0)
+
+ packet = PacketBUTTON(map_name=str(map), button_name=str(button), amount=amount, down=down, queue=1, axis=axis)
+ packet.send(self.sock, self.addr, self.uid)
+
+ def send_mouse_position(self, x=0, y=0):
+ """Send a mouse event to XBMC
+ Keywords Arguments:
+ x -- absolute x position of mouse ranging from 0 to 65535
+ which maps to the entire screen width
+ y -- same a 'x' but relates to the screen height
+ """
+ packet = PacketMOUSE(int(x), int(y))
+ packet.send(self.sock, self.addr, self.uid)
+
+ def send_log(self, loglevel=0, logmessage="", autoprint=True):
+ """
+ Keyword arguments:
+ loglevel -- the loglevel, follows XBMC standard.
+ logmessage -- the message to log
+ autoprint -- if the logmessage should automatically be printed to stdout
+ """
+ packet = PacketLOG(loglevel, logmessage)
+ packet.send(self.sock, self.addr, self.uid)
+
+ def send_action(self, actionmessage="", actiontype=ACTION_EXECBUILTIN):
+ """
+ Keyword arguments:
+ actionmessage -- the ActionString
+ actiontype -- The ActionType the ActionString should be sent to.
+ """
+ packet = PacketACTION(actionmessage, actiontype)
+ packet.send(self.sock, self.addr, self.uid)
+
+ def _get_icon_type(self, icon_file):
+ if icon_file:
+ if icon_file.lower()[-3:] == "png":
+ return ICON_PNG
+ elif icon_file.lower()[-3:] == "gif":
+ return ICON_GIF
+ elif icon_file.lower()[-3:] == "jpg":
+ return ICON_JPEG
+ return ICON_NONE
diff --git a/tools/EventClients/lib/python/zeroconf.py b/tools/EventClients/lib/python/zeroconf.py
new file mode 100644
index 0000000..ee2af14
--- /dev/null
+++ b/tools/EventClients/lib/python/zeroconf.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2008-2013 Team XBMC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+"""
+Simple wrapper around Avahi
+"""
+
+__author__ = "d4rk@xbmc.org"
+__version__ = "0.1"
+
+try:
+ import time
+ import dbus, avahi
+ from dbus import DBusException
+ from dbus.mainloop.glib import DBusGMainLoop
+ from gi.repository import GLib
+except Exception as e:
+ print("Zeroconf support disabled. To enable, install the following Python modules:")
+ print(" dbus, gi, avahi")
+ pass
+
+SERVICE_FOUND = 1
+SERVICE_LOST = 2
+
+class Browser:
+ """ Simple Zeroconf Browser """
+
+ def __init__( self, service_types = {} ):
+ """
+ service_types - dictionary of services => handlers
+ """
+ self._stop = False
+ self.loop = DBusGMainLoop()
+ self.bus = dbus.SystemBus( mainloop=self.loop )
+ self.server = dbus.Interface( self.bus.get_object( avahi.DBUS_NAME, '/' ),
+ 'org.freedesktop.Avahi.Server')
+ self.handlers = {}
+
+ for type in service_types.keys():
+ self.add_service( type, service_types[ type ] )
+
+
+ def add_service( self, type, handler = None ):
+ """
+ Add a service that the browser should watch for
+ """
+ self.sbrowser = dbus.Interface(
+ self.bus.get_object(
+ avahi.DBUS_NAME,
+ self.server.ServiceBrowserNew(
+ avahi.IF_UNSPEC,
+ avahi.PROTO_UNSPEC,
+ type,
+ 'local',
+ dbus.UInt32(0)
+ )
+ ),
+ avahi.DBUS_INTERFACE_SERVICE_BROWSER)
+ self.handlers[ type ] = handler
+ self.sbrowser.connect_to_signal("ItemNew", self._new_item_handler)
+ self.sbrowser.connect_to_signal("ItemRemove", self._remove_item_handler)
+
+
+ def run(self):
+ """
+ Run the GLib event loop
+ """
+ # Don't use loop.run() because Python's GIL will block all threads
+ loop = GLib.MainLoop()
+ context = loop.get_context()
+ while not self._stop:
+ if context.pending():
+ context.iteration( True )
+ else:
+ time.sleep(1)
+
+ def stop(self):
+ """
+ Stop the GLib event loop
+ """
+ self._stop = True
+
+
+ def _new_item_handler(self, interface, protocol, name, stype, domain, flags):
+ if flags & avahi.LOOKUP_RESULT_LOCAL:
+ # local service, skip
+ pass
+
+ self.server.ResolveService(
+ interface,
+ protocol,
+ name,
+ stype,
+ domain,
+ avahi.PROTO_UNSPEC,
+ dbus.UInt32(0),
+ reply_handler = self._service_resolved_handler,
+ error_handler = self._error_handler
+ )
+ return
+
+
+ def _remove_item_handler(self, interface, protocol, name, stype, domain, flags):
+ if self.handlers[ stype ]:
+ # FIXME: more details needed here
+ try:
+ self.handlers[ stype ]( SERVICE_LOST, { 'type' : stype, 'name' : name } )
+ except:
+ pass
+
+
+ def _service_resolved_handler( self, *args ):
+ service = {}
+ service['type'] = str( args[3] )
+ service['name'] = str( args[2] )
+ service['address'] = str( args[7] )
+ service['hostname'] = str( args[5] )
+ service['port'] = int( args[8] )
+
+ # if the service type has a handler call it
+ try:
+ if self.handlers[ args[3] ]:
+ self.handlers[ args[3] ]( SERVICE_FOUND, service )
+ except:
+ pass
+
+
+ def _error_handler( self, *args ):
+ print('ERROR: %s ' % str( args[0] ))
+
+
+if __name__ == "__main__":
+ def service_handler( found, service ):
+ print("---------------------")
+ print(['Found Service', 'Lost Service'][found-1])
+ for key in service.keys():
+ print(key+" : "+str( service[key] ))
+
+ browser = Browser( {
+ '_xbmc-events._udp' : service_handler,
+ '_xbmc-web._tcp' : service_handler
+ } )
+ browser.run()
+
diff --git a/tools/Linux/firewalld-services/kodi-eventserver.xml b/tools/Linux/firewalld-services/kodi-eventserver.xml
new file mode 100644
index 0000000..68cdb3c
--- /dev/null
+++ b/tools/Linux/firewalld-services/kodi-eventserver.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<service>
+ <short>Kodi EventServer</short>
+ <description>Kodi is a free cross-platform media-player jukebox and entertainment hub. Enable this option to remotely control Kodi via its EventServer API.</description>
+ <port protocol="udp" port="9777"/>
+</service>
diff --git a/tools/Linux/firewalld-services/kodi-http.xml b/tools/Linux/firewalld-services/kodi-http.xml
new file mode 100644
index 0000000..863c251
--- /dev/null
+++ b/tools/Linux/firewalld-services/kodi-http.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<service>
+ <short>Kodi web interface</short>
+ <description>Kodi is a free cross-platform media-player jukebox and entertainment hub. Enable this option to remotely control Kodi via its web interface.</description>
+ <port protocol="tcp" port="8080"/>
+</service>
diff --git a/tools/Linux/firewalld-services/kodi-jsonrpc.xml b/tools/Linux/firewalld-services/kodi-jsonrpc.xml
new file mode 100644
index 0000000..08ed2af
--- /dev/null
+++ b/tools/Linux/firewalld-services/kodi-jsonrpc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<service>
+ <short>Kodi JSON-RPC</short>
+ <description>Kodi is a free cross-platform media-player jukebox and entertainment hub. Enable this option to remotely control Kodi via its JSON-RPC API.</description>
+ <port protocol="tcp" port="9090"/>
+</service>
diff --git a/tools/Linux/kodi-standalone.sh.in b/tools/Linux/kodi-standalone.sh.in
new file mode 100644
index 0000000..956e193
--- /dev/null
+++ b/tools/Linux/kodi-standalone.sh.in
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# Copyright (C) 2009-2015 Team XBMC
+# http://kodi.tv
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with XBMC; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+bindir="@bindir@"
+bin_name=@APP_NAME_LC@
+APP="${bindir}/${bin_name} --standalone $@"
+
+@XBMC_STANDALONE_SH_PULSE@
+
+LOOP=1
+CRASHCOUNT=0
+LASTSUCCESSFULSTART=$(date +%s)
+
+while [ $LOOP -eq 1 ]
+do
+ $APP
+ RET=$?
+ NOW=$(date +%s)
+ if [ $RET -ge 64 ] && [ $RET -le 66 ] || [ $RET -eq 0 ]; then # clean exit
+ LOOP=0
+ else # crash
+ DIFF=$((NOW-LASTSUCCESSFULSTART))
+ if [ $DIFF -gt 60 ]; then # Not on startup, ignore
+ LASTSUCESSFULSTART=$NOW
+ CRASHCOUNT=0
+ else # at startup, look sharp
+ CRASHCOUNT=$((CRASHCOUNT+1))
+ if [ $CRASHCOUNT -ge 3 ]; then # Too many, bail out
+ LOOP=0
+ echo "${APP} has exited in an unclean state 3 times in the last ${DIFF} seconds."
+ echo "Something is probably wrong"
+ fi
+ fi
+ fi
+done
diff --git a/tools/Linux/kodi-standalone.sh.pulse b/tools/Linux/kodi-standalone.sh.pulse
new file mode 100644
index 0000000..e77efe8
--- /dev/null
+++ b/tools/Linux/kodi-standalone.sh.pulse
@@ -0,0 +1,4 @@
+PULSE_START="$(command -v start-pulseaudio-x11)"
+if [ -n "$PULSE_START" ]; then
+ $PULSE_START
+fi
diff --git a/tools/Linux/kodi-xsession.desktop.in b/tools/Linux/kodi-xsession.desktop.in
new file mode 100644
index 0000000..c9f8c43
--- /dev/null
+++ b/tools/Linux/kodi-xsession.desktop.in
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=@APP_NAME@
+Comment=This session will start @APP_NAME@ media center
+Exec=@APP_NAME_LC@-standalone
+TryExec=@APP_NAME_LC@-standalone
+Type=Application
+Keywords=audio;video;media;center;tv;movies;series;songs;remote;
+Icon=@APP_NAME_LC@
diff --git a/tools/Linux/kodi.desktop.in b/tools/Linux/kodi.desktop.in
new file mode 100644
index 0000000..71d3f7d
--- /dev/null
+++ b/tools/Linux/kodi.desktop.in
@@ -0,0 +1,25 @@
+[Desktop Entry]
+Version=1.0
+Name=@APP_NAME@
+GenericName=Media Center
+GenericName[zh_CN]=媒体中心
+Comment=Manage and view your media
+Comment[ru]=Просмотр и управление мультимедиа
+Comment[zh_CN]=管理和查看您的媒体
+Exec=@APP_NAME_LC@
+Icon=@APP_NAME_LC@
+Terminal=false
+Type=Application
+Categories=AudioVideo;Video;Player;TV;
+
+Actions=Fullscreen;Standalone;
+
+[Desktop Action Fullscreen]
+Name=Open in fullscreen
+Name[zh_CN]=全屏打开
+Exec=@APP_NAME_LC@ -fs
+
+[Desktop Action Standalone]
+Name=Open in standalone mode
+Name[zh_CN]=在独立模式下打开
+Exec=@APP_NAME_LC@ --standalone
diff --git a/tools/Linux/kodi.metainfo.xml.in b/tools/Linux/kodi.metainfo.xml.in
new file mode 100644
index 0000000..998c631
--- /dev/null
+++ b/tools/Linux/kodi.metainfo.xml.in
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component type="desktop-application">
+ <id>@APP_PACKAGE@</id>
+ <name>@APP_NAME@</name>
+ <project_license>GPL-2.0-only GPL-2.0-or-later LGPL-2.1-or-later MIT BSD-3-Clause BSD-4-Clause</project_license>
+ <metadata_license>CC0-1.0</metadata_license>
+ <developer_name>Team Kodi</developer_name>
+ <summary>Ultimate entertainment center</summary>
+ <url type="homepage">https://kodi.tv/</url>
+ <url type="donation">https://kodi.tv/contribute/donate</url>
+ <url type="bugtracker">https://github.com/xbmc/xbmc/issues</url>
+ <url type="faq">https://kodi.wiki/view/FAQs</url>
+ <url type="help">https://forum.kodi.tv/</url>
+ <url type="translate">https://kodi.weblate.cloud/</url>
+ <url type="contribute">https://github.com/xbmc/xbmc/blob/master/docs/CONTRIBUTING.md</url>
+ <url type="vcs-browser">https://github.com/xbmc/xbmc/</url>
+ <description>
+ <p>Kodi allows users to play and view videos, music, podcasts,
+ and other digital media files from local storage, network storage
+ and the internet. It's optimized for a 10-foot user interface to be
+ used with televisions and remote controls.</p>
+
+ <p>Kodi spawned from the love of media. It is an entertainment hub
+ that brings all your digital media together into a beautiful
+ and user friendly package. It is 100% free and open source,
+ very customisable and runs on a wide variety of devices. It is
+ supported by a dedicated team of volunteers and a huge community.</p>
+ </description>
+ <keywords>
+ <keyword>Kodi</keyword>
+ <keyword>xbmc</keyword>
+ <keyword>audio</keyword>
+ <keyword>video</keyword>
+ <keyword>media</keyword>
+ <keyword>media center</keyword>
+ <keyword>music</keyword>
+ <keyword>tv</keyword>
+ <keyword>television</keyword>
+ <keyword>remote control</keyword>
+ </keywords>
+ <launchable type="desktop-id">@APP_NAME_LC@.desktop</launchable>
+ <screenshots>
+ <screenshot type="default">
+ <image>https://mirrors.kodi.tv/screenshots/kodi-recently-added.jpg</image>
+ <caption>The homescreen keeps your media organized</caption>
+ </screenshot>
+ <screenshot>
+ <image>https://mirrors.kodi.tv/screenshots/kodi-videolibrary.jpg</image>
+ <caption>Easily browse your movies and series</caption>
+ </screenshot>
+ <screenshot>
+ <image>https://mirrors.kodi.tv/screenshots/kodi-video-info.jpg</image>
+ <caption>Get additional infos about your movies or series</caption>
+ </screenshot>
+ <screenshot>
+ <image>https://mirrors.kodi.tv/screenshots/kodi-tvshow.jpg</image>
+ <caption>Browse TV shows by seasons</caption>
+ </screenshot>
+ <screenshot>
+ <image>https://mirrors.kodi.tv/screenshots/kodi-music-info.jpg</image>
+ <caption>Use the music library to organize and read about your artists</caption>
+ </screenshot>
+ <screenshot>
+ <image>https://mirrors.kodi.tv/screenshots/kodi-epg.jpg</image>
+ <caption>Use the EPG to manage your TV stations</caption>
+ </screenshot>
+ <screenshot>
+ <image>https://mirrors.kodi.tv/screenshots/kodi-addons.jpg</image>
+ <caption>Extend what Kodi can do, just use addons</caption>
+ </screenshot>
+ <screenshot>
+ <image>https://mirrors.kodi.tv/screenshots/kodi-weather.jpg</image>
+ <caption>Keep the weather in check</caption>
+ </screenshot>
+ <screenshot>
+ <image>https://mirrors.kodi.tv/screenshots/kodi-webinterface.jpg</image>
+ <caption>The webinterface enables you to manage your Kodi from other devices</caption>
+ </screenshot>
+ </screenshots>
+ <releases>
+ <release date="2024-02-10" version="20.4-Nexus" type="stable"><url>https://kodi.tv/article/kodi-20-4-nexus-release/</url></release>
+ <release date="2024-01-09" version="20.3-Nexus" type="stable"><url>https://kodi.tv/article/kodi-20-3-nexus-release/</url></release>
+ <release date="2023-06-29" version="20.2-Nexus" type="stable"><url>https://kodi.tv/article/kodi-20-2-nexus-release/</url></release>
+ <release date="2023-03-11" version="20.1-Nexus" type="stable"><url>https://kodi.tv/article/kodi-20-1-nexus-release/</url></release>
+ <release date="2023-01-15" version="20.0-Nexus" type="stable"><url>https://kodi.tv/article/kodi-20-0-nexus-release/</url></release>
+ <release date="2022-12-21" version="20.0~rc2-Nexus" type="development"><url>https://kodi.tv/article/kodi-nexus-rc-2/</url></release>
+ <release date="2022-12-10" version="20.0~rc1-Nexus" type="development"><url>https://kodi.tv/article/kodi-nexus-rc-1/</url></release>
+ <release date="2022-11-08" version="20.0~b1-Nexus" type="development"><url>https://kodi.tv/article/kodi-nexus-beta-1/</url></release>
+ <release date="2022-09-08" version="20.0~a3-Nexus" type="development"><url>https://kodi.tv/article/kodi-nexus-alpha-3/</url></release>
+ <release date="2022-07-09" version="20.0~a2-Nexus" type="development"><url>https://kodi.tv/article/kodi-nexus-alpha-2/</url></release>
+ <release date="2022-05-16" version="20.0~a1-Nexus" type="development"><url>https://kodi.tv/article/kodi-nexus-alpha-1/</url></release>
+ <release date="2022-03-03" version="19.4-Matrix"/>
+ <release date="2021-10-24" version="19.3-Matrix"/>
+ <release date="2021-10-08" version="19.2-Matrix"/>
+ <release date="2021-05-09" version="19.1-Matrix"/>
+ <release date="2021-02-19" version="19.0-Matrix"/>
+ <release date="2020-10-24" version="18.9-Leia"/>
+ <release date="2020-07-28" version="18.8-Leia"/>
+ <release date="2020-05-21" version="18.7-Leia"/>
+ <release date="2020-02-29" version="18.6-Leia"/>
+ <release date="2019-11-18" version="18.5-Leia"/>
+ <release date="2019-08-31" version="18.4-Leia"/>
+ <release date="2019-06-27" version="18.3-Leia"/>
+ <release date="2019-04-22" version="18.2-Leia"/>
+ <release date="2019-02-17" version="18.1-Leia"/>
+ </releases>
+ <content_rating type="oars-1.0">
+ <content_attribute id="violence-cartoon">none</content_attribute>
+ <content_attribute id="violence-fantasy">none</content_attribute>
+ <content_attribute id="violence-realistic">none</content_attribute>
+ <content_attribute id="violence-bloodshed">none</content_attribute>
+ <content_attribute id="violence-sexual">none</content_attribute>
+ <content_attribute id="drugs-alcohol">none</content_attribute>
+ <content_attribute id="drugs-narcotics">none</content_attribute>
+ <content_attribute id="drugs-tobacco">none</content_attribute>
+ <content_attribute id="sex-nudity">none</content_attribute>
+ <content_attribute id="sex-themes">none</content_attribute>
+ <content_attribute id="language-profanity">none</content_attribute>
+ <content_attribute id="language-humor">none</content_attribute>
+ <content_attribute id="language-discrimination">none</content_attribute>
+ <content_attribute id="social-chat">none</content_attribute>
+ <content_attribute id="social-info">none</content_attribute>
+ <content_attribute id="social-audio">none</content_attribute>
+ <content_attribute id="social-location">none</content_attribute>
+ <content_attribute id="social-contacts">none</content_attribute>
+ <content_attribute id="money-purchasing">none</content_attribute>
+ <content_attribute id="money-gambling">none</content_attribute>
+ </content_rating>
+ <recommends>
+ <control>keyboard</control>
+ <control>pointing</control>
+ <control>touch</control>
+ <control>tv-remote</control>
+ <control>gamepad</control>
+ <control>tablet</control>
+ </recommends>
+</component>
diff --git a/tools/Linux/kodi.sh.in b/tools/Linux/kodi.sh.in
new file mode 100644
index 0000000..11cace2
--- /dev/null
+++ b/tools/Linux/kodi.sh.in
@@ -0,0 +1,192 @@
+#!/bin/sh
+
+# Copyright (C) 2008-2017 Team XBMC
+# http://kodi.tv
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with XBMC; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+APP=@APP_NAME@
+bin_name=@APP_NAME_LC@
+SAVED_ARGS="$@"
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+datarootdir="@datarootdir@"
+LIBDIR="@libdir@"
+APP_BINARY=$LIBDIR/${bin_name}/@APP_BINARY@
+CRASHLOG_DIR=${CRASHLOG_DIR:-$HOME}
+KODI_DATA=${KODI_DATA:-"${HOME}/.${bin_name}"} # mapped to special://home/
+
+# Workaround for high CPU load with nvidia GFX
+export __GL_YIELD=USLEEP
+
+# Fix wasting RAM due to fragmentation
+export MALLOC_MMAP_THRESHOLD_=131072
+
+# Check for some options used by this script
+while [ "$#" -gt "0" ]
+do
+ case "$1" in
+ --setlibdir)
+ LIBDIR="$2"
+ shift; shift
+ ;;
+ *)
+ shift
+ ;;
+ esac
+done
+
+KODI_BINARY=${APP_BINARY}
+
+if [ ! -x ${KODI_BINARY} ]; then
+ echo "Error: ${KODI_BINARY} not found"
+ exit 2
+fi
+
+APPORT_CORE="/var/crash/$(echo -n ${KODI_BINARY}|tr / _).$(id -u).crash"
+
+command_exists()
+{
+ command -pv $1 >/dev/null 2>&1
+}
+
+single_stacktrace()
+{
+ # core filename is either "core.$PID" or "core"
+ find "$1" -maxdepth $2 -name 'core*' | while read core; do
+ LC_ALL=C gdb --core="$core" --batch 2> /dev/null | grep -q "^Core was generated by \`${KODI_BINARY}" || continue
+ echo "=====> Core file: "$core" ($(stat -c%y "$core"))" >> $FILE
+ echo " =========================================" >> $FILE
+ gdb "${KODI_BINARY}" --core="$core" --batch -ex "thread apply all bt" 2> /dev/null >> $FILE
+ rm -f "$core"
+ done
+}
+
+print_crash_report()
+{
+ FILE="$CRASHLOG_DIR/${bin_name}_crashlog-`date +%Y%m%d_%H%M%S`.log"
+ echo "############## $APP CRASH LOG ###############" >> $FILE
+ echo >> $FILE
+ echo "################ SYSTEM INFO ################" >> $FILE
+ printf " Date: " >> $FILE
+ date >> $FILE
+ echo " $APP Options: $*" >> $FILE
+ printf " Arch: " >> $FILE
+ uname -m >> $FILE
+ printf " Kernel: " >> $FILE
+ uname -rvs >> $FILE
+ printf " Release: " >> $FILE
+ if [ -f /etc/os-release ]; then
+ . /etc/os-release
+ echo $NAME $VERSION >> $FILE
+ elif command_exists lsb_release; then
+ echo >> $FILE
+ lsb_release -a 2> /dev/null | sed -e 's/^/ /' >> $FILE
+ else
+ echo "lsb_release not available" >> $FILE
+ fi
+ echo "############## END SYSTEM INFO ##############" >> $FILE
+ echo >> $FILE
+ echo "############### STACK TRACE #################" >> $FILE
+ if command_exists gdb; then
+ if command_exists systemd-coredumpctl; then
+ systemd-coredumpctl dump -o core $(basename ${KODI_BINARY}) > /dev/null 2>&1
+ elif command_exists coredumpctl; then
+ coredumpctl dump -o core $(basename ${KODI_BINARY}) > /dev/null 2>&1
+ elif command_exists apport-unpack && test -f "${APPORT_CORE}"; then
+ TMP_DIR="$(mktemp -d -p ${HOME})"
+ if [ -d "${TMP_DIR}" ]; then
+ rm -f "${HOME}/core"
+ apport-unpack "${APPORT_CORE}" "${TMP_DIR}"
+ mv "${TMP_DIR}/CoreDump" "${HOME}/core"
+ rm -rf "${TMP_DIR}"
+ fi
+ fi
+ single_stacktrace "$PWD" 1
+ # Find in plugins directories
+ if [ $KODI_HOME ]; then
+ BASEDIR=$KODI_HOME
+ else
+ BASEDIR="$LIBDIR/${bin_name}/"
+ fi
+ single_stacktrace "$BASEDIR" 5
+ # find in userdata dir
+ single_stacktrace "$HOME" 5
+ # try /proc/sys/kernel/core_pattern
+ # Check if it does not contain a pipe to a program (see man 5 core)
+ if [ "$(cat /proc/sys/kernel/core_pattern | cut -c 1)" != "|" ]; then
+ [ -d "$(dirname $(cat /proc/sys/kernel/core_pattern))" ] && single_stacktrace "$(dirname $(cat /proc/sys/kernel/core_pattern))" 1
+ fi
+ else
+ echo "gdb not installed, can't get stack trace." >> $FILE
+ fi
+ echo "############# END STACK TRACE ###############" >> $FILE
+ echo >> $FILE
+ echo "################# LOG FILE ##################" >> $FILE
+ echo >> $FILE
+ if [ -f $KODI_TEMP/@APP_NAME_LC@.log ]
+ then
+ cat $KODI_TEMP/@APP_NAME_LC@.log >> $FILE
+ echo >> $FILE
+ elif [ -f $KODI_DATA/temp/@APP_NAME_LC@.log ]
+ then
+ cat $KODI_DATA/temp/@APP_NAME_LC@.log >> $FILE
+ echo >> $FILE
+ else
+ echo "Logfile not found in the usual place." >> $FILE
+ echo "Please attach it separately." >> $FILE
+ echo "Use pastebin.com or similar for forums or IRC." >> $FILE
+ fi
+ echo >> $FILE
+ echo "############### END LOG FILE ################" >> $FILE
+ echo >> $FILE
+ echo "############ END $APP CRASH LOG #############" >> $FILE
+ echo "Crash report available at $FILE"
+}
+
+propagate_sigterm() {
+ kill -TERM "$CHILD" 2>/dev/null
+}
+
+trap propagate_sigterm TERM
+
+if command_exists gdb; then
+ # Output warning in case ulimit is unsupported by shell
+ eval ulimit -c unlimited
+ if [ ! $? = "0" ]; then
+ echo "${bin_name}: ulimit is unsupported by this shell" 1>&2
+ fi
+fi
+
+LOOP=1
+while [ $(( $LOOP )) = "1" ]
+do
+ [ -f "${APPORT_CORE}" ] && rm -f "${APPORT_CORE}"
+ LOOP=0
+ ${KODI_BINARY} $SAVED_ARGS &
+ CHILD=$!
+ wait "${CHILD}"
+ RET=$?
+ if [ $RET -eq 65 ]
+ then # User requested to restart app
+ LOOP=1
+ elif [ $RET -ge 131 ] && [ $RET -le 136 ] || [ $RET -eq 139 ]
+ then # Crashed with core dump
+ print_crash_report
+ fi
+done
+
+exit $RET
diff --git a/tools/Linux/packaging/README.debian b/tools/Linux/packaging/README.debian
new file mode 100644
index 0000000..5e217d3
--- /dev/null
+++ b/tools/Linux/packaging/README.debian
@@ -0,0 +1,31 @@
+--- How to build a Kodi Debian package ---
+
+There are two available build methods:
+1.) debuild / debhelper
+ Requirements: debhelper, devscripts, all Kodi build deps
+ sudo apt-get install debhelper devscripts
+ sudo apt-get build-dep kodi (if you have one of our repos/ppas added, else read docs/README.Linux.md or docs/README.Ubuntu.md)
+
+ Result: Debian package for your host distribution and architecture only
+ Recommended for local installs
+
+ Example Usage: ./mk-debian-package.sh
+
+2.) pdebuild / pbuilder
+ Requirements: pbuilder, devscripts, proper pbuilder environment
+ For a comprehensive example how to setup pbuilder read:
+ https://wiki.ubuntu.com/PbuilderHowto
+
+ Result: Debian package for arbitrary Debian based distributions and architectures.
+ Recommended for hosting your own apt repository or (clean room) compile testing for various distributions
+
+ Example Usage:
+ RELEASEV=16 \
+ DISTS=-"unstable" \
+ ARCHS="i386 amd64" \
+ BUILDER="pdebuild" \
+ PDEBUILD_OPTS="--debbuildopts \"-j4\"" \
+ PBUILDER_BASE="/home/$USER/xbmc-packaging/pbuilder" \
+ DPUT_TARGET="local" \
+ ./mk-debian-package.sh
+
diff --git a/tools/Linux/packaging/media/icon128x128.png b/tools/Linux/packaging/media/icon128x128.png
new file mode 100644
index 0000000..8a25c4a
--- /dev/null
+++ b/tools/Linux/packaging/media/icon128x128.png
Binary files differ
diff --git a/tools/Linux/packaging/media/icon16x16.png b/tools/Linux/packaging/media/icon16x16.png
new file mode 100644
index 0000000..9b27352
--- /dev/null
+++ b/tools/Linux/packaging/media/icon16x16.png
Binary files differ
diff --git a/tools/Linux/packaging/media/icon22x22.png b/tools/Linux/packaging/media/icon22x22.png
new file mode 100644
index 0000000..21f76e5
--- /dev/null
+++ b/tools/Linux/packaging/media/icon22x22.png
Binary files differ
diff --git a/tools/Linux/packaging/media/icon24x24.png b/tools/Linux/packaging/media/icon24x24.png
new file mode 100644
index 0000000..dad983b
--- /dev/null
+++ b/tools/Linux/packaging/media/icon24x24.png
Binary files differ
diff --git a/tools/Linux/packaging/media/icon256x256.png b/tools/Linux/packaging/media/icon256x256.png
new file mode 100644
index 0000000..cc2ee49
--- /dev/null
+++ b/tools/Linux/packaging/media/icon256x256.png
Binary files differ
diff --git a/tools/Linux/packaging/media/icon32x32.png b/tools/Linux/packaging/media/icon32x32.png
new file mode 100644
index 0000000..c0a0534
--- /dev/null
+++ b/tools/Linux/packaging/media/icon32x32.png
Binary files differ
diff --git a/tools/Linux/packaging/media/icon48x48.png b/tools/Linux/packaging/media/icon48x48.png
new file mode 100644
index 0000000..898c023
--- /dev/null
+++ b/tools/Linux/packaging/media/icon48x48.png
Binary files differ
diff --git a/tools/Linux/packaging/media/icon64x64.png b/tools/Linux/packaging/media/icon64x64.png
new file mode 100644
index 0000000..700144b
--- /dev/null
+++ b/tools/Linux/packaging/media/icon64x64.png
Binary files differ
diff --git a/tools/Linux/packaging/mk-debian-package.sh b/tools/Linux/packaging/mk-debian-package.sh
new file mode 100755
index 0000000..ad81be0
--- /dev/null
+++ b/tools/Linux/packaging/mk-debian-package.sh
@@ -0,0 +1,187 @@
+#!/bin/bash
+#
+# Copyright (C) 2013 Team XBMC
+# http://kodi.tv
+#
+# This Program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with XBMC; see the file COPYING. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+
+
+RELEASEV=${RELEASEV:-"auto"}
+VERSION_PREFIX=${VERSION_PREFIX:-""}
+TAG=${TAG}
+TAGREV=${TAGREV:-""}
+REPO_DIR=${WORKSPACE:-$(cd "$(dirname $0)/../../../" ; pwd)}
+[[ $(which lsb_release) ]] && DISTS=${DISTS:-$(lsb_release -cs)} || DISTS=${DISTS:-"stable"}
+ARCHS=${ARCHS:-$(dpkg --print-architecture)}
+BUILDER=${BUILDER:-"debuild"}
+DEBUILD_OPTS=${DEBUILD_OPTS:-""}
+PDEBUILD_OPTS=${PDEBUILD_OPTS:-""}
+PBUILDER_BASE=${PBUILDER_BASE:-"/var/cache/pbuilder"}
+DPUT_TARGET=${DPUT_TARGET:-"local"}
+DEBIAN=${DEBIAN:-"https://github.com/xbmc/xbmc-packaging/archive/master.tar.gz"}
+BUILD_DATE=$(date '+%Y%m%d.%H%M')
+
+function usage {
+ echo "$0: This script builds a Kodi debian package from a git repository."
+ echo "The build is controlled by ENV variables, which can be overridden as appropriate:"
+ echo "BUILDER is either debuild(default) or pdebuild(needs a proper pbuilder setup)"
+ checkEnv
+}
+
+function checkEnv {
+ echo "#------ build environment ------#"
+ echo "REPO_DIR: $REPO_DIR"
+ getVersion
+ echo "RELEASEV: $RELEASEV"
+ echo "REVISION: $TAGREV"
+ [[ -n $TAG ]] && echo "TAG: $TAG"
+ echo "DISTS: $DISTS"
+ echo "ARCHS: $ARCHS"
+ echo "DEBIAN: $DEBIAN"
+ echo "BUILDER: $BUILDER"
+ echo "CONFIGURATION: $Configuration"
+
+ if ! [[ $(which $BUILDER) ]]
+ then
+ echo "Error: can't find ${BUILDER}, consider using full path to [debuild|pdebuild]"
+ exit 1
+ fi
+
+ if [[ "$BUILDER" =~ "pdebuild" ]]
+ then
+ if ! [[ -d $PBUILDER_BASE ]] ; then echo "Error: $PBUILDER_BASE does not exist"; exit 1; fi
+ echo "PBUILDER_BASE: $PBUILDER_BASE"
+ echo "PDEBUILD_OPTS: $PDEBUILD_OPTS"
+ else
+ echo "DEBUILD_OPTS: $DEBUILD_OPTS"
+ fi
+
+ echo "#-------------------------------#"
+}
+
+function getVersion {
+ getGitRev
+ if [[ $RELEASEV == "auto" ]]
+ then
+ local MAJORVER=$(grep VERSION_MAJOR $REPO_DIR/version.txt | awk '{ print $2 }')
+ local MINORVER=$(grep VERSION_MINOR $REPO_DIR/version.txt | awk '{ print $2 }')
+ RELEASEV=${MAJORVER}.${MINORVER}
+ else
+ PACKAGEVERSION="${RELEASEV}~git${BUILD_DATE}-${TAG}"
+ fi
+
+ if [[ -n ${VERSION_PREFIX} ]]
+ then
+ PACKAGEVERSION="${VERSION_PREFIX}:${RELEASEV}~git${BUILD_DATE}-${TAG}"
+ else
+ PACKAGEVERSION="${RELEASEV}~git${BUILD_DATE}-${TAG}"
+ fi
+}
+
+function getGitRev {
+ cd $REPO_DIR || exit 1
+ REV=$(git log -1 --pretty=format:"%h")
+ [[ -z $TAG ]] && TAG=$REV
+ [[ -z $TAGREV ]] && TAGREV=0
+}
+
+function archiveRepo {
+ cd $REPO_DIR || exit 1
+ git clean -xfd
+ echo $REV > VERSION
+ tools/depends/target/ffmpeg/autobuild.sh -d
+ DEST="kodi-${RELEASEV}~git${BUILD_DATE}-${TAG}"
+ [[ -d debian ]] && rm -rf debian
+ cd ..
+ tar -czf ${DEST}.tar.gz --exclude .git $(basename $REPO_DIR)
+ ln -s ${DEST}.tar.gz ${DEST/-/_}.orig.tar.gz
+ echo "Output Archive: ${DEST}.tar.gz"
+
+ cd $REPO_DIR || exit 1
+ getDebian
+}
+
+function getDebian {
+ if [[ -d $DEBIAN ]]
+ then
+ cp -r $DEBIAN .
+ else
+ mkdir tmp && cd tmp
+ curl -L -s $DEBIAN -o debian.tar.gz
+ tar xzf debian.tar.gz
+ cd xbmc-packaging-*
+ for FILE in *.unified; do mv $FILE debian/${FILE%.unified}; done
+ mv debian $REPO_DIR
+ cd $REPO_DIR ; rm -rf tmp
+ fi
+}
+
+function buildDebianPackages {
+ archiveRepo
+ cd $REPO_DIR || exit 1
+ sed -e "s/#PACKAGEVERSION#/${PACKAGEVERSION}/g" -e "s/#TAGREV#/${TAGREV}/g" debian/changelog.in > debian/changelog.tmp
+ [ "$Configuration" == "Debug" ] && sed -i "s/XBMC_RELEASE = yes/XBMC_RELEASE = no/" debian/rules
+
+ for dist in $DISTS
+ do
+ sed "s/#DIST#/${dist}/g" debian/changelog.tmp > debian/changelog
+ for arch in $ARCHS
+ do
+ cd $REPO_DIR
+ echo "building: DIST=$dist ARCH=$arch"
+ if [[ "$BUILDER" =~ "pdebuild" ]]
+ then
+ DIST=$dist ARCH=$arch $BUILDER $PDEBUILD_OPTS
+ [ $? -eq 0 ] && uploadPkg || exit 1
+ else
+ $BUILDER $DEBUILD_OPTS
+ echo "output directory: $REPO_DIR/.."
+ fi
+ done
+ done
+}
+
+function uploadPkg {
+ PKG="${PBUILDER_BASE}/${dist}-${arch}/result/${DEST/-/_}-${TAGREV}_${arch}.changes"
+ echo "signing package"
+ debsign $PKG
+ echo "uploading $PKG to $DPUT_TARGET"
+ dput $DPUT_TARGET $PKG
+ UPLOAD_DONE=$?
+}
+
+function cleanup {
+ if [[ $UPLOAD_DONE -eq 0 ]] && [[ "$BUILDER" =~ "pdebuild" ]]
+ then
+ cd $REPO_DIR/.. || exit 1
+ rm ${DEST}*
+ rm ${DEST/-/_}*
+ fi
+}
+
+###
+# main
+###
+if [[ $1 = "-h" ]] || [[ $1 = "--help" ]]
+then
+ usage
+ exit
+fi
+
+checkEnv
+buildDebianPackages
+cleanup
+
diff --git a/tools/Linux/packaging/package-kodi-launchpad.sh b/tools/Linux/packaging/package-kodi-launchpad.sh
new file mode 100755
index 0000000..d6e7c51
--- /dev/null
+++ b/tools/Linux/packaging/package-kodi-launchpad.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+releaseversion=${VERSION:-"AUTO"}
+epoch=${EPOCH:-"2"}
+gitrev=${GITREV:-"$(git log -1 --pretty=format:"%h")"}
+tag=${TAG:-${gitrev}}
+tagrev=${tagrev:-"0"}
+dists=${DISTS:-"hirsute groovy focal bionic"}
+gpgkey=${GPG_KEY:-"jenkins (jenkins build bot) <jenkins@kodi.tv>"}
+ppa=${PPA:-"nightly"}
+debianrepo="${DEBIAN:-"https://github.com/xbmc/xbmc-packaging"}"
+
+if [ "$releaseversion" = "AUTO" ]; then
+ majorversion="$(awk '/VERSION_MAJOR/ {print $2}' version.txt)"
+ minorversion="$(awk '/VERSION_MINOR/ {print $2}' version.txt)"
+ releaseversion="${majorversion}.${minorversion}"
+fi
+
+version="${releaseversion}+git$(date '+%Y%m%d.%H%M')-${tag}"
+debversion="${epoch}:${version}"
+origtarball="kodi_${version}.orig.tar.gz"
+
+declare -A PPAS=(
+ ["nightly"]='ppa:team-xbmc/xbmc-nightly'
+ ["unstable"]='ppa:team-xbmc/unstable'
+ ["stable"]='ppa:team-xbmc/ppa'
+ ["wsnipex-nightly"]='ppa:wsnipex/kodi-git'
+ ["wsnipex-stable"]='ppa:wsnipex/kodi-stable'
+)
+
+# clean up before creating the source tarball
+git clean -xfd
+
+# set build info
+date '+%Y%m%d' > BUILDDATE
+echo $gitrev > VERSION
+
+# download packaging files
+wget -O - ${debianrepo}/archive/master.tar.gz | tar xzv --strip-components=1 --exclude=".git*" -f -
+[ -d debian ] || { echo "ERROR: directory debian does not exist"; exit 3; }
+
+# add tarballs for internal ffmpeg, libdvd
+tools/depends/target/ffmpeg/autobuild.sh -d || { echo "Error downloading ffmpeg"; exit 2; }
+make -C tools/depends/target/libdvdnav download || { echo "Error downloading libdvdnav"; exit 2; }
+make -C tools/depends/target/libdvdread download || { echo "Error downloading libdvdread"; exit 2; }
+make -C tools/depends/target/libdvdcss download || { echo "Error downloading libdvdcss"; exit 2; }
+make -C tools/depends/target/dav1d download || { echo "Error downloading dav1d"; exit 2; }
+
+# create orig tarball if needed
+if grep -q quilt debian/source/format; then
+ echo "origtarball: ${origtarball}"
+ git archive -o ../${origtarball} ${gitrev}
+fi
+
+
+# build source packages
+for dist in ${dists//,/ }; do
+ echo "### Building for ${dist} ###"
+ sed \
+ -e "s/#PACKAGEVERSION#/${debversion}/" \
+ -e "s/#TAGREV#/${tagrev}/" \
+ -e "s/#DIST#/${dist}/g" \
+ debian/changelog.in > debian/changelog
+
+ echo "Changelog:"
+ cat debian/changelog
+ echo
+
+ debuild -d -S -k"${gpgkey}"
+ echo "### DONE ###"
+done
+
+# upload to PPA
+echo "### Uploading to PPA ${PPAS[${ppa}]} ###"
+dput ${PPAS[${ppa}]} ../kodi_${version}*.changes
+if [ $? -eq 0 ]; then
+ echo "### Successfully pushed ${version} to launchpad ###"
+else
+ echo "### ERROR could not upload package ###"
+fi
+
diff --git a/tools/buildsteps/README b/tools/buildsteps/README
new file mode 100644
index 0000000..048ff84
--- /dev/null
+++ b/tools/buildsteps/README
@@ -0,0 +1,15 @@
+This folder holds all the platform dependent build scripts which are called from the jenkins buildserver.
+
+The following ENV variables are available on all scripts:
+
+$WORKSPACE - the folder where jenkins checked out the source - XBMC_HOME so to say
+$Configuration - its either Debug, Release or Default and should be taken into account if possible (Defaults select platform default from <platformdir>/startbuild)
+$SDK_VERSION - the requested SDK_VERSION to be used for building. If "Default" is passed it uses the platform default from <platformdir>/startbuild
+$BUILDTHREADS - number of threads which can be used when building (e.x. use it for make -j$BUILDTHREADS)
+$XBMC_DEPENDS_ROOT - root for installing the xbmc build depends and toolchain helpers. If "Default" is passed it uses the platform default from <platformdir>/startbuild
+
+Additional ENV variables might be specified by the buildnodes. For android buildslaves these are:
+
+TOOLCHAIN - the used toolchain dir
+NDK_PATH - the path to the android native ndk
+SDK_PATH - the path to the android sdk
diff --git a/tools/buildsteps/android-arm64-v8a/configure-depends b/tools/buildsteps/android-arm64-v8a/configure-depends
new file mode 100644
index 0000000..cec12b7
--- /dev/null
+++ b/tools/buildsteps/android-arm64-v8a/configure-depends
@@ -0,0 +1,18 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#the following path must exist on the slave and use the defined scheme here!
+NDK_PATH=$ANDROID_DEV_ROOT/android-ndk-r$NDK_VERSION
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;./configure \
+ --with-tarballs=$TARBALLS \
+ --host=aarch64-linux-android \
+ --with-sdk-path=$SDK_PATH \
+ --with-ndk-path=$NDK_PATH \
+ $(if [ "$NDK_API" != "Default" ]; then echo --with-ndk-api=$NDK_API;fi) \
+ --prefix=$XBMC_DEPENDS_ROOT \
+ $DEBUG_SWITCH
+fi
diff --git a/tools/buildsteps/android-arm64-v8a/configure-xbmc b/tools/buildsteps/android-arm64-v8a/configure-xbmc
new file mode 100644
index 0000000..81c0d3c
--- /dev/null
+++ b/tools/buildsteps/android-arm64-v8a/configure-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+make -C $WORKSPACE/tools/depends/target/cmakebuildsys
diff --git a/tools/buildsteps/android-arm64-v8a/make-binary-addons b/tools/buildsteps/android-arm64-v8a/make-binary-addons
new file mode 100644
index 0000000..3bb9e74
--- /dev/null
+++ b/tools/buildsteps/android-arm64-v8a/make-binary-addons
@@ -0,0 +1,29 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/android-arm64-v8a/make-depends b/tools/buildsteps/android-arm64-v8a/make-depends
new file mode 100644
index 0000000..c5869b2
--- /dev/null
+++ b/tools/buildsteps/android-arm64-v8a/make-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
+
diff --git a/tools/buildsteps/android-arm64-v8a/make-native-depends b/tools/buildsteps/android-arm64-v8a/make-native-depends
new file mode 100644
index 0000000..c327180
--- /dev/null
+++ b/tools/buildsteps/android-arm64-v8a/make-native-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ]
+then
+ git clean -xffd $WORKSPACE/tools/depends/native
+ cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
diff --git a/tools/buildsteps/android-arm64-v8a/make-xbmc b/tools/buildsteps/android-arm64-v8a/make-xbmc
new file mode 100644
index 0000000..11d8d70
--- /dev/null
+++ b/tools/buildsteps/android-arm64-v8a/make-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS || make
diff --git a/tools/buildsteps/android-arm64-v8a/package b/tools/buildsteps/android-arm64-v8a/package
new file mode 100644
index 0000000..d1ddf48
--- /dev/null
+++ b/tools/buildsteps/android-arm64-v8a/package
@@ -0,0 +1,14 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+TARGET=apk
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS $TARGET
+
+cd $WORKSPACE
+
+#rename for upload
+#e.x. xbmc-20130314-8c2fb31-Frodo-arm64-v8a.apk
+UPLOAD_FILENAME="kodi-$(getBuildRevDateStr)-arm64-v8a"
+mv kodiapp-arm64-v8a-*.apk $UPLOAD_FILENAME.apk
diff --git a/tools/buildsteps/android-arm64-v8a/prepare-depends b/tools/buildsteps/android-arm64-v8a/prepare-depends
new file mode 100644
index 0000000..b4d02b7
--- /dev/null
+++ b/tools/buildsteps/android-arm64-v8a/prepare-depends
@@ -0,0 +1,15 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
+
+# if depends path has changed - cleanout everything and do a full rebuild
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ #clean up the rest too
+ cd $WORKSPACE;git clean -xffd
+ cd $WORKSPACE/tools/depends/;./bootstrap
+fi
diff --git a/tools/buildsteps/android-arm64-v8a/prepare-xbmc b/tools/buildsteps/android-arm64-v8a/prepare-xbmc
new file mode 100644
index 0000000..29e374b
--- /dev/null
+++ b/tools/buildsteps/android-arm64-v8a/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/android-x86_64/configure-depends b/tools/buildsteps/android-x86_64/configure-depends
new file mode 100644
index 0000000..c27d6d8
--- /dev/null
+++ b/tools/buildsteps/android-x86_64/configure-depends
@@ -0,0 +1,17 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#the following path must exist on the slave and use the defined scheme here!
+NDK_PATH=$ANDROID_DEV_ROOT/android-ndk-r$NDK_VERSION
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;./configure \
+ --with-tarballs=$TARBALLS \
+ --host=x86_64-linux-android \
+ --with-sdk-path=$SDK_PATH \
+ --with-ndk-path=$NDK_PATH \
+ $(if [ "$NDK_API" != "Default" ]; then echo --with-ndk-api=$NDK_API;fi) \
+ --prefix=$XBMC_DEPENDS_ROOT $DEBUG_SWITCH
+fi
diff --git a/tools/buildsteps/android-x86_64/configure-xbmc b/tools/buildsteps/android-x86_64/configure-xbmc
new file mode 100644
index 0000000..81c0d3c
--- /dev/null
+++ b/tools/buildsteps/android-x86_64/configure-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+make -C $WORKSPACE/tools/depends/target/cmakebuildsys
diff --git a/tools/buildsteps/android-x86_64/make-binary-addons b/tools/buildsteps/android-x86_64/make-binary-addons
new file mode 100644
index 0000000..3bb9e74
--- /dev/null
+++ b/tools/buildsteps/android-x86_64/make-binary-addons
@@ -0,0 +1,29 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/android-x86_64/make-depends b/tools/buildsteps/android-x86_64/make-depends
new file mode 100644
index 0000000..c5869b2
--- /dev/null
+++ b/tools/buildsteps/android-x86_64/make-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
+
diff --git a/tools/buildsteps/android-x86_64/make-native-depends b/tools/buildsteps/android-x86_64/make-native-depends
new file mode 100644
index 0000000..c327180
--- /dev/null
+++ b/tools/buildsteps/android-x86_64/make-native-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ]
+then
+ git clean -xffd $WORKSPACE/tools/depends/native
+ cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
diff --git a/tools/buildsteps/android-x86_64/make-xbmc b/tools/buildsteps/android-x86_64/make-xbmc
new file mode 100644
index 0000000..11d8d70
--- /dev/null
+++ b/tools/buildsteps/android-x86_64/make-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS || make
diff --git a/tools/buildsteps/android-x86_64/package b/tools/buildsteps/android-x86_64/package
new file mode 100644
index 0000000..b477126
--- /dev/null
+++ b/tools/buildsteps/android-x86_64/package
@@ -0,0 +1,14 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+TARGET=apk
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS $TARGET
+
+cd $WORKSPACE
+
+#rename for upload
+#e.x. xbmc-20130314-8c2fb31-Frodo-x86_64.apk
+UPLOAD_FILENAME="kodi-$(getBuildRevDateStr)-x86_64"
+mv kodiapp-x86_64-*.apk $UPLOAD_FILENAME.apk
diff --git a/tools/buildsteps/android-x86_64/prepare-depends b/tools/buildsteps/android-x86_64/prepare-depends
new file mode 100644
index 0000000..b4d02b7
--- /dev/null
+++ b/tools/buildsteps/android-x86_64/prepare-depends
@@ -0,0 +1,15 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
+
+# if depends path has changed - cleanout everything and do a full rebuild
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ #clean up the rest too
+ cd $WORKSPACE;git clean -xffd
+ cd $WORKSPACE/tools/depends/;./bootstrap
+fi
diff --git a/tools/buildsteps/android-x86_64/prepare-xbmc b/tools/buildsteps/android-x86_64/prepare-xbmc
new file mode 100644
index 0000000..29e374b
--- /dev/null
+++ b/tools/buildsteps/android-x86_64/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/android/configure-depends b/tools/buildsteps/android/configure-depends
new file mode 100644
index 0000000..649ff6d
--- /dev/null
+++ b/tools/buildsteps/android/configure-depends
@@ -0,0 +1,18 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#the following path must exist on the slave and use the defined scheme here!
+NDK_PATH=$ANDROID_DEV_ROOT/android-ndk-r$NDK_VERSION
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;./configure \
+ --with-tarballs=$TARBALLS \
+ --host=arm-linux-androideabi \
+ --with-sdk-path=$SDK_PATH \
+ --with-ndk-path=$NDK_PATH \
+ $(if [ "$NDK_API" != "Default" ]; then echo --with-ndk-api=$NDK_API;fi) \
+ --prefix=$XBMC_DEPENDS_ROOT \
+ $DEBUG_SWITCH
+fi
diff --git a/tools/buildsteps/android/configure-xbmc b/tools/buildsteps/android/configure-xbmc
new file mode 100644
index 0000000..81c0d3c
--- /dev/null
+++ b/tools/buildsteps/android/configure-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+make -C $WORKSPACE/tools/depends/target/cmakebuildsys
diff --git a/tools/buildsteps/android/make-binary-addons b/tools/buildsteps/android/make-binary-addons
new file mode 100644
index 0000000..3bb9e74
--- /dev/null
+++ b/tools/buildsteps/android/make-binary-addons
@@ -0,0 +1,29 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/android/make-depends b/tools/buildsteps/android/make-depends
new file mode 100644
index 0000000..c5869b2
--- /dev/null
+++ b/tools/buildsteps/android/make-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
+
diff --git a/tools/buildsteps/android/make-native-depends b/tools/buildsteps/android/make-native-depends
new file mode 100644
index 0000000..c327180
--- /dev/null
+++ b/tools/buildsteps/android/make-native-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ]
+then
+ git clean -xffd $WORKSPACE/tools/depends/native
+ cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
diff --git a/tools/buildsteps/android/make-xbmc b/tools/buildsteps/android/make-xbmc
new file mode 100644
index 0000000..11d8d70
--- /dev/null
+++ b/tools/buildsteps/android/make-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS || make
diff --git a/tools/buildsteps/android/package b/tools/buildsteps/android/package
new file mode 100644
index 0000000..cbe3607
--- /dev/null
+++ b/tools/buildsteps/android/package
@@ -0,0 +1,14 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+TARGET=apk
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS $TARGET
+
+cd $WORKSPACE
+
+#rename for upload
+#e.x. xbmc-20130314-8c2fb31-Frodo-armeabi-v7a.apk
+UPLOAD_FILENAME="kodi-$(getBuildRevDateStr)-armeabi-v7a"
+mv kodiapp-armeabi-*.apk $UPLOAD_FILENAME.apk
diff --git a/tools/buildsteps/android/prepare-depends b/tools/buildsteps/android/prepare-depends
new file mode 100644
index 0000000..b4d02b7
--- /dev/null
+++ b/tools/buildsteps/android/prepare-depends
@@ -0,0 +1,15 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
+
+# if depends path has changed - cleanout everything and do a full rebuild
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ #clean up the rest too
+ cd $WORKSPACE;git clean -xffd
+ cd $WORKSPACE/tools/depends/;./bootstrap
+fi
diff --git a/tools/buildsteps/android/prepare-xbmc b/tools/buildsteps/android/prepare-xbmc
new file mode 100644
index 0000000..29e374b
--- /dev/null
+++ b/tools/buildsteps/android/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/androidx86/configure-depends b/tools/buildsteps/androidx86/configure-depends
new file mode 100644
index 0000000..9fb0e20
--- /dev/null
+++ b/tools/buildsteps/androidx86/configure-depends
@@ -0,0 +1,17 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#the following path must exist on the slave and use the defined scheme here!
+NDK_PATH=$ANDROID_DEV_ROOT/android-ndk-r$NDK_VERSION
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;./configure \
+ --with-tarballs=$TARBALLS \
+ --host=i686-linux-android \
+ --with-sdk-path=$SDK_PATH \
+ --with-ndk-path=$NDK_PATH \
+ $(if [ "$NDK_API" != "Default" ]; then echo --with-ndk-api=$NDK_API;fi) \
+ --prefix=$XBMC_DEPENDS_ROOT $DEBUG_SWITCH
+fi
diff --git a/tools/buildsteps/androidx86/configure-xbmc b/tools/buildsteps/androidx86/configure-xbmc
new file mode 100644
index 0000000..81c0d3c
--- /dev/null
+++ b/tools/buildsteps/androidx86/configure-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+make -C $WORKSPACE/tools/depends/target/cmakebuildsys
diff --git a/tools/buildsteps/androidx86/make-binary-addons b/tools/buildsteps/androidx86/make-binary-addons
new file mode 100644
index 0000000..3bb9e74
--- /dev/null
+++ b/tools/buildsteps/androidx86/make-binary-addons
@@ -0,0 +1,29 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/androidx86/make-depends b/tools/buildsteps/androidx86/make-depends
new file mode 100644
index 0000000..c5869b2
--- /dev/null
+++ b/tools/buildsteps/androidx86/make-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
+
diff --git a/tools/buildsteps/androidx86/make-native-depends b/tools/buildsteps/androidx86/make-native-depends
new file mode 100644
index 0000000..33cc579
--- /dev/null
+++ b/tools/buildsteps/androidx86/make-native-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ]
+then
+ git clean -xffd $WORKSPACE/tools/depends/native
+ cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi \ No newline at end of file
diff --git a/tools/buildsteps/androidx86/make-xbmc b/tools/buildsteps/androidx86/make-xbmc
new file mode 100644
index 0000000..11d8d70
--- /dev/null
+++ b/tools/buildsteps/androidx86/make-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS || make
diff --git a/tools/buildsteps/androidx86/package b/tools/buildsteps/androidx86/package
new file mode 100644
index 0000000..4e8ca13
--- /dev/null
+++ b/tools/buildsteps/androidx86/package
@@ -0,0 +1,14 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+TARGET=apk
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS $TARGET
+
+cd $WORKSPACE
+
+#rename for upload
+#e.x. xbmc-20130314-8c2fb31-Frodo-x86.apk
+UPLOAD_FILENAME="kodi-$(getBuildRevDateStr)-x86"
+mv kodiapp-x86-*.apk $UPLOAD_FILENAME.apk
diff --git a/tools/buildsteps/androidx86/prepare-depends b/tools/buildsteps/androidx86/prepare-depends
new file mode 100644
index 0000000..b4d02b7
--- /dev/null
+++ b/tools/buildsteps/androidx86/prepare-depends
@@ -0,0 +1,15 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
+
+# if depends path has changed - cleanout everything and do a full rebuild
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ #clean up the rest too
+ cd $WORKSPACE;git clean -xffd
+ cd $WORKSPACE/tools/depends/;./bootstrap
+fi
diff --git a/tools/buildsteps/androidx86/prepare-xbmc b/tools/buildsteps/androidx86/prepare-xbmc
new file mode 100644
index 0000000..29e374b
--- /dev/null
+++ b/tools/buildsteps/androidx86/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=android
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/defaultenv b/tools/buildsteps/defaultenv
new file mode 100644
index 0000000..e571e83
--- /dev/null
+++ b/tools/buildsteps/defaultenv
@@ -0,0 +1,183 @@
+BUILDTHREADS=${BUILDTHREADS:-1}
+SDK_VERSION=${SDK_VERSION:-"Default"}
+NDK_VERSION=${NDK_VERSION:-"Default"}
+NDK_API=${NDK_API:-"Default"}
+Configuration=${Configuration:-"Default"}
+XBMC_DEPENDS_ROOT=${XBMC_DEPENDS_ROOT:-"Default"}
+XCODE_APP=${XCODE_APP:-"Default"}
+PATH_CHANGE_REV_FILENAME=".last_success_revision"
+FAILED_BUILD_FILENAME=".last_failed_revision"
+#TARBALLS ENV-VAR is only used by android scripts atm
+TARBALLS=${TARBALLS:-"/opt/xbmc-tarballs"}
+RENDER_SYSTEM=${RENDER_SYSTEM:-"Default"}
+BUILD_HOST=${BUILD_HOST:-"Default"}
+
+BINARY_ADDONS_ROOT=tools/depends/target
+BINARY_ADDONS="binary-addons"
+DEPLOYED_BINARY_ADDONS="-e /addons"
+
+# Jenkins env variables
+JENKINS_BUILD_TIMESTAMP=${BUILD_TIMESTAMP:-"unknown"}
+JENKINS_BUILD_COMMIT=$(echo ${GIT_COMMIT:-"unknown"} | cut -c1-8)
+JENKINS_BUILD_REVISION=${Revision:-"unknown"}
+JENKINS_BUILD_ID=${BUILD_ID:-"unknown"}
+
+JENKINS_BUILD_STRING="${JENKINS_BUILD_TIMESTAMP}-${JENKINS_BUILD_COMMIT}-${JENKINS_BUILD_REVISION}-${JENKINS_BUILD_ID}"
+
+#set platform defaults
+#$XBMC_PLATFORM_DIR matches the platform subdirs!
+case $XBMC_PLATFORM_DIR in
+ ios)
+ DEFAULT_SDK_VERSION=14.4
+ DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
+ DEFAULT_CONFIGURATION="Debug"
+ DEFAULT_XCODE_APP="Xcode12.4.app"
+ ;;
+
+ tvos)
+ DEFAULT_SDK_VERSION=14.3
+ DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
+ DEFAULT_CONFIGURATION="Debug"
+ DEFAULT_XCODE_APP="Xcode12.4.app"
+ ;;
+
+ osx64)
+ DEFAULT_SDK_VERSION=11.1
+ DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
+ DEFAULT_CONFIGURATION="Debug"
+ DEFAULT_XCODE_APP="Xcode12.4.app"
+ ;;
+
+ osx-arm64)
+ DEFAULT_SDK_VERSION=11.1
+ DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
+ DEFAULT_CONFIGURATION="Debug"
+ DEFAULT_XCODE_APP="Xcode12.4.app"
+ ;;
+
+ android)
+ DEFAULT_NDK_VERSION="21e" # NDK package version (newer API can be inside)
+ DEFAULT_NDK_API="21" # Lollipop API level (21) defined in package ./sysroot/usr/include/android/api-level.h
+ DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
+ DEFAULT_CONFIGURATION="RelWithDebInfo"
+ ;;
+
+ linux)
+ DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
+ DEFAULT_CONFIGURATION="Debug"
+ DEFAULT_RENDER_SYSTEM="gl"
+ DEFAULT_BUILD_HOST="x86_64-linux-gnu"
+ ;;
+
+ freebsd)
+ DEFAULT_CONFIGURATION="Debug"
+ ;;
+esac
+
+if [ "$SDK_VERSION" == "Default" ]
+then
+ SDK_VERSION=$DEFAULT_SDK_VERSION
+fi
+
+if [ "$NDK_VERSION" == "Default" ]
+then
+ NDK_VERSION=$DEFAULT_NDK_VERSION
+fi
+
+if [ "$NDK_API" == "Default" ]
+then
+ NDK_API=$DEFAULT_NDK_API
+fi
+
+if [ "$XBMC_DEPENDS_ROOT" == "Default" ]
+then
+ XBMC_DEPENDS_ROOT=$DEFAULT_XBMC_DEPENDS_ROOT
+fi
+
+if [ "$XCODE_APP" == "Default" ]
+then
+ XCODE_APP=$DEFAULT_XCODE_APP
+fi
+
+# make osx environment aware of the selected xcode app
+export DEVELOPER_DIR=/Applications/$XCODE_APP/Contents/Developer
+
+if [ "$Configuration" == "Default" ]
+then
+ Configuration=$DEFAULT_CONFIGURATION
+fi
+
+if [ "$Configuration" == "Release" ]
+then
+ DEBUG_SWITCH='--disable-debug'
+fi
+
+if [ "$RENDER_SYSTEM" == "Default" ]
+then
+ RENDER_SYSTEM=$DEFAULT_RENDER_SYSTEM
+fi
+
+if [ "$BUILD_HOST" == "Default" ]
+then
+ BUILD_HOST=$DEFAULT_BUILD_HOST
+fi
+
+#helper functions
+
+#hash a dir based on the git revision, Configuration, SDK_PATH, NDK_PATH, NDK_VERSION, SDK_VERSION, TOOLCHAIN and XBMC_DEPENDS_ROOT
+#param1 path to be hashed
+function getBuildHash ()
+{
+ local checkPath
+ checkPath="$1"
+ local hashStr
+ hashStr="$(git rev-list HEAD --max-count=1 -- $checkPath)"
+ hashStr="$hashStr $Configuration $SDK_PATH $NDK_PATH $NDK_VERSION $SDK_VERSION $TOOLCHAIN $XBMC_DEPENDS_ROOT $XCODE_APP"
+ echo $hashStr
+}
+
+#param1 path to be checked for changes
+function pathChanged ()
+{
+ local ret
+ local checkPath
+ ret="0"
+
+ checkPath="$1"
+ if [ -e $checkPath/$PATH_CHANGE_REV_FILENAME ]
+ then
+ if [ "$(cat $checkPath/$PATH_CHANGE_REV_FILENAME)" != "$(getBuildHash $checkPath)" ]
+ then
+ ret="1"
+ fi
+ else
+ ret="1"
+ fi
+
+ echo $ret
+}
+
+#param1 path to be tagged with hash
+function tagSuccessFulBuild ()
+{
+ local pathToTag
+ pathToTag="$1"
+ # tag last successful build with revisions of the given dir
+ # needs to match the checks in function getBuildHash
+ echo "$(getBuildHash $pathToTag)" > $pathToTag/$PATH_CHANGE_REV_FILENAME
+}
+
+#param1 path to be tagged with hash
+function tagFailedBuild ()
+{
+ local pathToTag
+ pathToTag="$1"
+ # tag last failed build with revisions of the given dir
+ # needs to match the checks in function getBuildHash
+ echo "$(getBuildHash $pathToTag)" > $pathToTag/$FAILED_BUILD_FILENAME
+}
+
+function getBuildRevDateStr ()
+{
+ echo "${JENKINS_BUILD_STRING}"
+}
diff --git a/tools/buildsteps/freebsd/configure-depends b/tools/buildsteps/freebsd/configure-depends
new file mode 100644
index 0000000..d152e7c
--- /dev/null
+++ b/tools/buildsteps/freebsd/configure-depends
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#nothing for freebsd atm
diff --git a/tools/buildsteps/freebsd/configure-xbmc b/tools/buildsteps/freebsd/configure-xbmc
new file mode 100644
index 0000000..b6c2260
--- /dev/null
+++ b/tools/buildsteps/freebsd/configure-xbmc
@@ -0,0 +1,7 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+mkdir -p $WORKSPACE/build
+cd $WORKSPACE/build
+cmake -DCMAKE_BUILD_TYPE=$Configuration -DAPP_RENDER_SYSTEM=gl ..
diff --git a/tools/buildsteps/freebsd/make-binary-addons b/tools/buildsteps/freebsd/make-binary-addons
new file mode 100644
index 0000000..0647693
--- /dev/null
+++ b/tools/buildsteps/freebsd/make-binary-addons
@@ -0,0 +1,28 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;gmake -j $BUILDTHREADS V=99 VERBOSE=1 || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/freebsd/make-depends b/tools/buildsteps/freebsd/make-depends
new file mode 100644
index 0000000..d152e7c
--- /dev/null
+++ b/tools/buildsteps/freebsd/make-depends
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#nothing for freebsd atm
diff --git a/tools/buildsteps/freebsd/make-native-depends b/tools/buildsteps/freebsd/make-native-depends
new file mode 100644
index 0000000..d152e7c
--- /dev/null
+++ b/tools/buildsteps/freebsd/make-native-depends
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#nothing for freebsd atm
diff --git a/tools/buildsteps/freebsd/make-xbmc b/tools/buildsteps/freebsd/make-xbmc
new file mode 100644
index 0000000..70faded
--- /dev/null
+++ b/tools/buildsteps/freebsd/make-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;gmake -j$BUILDTHREADS || gmake
diff --git a/tools/buildsteps/freebsd/package b/tools/buildsteps/freebsd/package
new file mode 100644
index 0000000..d152e7c
--- /dev/null
+++ b/tools/buildsteps/freebsd/package
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#nothing for freebsd atm
diff --git a/tools/buildsteps/freebsd/prepare-depends b/tools/buildsteps/freebsd/prepare-depends
new file mode 100644
index 0000000..7aae09b
--- /dev/null
+++ b/tools/buildsteps/freebsd/prepare-depends
@@ -0,0 +1,8 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+#freebsd doesn't use depends atm
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
diff --git a/tools/buildsteps/freebsd/prepare-xbmc b/tools/buildsteps/freebsd/prepare-xbmc
new file mode 100644
index 0000000..18f2cf8
--- /dev/null
+++ b/tools/buildsteps/freebsd/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/freebsd/run-tests b/tools/buildsteps/freebsd/run-tests
new file mode 100644
index 0000000..9ee91ce
--- /dev/null
+++ b/tools/buildsteps/freebsd/run-tests
@@ -0,0 +1,14 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=freebsd
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;gmake -j$BUILDTHREADS kodi-test
+if [ "$Configuration" != "Coverage" ]; then
+ cd $WORKSPACE;build/kodi-test --gtest_output=xml:gtestresults.xml
+else
+ cd $WORKSPACE/build;GTEST_OUTPUT="xml:$WORKSPACE/gtestresults.xml" gmake coverage
+fi
+
+awk '{ if ($1 == "<testcase" && match($0, "notrun")) print substr($0,0,length($0)-2) "><skipped/></testcase>"; else print $0;}' gtestresults.xml > gtestresults-skipped.xml
+rm gtestresults.xml
+mv gtestresults-skipped.xml gtestresults.xml
diff --git a/tools/buildsteps/ios/configure-depends b/tools/buildsteps/ios/configure-depends
new file mode 100755
index 0000000..37e1f77
--- /dev/null
+++ b/tools/buildsteps/ios/configure-depends
@@ -0,0 +1,13 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=ios
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;./configure \
+ --with-tarballs=/Users/Shared/xbmc-depends/tarballs \
+ --host=aarch64-apple-darwin \
+ --with-platform=ios \
+ --with-sdk=$SDK_VERSION \
+ --prefix=$XBMC_DEPENDS_ROOT $DEBUG_SWITCH
+fi
diff --git a/tools/buildsteps/ios/configure-xbmc b/tools/buildsteps/ios/configure-xbmc
new file mode 100755
index 0000000..dbe8a74
--- /dev/null
+++ b/tools/buildsteps/ios/configure-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=ios
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+make -C $WORKSPACE/tools/depends/target/cmakebuildsys
diff --git a/tools/buildsteps/ios/make-binary-addons b/tools/buildsteps/ios/make-binary-addons
new file mode 100755
index 0000000..3f5bd02
--- /dev/null
+++ b/tools/buildsteps/ios/make-binary-addons
@@ -0,0 +1,30 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=ios
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+
+ INSTALL_PREFIX="../../../../../build/addons/"
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 INSTALL_PREFIX="$INSTALL_PREFIX" || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/ios/make-depends b/tools/buildsteps/ios/make-depends
new file mode 100755
index 0000000..eb36ee2
--- /dev/null
+++ b/tools/buildsteps/ios/make-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=ios
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
+
diff --git a/tools/buildsteps/ios/make-native-depends b/tools/buildsteps/ios/make-native-depends
new file mode 100755
index 0000000..3211bf7
--- /dev/null
+++ b/tools/buildsteps/ios/make-native-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=ios
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ]
+then
+ git clean -xffd $WORKSPACE/tools/depends/native
+ cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi \ No newline at end of file
diff --git a/tools/buildsteps/ios/make-xbmc b/tools/buildsteps/ios/make-xbmc
new file mode 100755
index 0000000..5d7c604
--- /dev/null
+++ b/tools/buildsteps/ios/make-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=ios
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;xcodebuild -configuration $Configuration -jobs $BUILDTHREADS \
+ -parallelizeTargets \
+ -target deb \
+ SDKROOT=iphoneos$SDK_VERSION XBMC_DEPENDS_ROOT=$XBMC_DEPENDS_ROOT \
+ CODE_SIGNING_ALLOWED="NO"
diff --git a/tools/buildsteps/ios/package b/tools/buildsteps/ios/package
new file mode 100755
index 0000000..b264094
--- /dev/null
+++ b/tools/buildsteps/ios/package
@@ -0,0 +1,11 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=ios
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build/tools/darwin/packaging/darwin_embedded/
+
+#rename for upload
+#e.x. kodi-20130314-8c2fb31-Frodo-ios64.deb
+UPLOAD_FILENAME="kodi-$(getBuildRevDateStr)-ios64.deb"
+mkdir $WORKSPACE/tools/darwin/packaging/ios
+mv *.deb $WORKSPACE/tools/darwin/packaging/ios/$UPLOAD_FILENAME
diff --git a/tools/buildsteps/ios/prepare-depends b/tools/buildsteps/ios/prepare-depends
new file mode 100755
index 0000000..3b6a893
--- /dev/null
+++ b/tools/buildsteps/ios/prepare-depends
@@ -0,0 +1,15 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=ios
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
+
+# if depends path has changed - cleanout everything and do a full rebuild
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ #clean up the rest too
+ cd $WORKSPACE;git clean -xffd
+ cd $WORKSPACE/tools/depends/;./bootstrap
+fi
diff --git a/tools/buildsteps/ios/prepare-xbmc b/tools/buildsteps/ios/prepare-xbmc
new file mode 100755
index 0000000..d1dc25c
--- /dev/null
+++ b/tools/buildsteps/ios/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=ios
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/jenkins_docs/README.mac b/tools/buildsteps/jenkins_docs/README.mac
new file mode 100644
index 0000000..edbf52c
--- /dev/null
+++ b/tools/buildsteps/jenkins_docs/README.mac
@@ -0,0 +1,100 @@
+This are the steps to be done for configuring a mac for being a build slave to the Kodi jenkins CI system
+--------------------------------------------------------------------------------------------------------
+
+1. setup user jenkins as follows:
+
+# create jenkins group
+NEXT_GID=$((`dscl /Local/Default list /Groups gid | awk '{ print $2 }' | sort -n | grep -v '^[5-9]' | tail -n1` + 1))
+sudo dscl /Local/Default create /Groups/jenkins
+sudo dscl /Local/Default create /Groups/jenkins PrimaryGroupID $NEXT_GID
+sudo dscl /Local/Default create /Groups/jenkins Password \*
+sudo dscl /Local/Default create /Groups/jenkins RealName 'Jenkins Node Service'
+# create jenkins user
+NEXT_UID=$((`dscl /Local/Default list /Users uid | awk '{ print $2 }' | sort -n | grep -v '^[5-9]' | tail -n1` + 1))
+sudo dscl /Local/Default create /Users/jenkins
+sudo dscl /Local/Default create /Users/jenkins UniqueID $NEXT_UID
+sudo dscl /Local/Default create /Users/jenkins PrimaryGroupID $NEXT_GID
+sudo dscl /Local/Default create /Users/jenkins UserShell /usr/bin/false
+sudo dscl /Local/Default create /Users/jenkins NFSHomeDirectory /var/lib/jenkins
+sudo dscl /Local/Default create /Users/jenkins Password \*
+sudo dseditgroup -o edit -a jenkins -t user jenkins
+# create the jenkins home dir
+sudo mkdir /var/lib/jenkins
+sudo chown -R jenkins:wheel /var/lib/jenkins
+# create a logging space
+sudo mkdir /var/log/jenkins
+sudo chown jenkins:wheel /var/log/jenkins
+
+3. mkdir /Users/Shared/jenkins
+
+4. sudo chown jenkins:wheel /Users/Shared/jenkins
+
+5. mkdir -p /Users/Shared/xbmc-depends/dSyms
+
+6. sudo chown -R jenkins:wheel /Users/Shared/xbmc-depends/
+
+7. Change to user jenknis via sudo -u jenkins bash
+
+8. mkdir /Users/Shared/jenkins/slave
+
+9. nano /Users/Shared/jenkins/slave/startslave.sh and add the following
+
+#!/bin/sh
+
+rm error.log
+rm stdout.log
+java -Djava.awt.headless=true -jar slave.jar -jar-cache /Users/Shared/jenkins/cache -jnlpUrl http://jenkins.kodi.tv/computer/<node name from jenkins node page>/slave-agent.jnlp -secret <secret from jenkins node page>
+
+10. chmod +x /Users/Shared/jenkins/slave/startslave.sh
+
+11. edit startslave.sh and add nodename and the secret at the end of the command line from the node page
+
+12. nano /Users/Shared/jenkins/slave/org.jenkins-ci.slave.jnlp.plist and add the following
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.example.ci</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/Users/Shared/jenkins/slave/startslave.sh</string>
+ </array>
+ <key>KeepAlive</key>
+ <true/>
+ <key>RunAtLoad</key>
+ <true/>
+ <key>SessionCreate</key>
+ <true/>
+ <key>UserName</key>
+ <string>jenkins</string>
+ <key>WorkingDirectory</key>
+ <string>/Users/Shared/jenkins</string>
+ <key>StandardOutPath</key>
+ <string>/Users/Shared/jenkins/slave/stdout.log</string>
+ <key>StandardErrorPath</key>
+ <string>/Users/Shared/jenkins/slave/error.log</string>
+</dict>
+</plist>
+
+13. sudo mv /Users/Shared/jenkins/slave/org.jenkins-ci.slave.jnlp.plist /Library/LaunchDaemons/org.jenkins-ci.slave.jnlp.plist
+
+14. sudo nano /etc/profile and add PATH=$PATH:/usr/local/bin
+
+15. curl http://jenkins.kodi.tv/jnlpJars/slave.jar -Lo /Users/Shared/jenkins/slave.jar
+
+16. install java JDK 8
+
+17. Install Xcode (get it from developer.apple.com -> Downloads) and start it once (accept license):
+- 10.2 to /Applications/Xcode10.2.app - for macOS and iOS builds
+- 11.3.1 to /Applications/Xcode11.3.1.app - for tvOS builds
+
+18. install brew
+
+19. install ccache via brew (brew install ccache)
+
+20. edit /var/lib/jenkins/.ccache/ccache.conf and set max_size to 20.0G (this file might just appear after the first build done on the node)
+
+21. load service:
+sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.slave.jnlp.plist
diff --git a/tools/buildsteps/linux-debian/configure-depends b/tools/buildsteps/linux-debian/configure-depends
new file mode 100755
index 0000000..96e6aaa
--- /dev/null
+++ b/tools/buildsteps/linux-debian/configure-depends
@@ -0,0 +1,2 @@
+# We do not use unified dependencies here, but system libs
+exit 0
diff --git a/tools/buildsteps/linux-debian/configure-xbmc b/tools/buildsteps/linux-debian/configure-xbmc
new file mode 100755
index 0000000..44380b3
--- /dev/null
+++ b/tools/buildsteps/linux-debian/configure-xbmc
@@ -0,0 +1,2 @@
+# Nothing to be done, this is all handled by the package script
+exit 0
diff --git a/tools/buildsteps/linux-debian/make-depends b/tools/buildsteps/linux-debian/make-depends
new file mode 100755
index 0000000..d1de8c7
--- /dev/null
+++ b/tools/buildsteps/linux-debian/make-depends
@@ -0,0 +1,2 @@
+# noop
+exit 0
diff --git a/tools/buildsteps/linux-debian/make-xbmc b/tools/buildsteps/linux-debian/make-xbmc
new file mode 100755
index 0000000..d1de8c7
--- /dev/null
+++ b/tools/buildsteps/linux-debian/make-xbmc
@@ -0,0 +1,2 @@
+# noop
+exit 0
diff --git a/tools/buildsteps/linux-debian/package b/tools/buildsteps/linux-debian/package
new file mode 100755
index 0000000..accffd1
--- /dev/null
+++ b/tools/buildsteps/linux-debian/package
@@ -0,0 +1,16 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux-debian
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE
+
+RELEASEV=$VERSION \
+TAG=$TAG \
+DISTS=${DISTS:-"stable"} \
+ARCHS=${ARCHS:-"i386 amd64"} \
+BUILDER=${BUILDER:-"pdebuild"} \
+PDEBUILD_OPTS=${PDEBUILD_OPTS:-"--debbuildopts \"-j$BUILDTHREADS\""} \
+PBUILDER_BASE=${PBUILDER_BASE:-"/home/$USER/xbmc-packaging/pbuilder"} \
+DPUT_TARGET=${DPUT_TARGET:-"local"} \
+Configuration="$Configuration" \
+tools/Linux/packaging/mk-debian-package.sh
diff --git a/tools/buildsteps/linux-debian/prepare-depends b/tools/buildsteps/linux-debian/prepare-depends
new file mode 100755
index 0000000..ca916d0
--- /dev/null
+++ b/tools/buildsteps/linux-debian/prepare-depends
@@ -0,0 +1 @@
+exit 0
diff --git a/tools/buildsteps/linux-debian/prepare-xbmc b/tools/buildsteps/linux-debian/prepare-xbmc
new file mode 100755
index 0000000..d54f426
--- /dev/null
+++ b/tools/buildsteps/linux-debian/prepare-xbmc
@@ -0,0 +1,2 @@
+#nothing on linux
+exit 0
diff --git a/tools/buildsteps/linux/configure-depends b/tools/buildsteps/linux/configure-depends
new file mode 100755
index 0000000..7046717
--- /dev/null
+++ b/tools/buildsteps/linux/configure-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;./configure \
+ --with-toolchain=/usr --prefix=$XBMC_DEPENDS_ROOT --host=$BUILD_HOST --with-rendersystem=$RENDER_SYSTEM --with-tarballs=$TARBALLS $DEBUG_SWITCH
+fi
diff --git a/tools/buildsteps/linux/configure-xbmc b/tools/buildsteps/linux/configure-xbmc
new file mode 100755
index 0000000..92557bf
--- /dev/null
+++ b/tools/buildsteps/linux/configure-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+make -C $WORKSPACE/tools/depends/target/cmakebuildsys
diff --git a/tools/buildsteps/linux/make-binary-addons b/tools/buildsteps/linux/make-binary-addons
new file mode 100755
index 0000000..1f93c3e
--- /dev/null
+++ b/tools/buildsteps/linux/make-binary-addons
@@ -0,0 +1,28 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/linux/make-depends b/tools/buildsteps/linux/make-depends
new file mode 100755
index 0000000..224d4e5
--- /dev/null
+++ b/tools/buildsteps/linux/make-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS || make && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
+
diff --git a/tools/buildsteps/linux/make-native-depends b/tools/buildsteps/linux/make-native-depends
new file mode 100755
index 0000000..5ac21af
--- /dev/null
+++ b/tools/buildsteps/linux/make-native-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ]
+then
+ git clean -xffd $WORKSPACE/tools/depends/native
+ cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
diff --git a/tools/buildsteps/linux/make-xbmc b/tools/buildsteps/linux/make-xbmc
new file mode 100755
index 0000000..534b578
--- /dev/null
+++ b/tools/buildsteps/linux/make-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS || make
diff --git a/tools/buildsteps/linux/package b/tools/buildsteps/linux/package
new file mode 100755
index 0000000..09da07b
--- /dev/null
+++ b/tools/buildsteps/linux/package
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#nothing for linux atm
diff --git a/tools/buildsteps/linux/prepare-depends b/tools/buildsteps/linux/prepare-depends
new file mode 100755
index 0000000..ec5219a
--- /dev/null
+++ b/tools/buildsteps/linux/prepare-depends
@@ -0,0 +1,15 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
+
+# if depends path has changed - cleanout everything and do a full rebuild
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ #clean up the rest too
+ cd $WORKSPACE;git clean -xffd
+ cd $WORKSPACE/tools/depends/;./bootstrap
+fi
diff --git a/tools/buildsteps/linux/prepare-xbmc b/tools/buildsteps/linux/prepare-xbmc
new file mode 100755
index 0000000..84a96e5
--- /dev/null
+++ b/tools/buildsteps/linux/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/linux/run-tests b/tools/buildsteps/linux/run-tests
new file mode 100755
index 0000000..f11d5f1
--- /dev/null
+++ b/tools/buildsteps/linux/run-tests
@@ -0,0 +1,14 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=linux
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS kodi-test
+if [ "$Configuration" != "Coverage" ]; then
+ cd $WORKSPACE;build/kodi-test --gtest_output=xml:gtestresults.xml
+else
+ cd $WORKSPACE/build;GTEST_OUTPUT="xml:$WORKSPACE/gtestresults.xml" make coverage
+fi
+
+awk '{ if ($1 == "<testcase" && match($0, "notrun")) print substr($0,0,length($0)-2) "><skipped/></testcase>"; else print $0;}' gtestresults.xml > gtestresults-skipped.xml
+rm gtestresults.xml
+mv gtestresults-skipped.xml gtestresults.xml
diff --git a/tools/buildsteps/osx-arm64/configure-depends b/tools/buildsteps/osx-arm64/configure-depends
new file mode 100755
index 0000000..c950eb9
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/configure-depends
@@ -0,0 +1,13 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;./configure \
+ --with-tarballs=/Users/Shared/xbmc-depends/tarballs \
+ --host=aarch64-apple-darwin \
+ --with-sdk=$SDK_VERSION \
+ --with-platform=macos \
+ --prefix=$XBMC_DEPENDS_ROOT $DEBUG_SWITCH
+fi
diff --git a/tools/buildsteps/osx-arm64/configure-xbmc b/tools/buildsteps/osx-arm64/configure-xbmc
new file mode 100755
index 0000000..c8adee0
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/configure-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+make -C $WORKSPACE/tools/depends/target/cmakebuildsys APP_WINDOW_SYSTEM=native CMAKE_EXTRA_ARGUMENTS="-D CODE_SIGN_IDENTITY='$CODE_SIGN_IDENTITY' -D NOTARYTOOL_KEYCHAIN_PROFILE='$NOTARYTOOL_KEYCHAIN_PROFILE' -D NOTARYTOOL_KEYCHAIN_PATH='$NOTARYTOOL_KEYCHAIN_PATH'"
diff --git a/tools/buildsteps/osx-arm64/load-env b/tools/buildsteps/osx-arm64/load-env
new file mode 100755
index 0000000..4990f4b
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/load-env
@@ -0,0 +1,3 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
diff --git a/tools/buildsteps/osx-arm64/make-binary-addons b/tools/buildsteps/osx-arm64/make-binary-addons
new file mode 100755
index 0000000..458f9f1
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/make-binary-addons
@@ -0,0 +1,30 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+
+ INSTALL_PREFIX="../../../../../build/addons/"
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 INSTALL_PREFIX="$INSTALL_PREFIX" || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/osx-arm64/make-depends b/tools/buildsteps/osx-arm64/make-depends
new file mode 100755
index 0000000..74e4213
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/make-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
+
diff --git a/tools/buildsteps/osx-arm64/make-native-depends b/tools/buildsteps/osx-arm64/make-native-depends
new file mode 100755
index 0000000..d0e6d76
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/make-native-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ]
+then
+ git clean -xffd $WORKSPACE/tools/depends/native
+ cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi \ No newline at end of file
diff --git a/tools/buildsteps/osx-arm64/make-xbmc b/tools/buildsteps/osx-arm64/make-xbmc
new file mode 100755
index 0000000..b43dec9
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/make-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS || make
diff --git a/tools/buildsteps/osx-arm64/package b/tools/buildsteps/osx-arm64/package
new file mode 100755
index 0000000..b14c2e0
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/package
@@ -0,0 +1,11 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS dmg
+cd $WORKSPACE/build/tools/darwin/packaging/osx/
+
+#rename for upload
+#e.x. kodi-20130314-8c2fb31-Frodo-x86_64.dmg
+UPLOAD_FILENAME="kodi-$(getBuildRevDateStr)-arm64.dmg"
+mv *.dmg $WORKSPACE/tools/darwin/packaging/osx/$UPLOAD_FILENAME
diff --git a/tools/buildsteps/osx-arm64/prepare-depends b/tools/buildsteps/osx-arm64/prepare-depends
new file mode 100755
index 0000000..13faf12
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/prepare-depends
@@ -0,0 +1,15 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
+
+# if depends path has changed - cleanout everything and do a full rebuild
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ #clean up the rest too
+ cd $WORKSPACE;git clean -xffd
+ cd $WORKSPACE/tools/depends/;./bootstrap
+fi
diff --git a/tools/buildsteps/osx-arm64/prepare-xbmc b/tools/buildsteps/osx-arm64/prepare-xbmc
new file mode 100755
index 0000000..9402652
--- /dev/null
+++ b/tools/buildsteps/osx-arm64/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx-arm64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/osx64/configure-depends b/tools/buildsteps/osx64/configure-depends
new file mode 100755
index 0000000..c44250e
--- /dev/null
+++ b/tools/buildsteps/osx64/configure-depends
@@ -0,0 +1,13 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;./configure \
+ --with-tarballs=/Users/Shared/xbmc-depends/tarballs \
+ --host=x86_64-apple-darwin \
+ --with-sdk=$SDK_VERSION \
+ --with-platform=macos \
+ --prefix=$XBMC_DEPENDS_ROOT $DEBUG_SWITCH
+fi
diff --git a/tools/buildsteps/osx64/configure-xbmc b/tools/buildsteps/osx64/configure-xbmc
new file mode 100755
index 0000000..2643cc9
--- /dev/null
+++ b/tools/buildsteps/osx64/configure-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+make -C $WORKSPACE/tools/depends/target/cmakebuildsys CMAKE_EXTRA_ARGUMENTS="-D CODE_SIGN_IDENTITY='$CODE_SIGN_IDENTITY' -D NOTARYTOOL_KEYCHAIN_PROFILE='$NOTARYTOOL_KEYCHAIN_PROFILE' -D NOTARYTOOL_KEYCHAIN_PATH='$NOTARYTOOL_KEYCHAIN_PATH'"
diff --git a/tools/buildsteps/osx64/load-env b/tools/buildsteps/osx64/load-env
new file mode 100755
index 0000000..59635b7
--- /dev/null
+++ b/tools/buildsteps/osx64/load-env
@@ -0,0 +1,3 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
diff --git a/tools/buildsteps/osx64/make-binary-addons b/tools/buildsteps/osx64/make-binary-addons
new file mode 100755
index 0000000..fd0bd7a
--- /dev/null
+++ b/tools/buildsteps/osx64/make-binary-addons
@@ -0,0 +1,30 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+
+ INSTALL_PREFIX="../../../../../build/addons/"
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 INSTALL_PREFIX="$INSTALL_PREFIX" || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/osx64/make-depends b/tools/buildsteps/osx64/make-depends
new file mode 100755
index 0000000..5a325e1
--- /dev/null
+++ b/tools/buildsteps/osx64/make-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
+
diff --git a/tools/buildsteps/osx64/make-native-depends b/tools/buildsteps/osx64/make-native-depends
new file mode 100755
index 0000000..b5ef526
--- /dev/null
+++ b/tools/buildsteps/osx64/make-native-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ]
+then
+ git clean -xffd $WORKSPACE/tools/depends/native
+ cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi \ No newline at end of file
diff --git a/tools/buildsteps/osx64/make-xbmc b/tools/buildsteps/osx64/make-xbmc
new file mode 100755
index 0000000..cc1184b
--- /dev/null
+++ b/tools/buildsteps/osx64/make-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS || make
diff --git a/tools/buildsteps/osx64/package b/tools/buildsteps/osx64/package
new file mode 100755
index 0000000..66db6d3
--- /dev/null
+++ b/tools/buildsteps/osx64/package
@@ -0,0 +1,11 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS dmg
+cd $WORKSPACE/build/tools/darwin/packaging/osx/
+
+#rename for upload
+#e.x. kodi-20130314-8c2fb31-Frodo-x86_64.dmg
+UPLOAD_FILENAME="kodi-$(getBuildRevDateStr)-x86_64.dmg"
+mv *.dmg $WORKSPACE/tools/darwin/packaging/osx/$UPLOAD_FILENAME
diff --git a/tools/buildsteps/osx64/prepare-depends b/tools/buildsteps/osx64/prepare-depends
new file mode 100755
index 0000000..8aba95e
--- /dev/null
+++ b/tools/buildsteps/osx64/prepare-depends
@@ -0,0 +1,15 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
+
+# if depends path has changed - cleanout everything and do a full rebuild
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ #clean up the rest too
+ cd $WORKSPACE;git clean -xffd
+ cd $WORKSPACE/tools/depends/;./bootstrap
+fi
diff --git a/tools/buildsteps/osx64/prepare-xbmc b/tools/buildsteps/osx64/prepare-xbmc
new file mode 100755
index 0000000..05b5ed3
--- /dev/null
+++ b/tools/buildsteps/osx64/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/osx64/run-tests b/tools/buildsteps/osx64/run-tests
new file mode 100755
index 0000000..38ae333
--- /dev/null
+++ b/tools/buildsteps/osx64/run-tests
@@ -0,0 +1,10 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=osx64
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;make -j$BUILDTHREADS kodi-test
+cd $WORKSPACE;build/kodi-test --gtest_output=xml:gtestresults.xml
+
+awk '{ if ($1 == "<testcase" && match($0, "notrun")) print substr($0,0,length($0)-2) "><skipped/></testcase>"; else print $0;}' gtestresults.xml > gtestresults-skipped.xml
+rm gtestresults.xml
+mv gtestresults-skipped.xml gtestresults.xml
diff --git a/tools/buildsteps/tvos/configure-depends b/tools/buildsteps/tvos/configure-depends
new file mode 100755
index 0000000..98d78e3
--- /dev/null
+++ b/tools/buildsteps/tvos/configure-depends
@@ -0,0 +1,13 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=tvos
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;./configure \
+ --with-tarballs=/Users/Shared/xbmc-depends/tarballs \
+ --host=aarch64-apple-darwin \
+ --with-sdk=$SDK_VERSION \
+ --with-platform=tvos \
+ --prefix=$XBMC_DEPENDS_ROOT $DEBUG_SWITCH
+fi
diff --git a/tools/buildsteps/tvos/configure-xbmc b/tools/buildsteps/tvos/configure-xbmc
new file mode 100755
index 0000000..e3c3767
--- /dev/null
+++ b/tools/buildsteps/tvos/configure-xbmc
@@ -0,0 +1,5 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=tvos
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+make -C $WORKSPACE/tools/depends/target/cmakebuildsys
diff --git a/tools/buildsteps/tvos/make-binary-addons b/tools/buildsteps/tvos/make-binary-addons
new file mode 100755
index 0000000..ae64154
--- /dev/null
+++ b/tools/buildsteps/tvos/make-binary-addons
@@ -0,0 +1,30 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=tvos
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends
+
+#clear the build failed file
+rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME
+
+ALL_BINARY_ADDONS_BUILT="1"
+#only build binary addons when requested by env/jenkins
+if [ "$BUILD_BINARY_ADDONS" == "true" ]
+then
+ for addon in $BINARY_ADDONS
+ do
+ echo "building $addon"
+ git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon
+
+ INSTALL_PREFIX="../../../../../build/addons/"
+ cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 INSTALL_PREFIX="$INSTALL_PREFIX" || ALL_BINARY_ADDONS_BUILT="0"
+ done
+fi
+
+if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ]
+then
+ tagSuccessFulBuild $WORKSPACE/cmake
+else
+ #mark the build failure in the filesystem but leave jenkins running
+ tagFailedBuild $WORKSPACE/cmake
+fi
diff --git a/tools/buildsteps/tvos/make-depends b/tools/buildsteps/tvos/make-depends
new file mode 100755
index 0000000..e887290
--- /dev/null
+++ b/tools/buildsteps/tvos/make-depends
@@ -0,0 +1,8 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=tvos
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
diff --git a/tools/buildsteps/tvos/make-native-depends b/tools/buildsteps/tvos/make-native-depends
new file mode 100755
index 0000000..3e44687
--- /dev/null
+++ b/tools/buildsteps/tvos/make-native-depends
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=tvos
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ]
+then
+ git clean -xffd $WORKSPACE/tools/depends/native
+ cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends
+fi
diff --git a/tools/buildsteps/tvos/make-xbmc b/tools/buildsteps/tvos/make-xbmc
new file mode 100755
index 0000000..439711c
--- /dev/null
+++ b/tools/buildsteps/tvos/make-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=tvos
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build;xcodebuild -configuration $Configuration -jobs $BUILDTHREADS \
+ -parallelizeTargets \
+ -target deb \
+ SDKROOT=appletvos$SDK_VERSION XBMC_DEPENDS_ROOT=$XBMC_DEPENDS_ROOT \
+ CODE_SIGNING_ALLOWED="NO"
diff --git a/tools/buildsteps/tvos/package b/tools/buildsteps/tvos/package
new file mode 100755
index 0000000..2318af2
--- /dev/null
+++ b/tools/buildsteps/tvos/package
@@ -0,0 +1,11 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=tvos
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+cd $WORKSPACE/build/tools/darwin/packaging/darwin_embedded/
+
+#rename for upload
+#e.x. kodi-20130314-8c2fb31-Frodo-tvos.deb
+UPLOAD_FILENAME="kodi-$(getBuildRevDateStr)-tvos.deb"
+mkdir $WORKSPACE/tools/darwin/packaging/tvos
+mv *.deb $WORKSPACE/tools/darwin/packaging/tvos/$UPLOAD_FILENAME
diff --git a/tools/buildsteps/tvos/prepare-depends b/tools/buildsteps/tvos/prepare-depends
new file mode 100755
index 0000000..96cdae4
--- /dev/null
+++ b/tools/buildsteps/tvos/prepare-depends
@@ -0,0 +1,15 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=tvos
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#clean without depends for skipping depends build if possible
+#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
+cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS}
+
+# if depends path has changed - cleanout everything and do a full rebuild
+if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
+then
+ #clean up the rest too
+ cd $WORKSPACE;git clean -xffd
+ cd $WORKSPACE/tools/depends/;./bootstrap
+fi
diff --git a/tools/buildsteps/tvos/prepare-xbmc b/tools/buildsteps/tvos/prepare-xbmc
new file mode 100755
index 0000000..af48229
--- /dev/null
+++ b/tools/buildsteps/tvos/prepare-xbmc
@@ -0,0 +1,9 @@
+WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )}
+XBMC_PLATFORM_DIR=tvos
+. $WORKSPACE/tools/buildsteps/defaultenv
+
+#build binary addons before building xbmc...
+#make sure that binary_addons don't clean the native tools
+#here
+BINARY_ADDONS_CLEAN_NATIVETOOLS="0"
+. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons
diff --git a/tools/buildsteps/windows/BuildSetup.bat b/tools/buildsteps/windows/BuildSetup.bat
new file mode 100644
index 0000000..6d2180a
--- /dev/null
+++ b/tools/buildsteps/windows/BuildSetup.bat
@@ -0,0 +1,300 @@
+@ECHO OFF
+REM setup all paths
+PUSHD %~dp0\..\..\..
+SET base_dir=%CD%
+POPD
+
+REM read the version values from version.txt
+FOR /f "tokens=1,*" %%i IN (%base_dir%\version.txt) DO SET %%i=%%j
+
+SET APP_VERSION=%VERSION_MAJOR%.%VERSION_MINOR%
+IF NOT [%VERSION_TAG%] == [] (
+ SET APP_VERSION=%APP_VERSION%-%VERSION_TAG%
+)
+
+rem ----Usage----
+rem BuildSetup [clean|noclean] [noprompt] [nobinaryaddons] [sh]
+rem clean to force a full rebuild
+rem noclean to force a build without clean
+rem noprompt to avoid all prompts
+rem nobinaryaddons to skip building binary addons
+rem sh to use sh shell instead rxvt
+CLS
+TITLE %APP_NAME% for Windows Build Script
+rem ----PURPOSE----
+rem - Create a working application build with a single click
+rem -------------------------------------------------------------
+rem Config
+rem If you get an error that Visual studio was not found, SET your path for VSNET main executable.
+rem -------------------------------------------------------------
+rem CONFIG START
+SET buildmode=ask
+SET promptlevel=prompt
+SET buildbinaryaddons=true
+SET exitcode=0
+SET useshell=rxvt
+FOR %%b in (%*) DO (
+ IF %%b==clean SET buildmode=clean
+ IF %%b==noclean SET buildmode=noclean
+ IF %%b==noprompt SET promptlevel=noprompt
+ IF %%b==nobinaryaddons SET buildbinaryaddons=false
+ IF %%b==sh SET useshell=sh
+)
+
+SET PreferredToolArchitecture=x64
+SET buildconfig=Release
+set WORKSPACE=%base_dir%\kodi-build.%TARGET_PLATFORM%
+
+
+ :: sets the BRANCH env var
+ FOR /f %%a IN ('getbranch.bat') DO SET BRANCH=%%a
+
+ rem CONFIG END
+ rem -------------------------------------------------------------
+ goto COMPILE_CMAKE_EXE
+
+:COMPILE_CMAKE_EXE
+ ECHO Wait while preparing the build.
+ ECHO ------------------------------------------------------------
+ ECHO Compiling %APP_NAME% branch %BRANCH%...
+
+ IF %buildmode%==clean (
+ RMDIR /S /Q %WORKSPACE%
+ )
+ MKDIR %WORKSPACE%
+ PUSHD %WORKSPACE%
+
+ cmake.exe -G "%cmakeGenerator%" -A %cmakeArch% -T host=x64 %cmakeProps% %base_dir%
+ IF %errorlevel%==1 (
+ set DIETEXT="%APP_NAME%.EXE failed to build!"
+ goto DIE
+ )
+
+ cmake.exe --build . --config "%buildconfig%"
+ IF %errorlevel%==1 (
+ set DIETEXT="%APP_NAME%.EXE failed to build!"
+ goto DIE
+ )
+
+ set EXE="%WORKSPACE%\%buildconfig%\%APP_NAME%.exe"
+ set PDB="%WORKSPACE%\%buildconfig%\%APP_NAME%.pdb"
+ set D3D="%WORKSPACE%\D3DCompile*.DLL"
+
+ POPD
+ ECHO Done!
+ ECHO ------------------------------------------------------------
+ IF "%cmakeProps%" NEQ "" GOTO MAKE_APPX
+ GOTO MAKE_BUILD_EXE
+
+
+:MAKE_BUILD_EXE
+ ECHO Copying files...
+ PUSHD %base_dir%\project\Win32BuildSetup
+ IF EXIST BUILD_WIN32\application rmdir BUILD_WIN32\application /S /Q
+ rem Add files to exclude.txt that should not be included in the installer
+
+ Echo Thumbs.db>>exclude.txt
+ Echo Desktop.ini>>exclude.txt
+ Echo dsstdfx.bin>>exclude.txt
+ Echo exclude.txt>>exclude.txt
+ Echo xbmc.log>>exclude.txt
+ Echo xbmc.old.log>>exclude.txt
+ Echo kodi.log>>exclude.txt
+ Echo kodi.old.log>>exclude.txt
+ Echo .so\>>exclude.txt
+ Echo .h\>>exclude.txt
+ Echo .cpp\>>exclude.txt
+ Echo .exp\>>exclude.txt
+ Echo .lib\>>exclude.txt
+ rem Exclude userdata files
+ Echo userdata\advancedsettings.xml>>exclude.txt
+ Echo userdata\guisettings.xml>>exclude.txt
+ Echo userdata\mediasources.xml>>exclude.txt
+ Echo userdata\ModeLines_template.xml>>exclude.txt
+ Echo userdata\passwords.xml>>exclude.txt
+ Echo userdata\profiles.xml>>exclude.txt
+ Echo userdata\sources.xml>>exclude.txt
+ Echo userdata\upnpserver.xml>>exclude.txt
+ rem Exclude userdata folders
+ Echo userdata\addon_data\>>exclude.txt
+ Echo userdata\cache\>>exclude.txt
+ Echo userdata\database\>>exclude.txt
+ Echo userdata\playlists\>>exclude.txt
+ Echo userdata\thumbnails\>>exclude.txt
+
+ rem Exclude dlls from system to avoid duplicates
+ Echo .dll>>exclude_dll.txt
+
+ md BUILD_WIN32\application
+
+ xcopy %EXE% BUILD_WIN32\application > NUL
+ xcopy %D3D% BUILD_WIN32\application > NUL
+ xcopy %base_dir%\userdata BUILD_WIN32\application\userdata /E /Q /I /Y /EXCLUDE:exclude.txt > NUL
+ copy %base_dir%\LICENSE.md BUILD_WIN32\application > NUL
+ copy %base_dir%\privacy-policy.txt BUILD_WIN32\application > NUL
+ copy %base_dir%\known_issues.txt BUILD_WIN32\application > NUL
+
+ xcopy %WORKSPACE%\addons BUILD_WIN32\application\addons /E /Q /I /Y /EXCLUDE:exclude.txt > NUL
+ xcopy %WORKSPACE%\*.dll BUILD_WIN32\application /Q /I /Y > NUL
+ xcopy %WORKSPACE%\libbluray-*.jar BUILD_WIN32\application /Q /I /Y > NUL
+ xcopy %WORKSPACE%\system BUILD_WIN32\application\system /E /Q /I /Y /EXCLUDE:exclude.txt+exclude_dll.txt > NUL
+ xcopy %WORKSPACE%\media BUILD_WIN32\application\media /E /Q /I /Y /EXCLUDE:exclude.txt > NUL
+
+ REM create AppxManifest.xml
+ @PowerShell "(GC .\AppxManifest.xml.in)|%%{$_" ^
+ " -Replace '@APP_NAME@', '%APP_NAME%'" ^
+ " -Replace '@COMPANY_NAME@', '%COMPANY_NAME%'" ^
+ " -Replace '@TARGET_ARCHITECTURE@', '%TARGET_ARCHITECTURE%'" ^
+ " -Replace '@VERSION_CODE@', '%VERSION_CODE%'" ^
+ " -Replace '@PACKAGE_IDENTITY@', '%PACKAGE_IDENTITY%'" ^
+ " -Replace '@PACKAGE_PUBLISHER@', '%PACKAGE_PUBLISHER%'" ^
+ " -Replace '@PACKAGE_DESCRIPTION@', '%PACKAGE_DESCRIPTION%'" ^
+ "}|SC .\BUILD_WIN32\application\AppxManifest.xml"
+
+ SET build_path=%CD%
+ IF %buildbinaryaddons%==true (
+ ECHO ------------------------------------------------------------
+ ECHO Building addons...
+ cd %base_dir%\tools\buildsteps\windows
+ IF %buildmode%==clean (
+ call make-addons.bat clean
+ )
+ call make-addons.bat
+ IF %errorlevel%==1 (
+ set DIETEXT="failed to build addons"
+ cd %build_path%
+ goto DIE
+ )
+
+ cd %build_path%
+ IF EXIST error.log del error.log > NUL
+ )
+
+ rem restore title, some scripts mess these up
+ TITLE %APP_NAME% for Windows Build Script
+
+ IF EXIST exclude.txt del exclude.txt > NUL
+ IF EXIST exclude_dll.txt del exclude_dll.txt > NUL
+ POPD
+
+ ECHO ------------------------------------------------------------
+ ECHO Build Succeeded!
+ GOTO NSIS_EXE
+
+:NSIS_EXE
+ ECHO ------------------------------------------------------------
+ ECHO Generating installer includes...
+ PUSHD %base_dir%\project\Win32BuildSetup
+ call genNsisIncludes.bat
+ ECHO ------------------------------------------------------------
+ call getdeploydependencies.bat
+ CALL extract_git_rev.bat > NUL
+ SET APP_SETUPFILE=%APP_NAME%Setup-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.exe
+ SET APP_PDBFILE=%APP_NAME%Setup-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.pdb
+ ECHO Creating installer %APP_SETUPFILE%...
+ IF EXIST %APP_SETUPFILE% del %APP_SETUPFILE% > NUL
+
+ rem determine if current system is 32 or 64 bits
+ SET HOST_BITS=32
+ IF %PROCESSOR_ARCHITECTURE% == AMD64 SET HOST_BITS=64
+ IF %PROCESSOR_ARCHITECTURE% == ARM64 SET HOST_BITS=64
+
+ IF %HOST_BITS% == 64 (
+ SET NSIS_REG_KEY=HKLM\Software\Wow6432Node\NSIS
+ ) ELSE (
+ SET NSIS_REG_KEY=HKLM\Software\NSIS
+ )
+
+ rem get path to makensis.exe from registry, first try tab delim
+ FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "%NSIS_REG_KEY%" /ve') DO SET NSISExePath=%%B
+
+ IF NOT EXIST "%NSISExePath%" (
+ rem try with space delim instead of tab
+ FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "%NSIS_REG_KEY%" /ve') DO SET NSISExePath=%%B
+ )
+
+ IF NOT EXIST "%NSISExePath%" (
+ rem fails on localized windows (Default) becomes (Par D�faut)
+ FOR /F "tokens=3* delims= " %%A IN ('REG QUERY "%NSIS_REG_KEY%" /ve') DO SET NSISExePath=%%B
+ )
+
+ IF NOT EXIST "%NSISExePath%" (
+ FOR /F "tokens=3* delims= " %%A IN ('REG QUERY "%NSIS_REG_KEY%" /ve') DO SET NSISExePath=%%B
+ )
+
+ SET NSISExe=%NSISExePath%\makensis.exe
+ "%NSISExe%" /V1 /X"SetCompressor /FINAL lzma" /Dapp_root="%CD%\BUILD_WIN32" /DAPP_NAME="%APP_NAME%" /DTARGET_ARCHITECTURE="%TARGET_ARCHITECTURE%" /DVERSION_NUMBER="%VERSION_CODE%.0" /DCOMPANY_NAME="%COMPANY_NAME%" /DWEBSITE="%WEBSITE%" /Dapp_revision="%GIT_REV%" /Dapp_branch="%BRANCH%" /D%TARGET_ARCHITECTURE% "genNsisInstaller.nsi"
+ IF NOT EXIST "%APP_SETUPFILE%" (
+ POPD
+ set DIETEXT=Failed to create %APP_SETUPFILE%. NSIS installed?
+ goto DIE
+ )
+ copy %PDB% %APP_PDBFILE% > nul
+ ECHO ------------------------------------------------------------
+ ECHO Done!
+ ECHO Setup is located at %CD%\%APP_SETUPFILE%
+ ECHO ------------------------------------------------------------
+ POPD
+ GOTO END
+
+:MAKE_APPX
+ set app_ext=msix
+ set app_path=%base_dir%\project\UWPBuildSetup
+ if not exist "%app_path%" mkdir %app_path%
+ call %base_dir%\project\Win32BuildSetup\extract_git_rev.bat > NUL
+ for /F %%a IN ('dir /B /S %WORKSPACE%\AppPackages ^| findstr /I /R "%APP_NAME%_.*_%TARGET_ARCHITECTURE%_%buildconfig%\.%app_ext%$"') DO (
+ copy /Y %%a %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.%app_ext%
+ copy /Y %%~dpna.cer %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.cer
+ copy /Y %%~dpna.appxsym %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.appxsym
+ goto END_APPX
+ )
+ rem Release builds don't have Release in it's name
+ for /F %%a IN ('dir /B /S %WORKSPACE%\AppPackages ^| findstr /I /R "%APP_NAME%_.*_%TARGET_ARCHITECTURE%\.%app_ext%$"') DO (
+ copy /Y %%a %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.%app_ext%
+ copy /Y %%~dpna.cer %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.cer
+ copy /Y %%~dpna.appxsym %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.appxsym
+ goto END_APPX
+ )
+
+ rem apxx file has win32 instead of x86 in it's name
+ if %TARGET_ARCHITECTURE%==x86 (
+ for /F %%a IN ('dir /B /S %WORKSPACE%\AppPackages ^| findstr /I /R "%APP_NAME%_.*_win32_%buildconfig%\.%app_ext%$"') DO (
+ copy /Y %%a %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.%app_ext%
+ copy /Y %%~dpna.cer %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.cer
+ copy /Y %%~dpna.appxsym %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.appxsym
+ goto END_APPX
+ )
+
+ rem Release builds don't have Release in it's name
+ for /F %%a IN ('dir /B /S %WORKSPACE%\AppPackages ^| findstr /I /R "%APP_NAME%_.*_win32\.%app_ext%$"') DO (
+ copy /Y %%a %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.%app_ext%
+ copy /Y %%~dpna.cer %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.cer
+ copy /Y %%~dpna.appxsym %app_path%\%APP_NAME%-%GIT_REV%-%BRANCH%-%TARGET_ARCHITECTURE%.appxsym
+ goto END_APPX
+ )
+ )
+
+:END_APPX
+ ECHO ------------------------------------------------------------
+ ECHO Done!
+ ECHO Setup is located at %app_path%
+ ECHO ------------------------------------------------------------
+ GOTO END
+
+:DIE
+ ECHO ------------------------------------------------------------
+ ECHO !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-
+ ECHO ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR
+ ECHO !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-
+ set DIETEXT=ERROR: %DIETEXT%
+ echo %DIETEXT%
+ SET exitcode=1
+ ECHO ------------------------------------------------------------
+ GOTO END
+
+:END
+ IF %promptlevel% NEQ noprompt (
+ ECHO Press any key to exit...
+ pause > NUL
+ )
+ EXIT /B %exitcode%
diff --git a/tools/buildsteps/windows/arm-uwp/BuildSetup.bat b/tools/buildsteps/windows/arm-uwp/BuildSetup.bat
new file mode 100644
index 0000000..8fd6e03
--- /dev/null
+++ b/tools/buildsteps/windows/arm-uwp/BuildSetup.bat
@@ -0,0 +1,19 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+
+CALL vswhere.bat arm store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+
+SET cmakeGenerator=Visual Studio %vsver%
+SET cmakeArch=ARM
+SET TARGET_ARCHITECTURE=arm
+SET TARGET_PLATFORM=%TARGET_ARCHITECTURE%-uwp
+SET cmakeProps=-DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=%UCRTVersion%
+
+CALL BuildSetup.bat %*
+POPD
diff --git a/tools/buildsteps/windows/arm-uwp/bootstrap-addons.bat b/tools/buildsteps/windows/arm-uwp/bootstrap-addons.bat
new file mode 100644
index 0000000..0e672f0
--- /dev/null
+++ b/tools/buildsteps/windows/arm-uwp/bootstrap-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat arm store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL bootstrap-addons %*
+POPD
diff --git a/tools/buildsteps/windows/arm-uwp/download-dependencies.bat b/tools/buildsteps/windows/arm-uwp/download-dependencies.bat
new file mode 100644
index 0000000..36b23ff
--- /dev/null
+++ b/tools/buildsteps/windows/arm-uwp/download-dependencies.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-dependencies.bat win10-arm
+POPD
diff --git a/tools/buildsteps/windows/arm-uwp/download-msys2.bat b/tools/buildsteps/windows/arm-uwp/download-msys2.bat
new file mode 100644
index 0000000..8c041ba
--- /dev/null
+++ b/tools/buildsteps/windows/arm-uwp/download-msys2.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-msys2.bat %*
+POPD
diff --git a/tools/buildsteps/windows/arm-uwp/make-addons.bat b/tools/buildsteps/windows/arm-uwp/make-addons.bat
new file mode 100644
index 0000000..6c23384
--- /dev/null
+++ b/tools/buildsteps/windows/arm-uwp/make-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat arm store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-addons.bat win10 %*
+POPD
diff --git a/tools/buildsteps/windows/arm-uwp/make-mingwlibs.bat b/tools/buildsteps/windows/arm-uwp/make-mingwlibs.bat
new file mode 100644
index 0000000..6a59615
--- /dev/null
+++ b/tools/buildsteps/windows/arm-uwp/make-mingwlibs.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat arm store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-mingwlibs.bat buildArm win10 %*
+POPD
diff --git a/tools/buildsteps/windows/arm-uwp/prepare-env.bat b/tools/buildsteps/windows/arm-uwp/prepare-env.bat
new file mode 100644
index 0000000..354a5cf
--- /dev/null
+++ b/tools/buildsteps/windows/arm-uwp/prepare-env.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL prepare-env.bat
+POPD
diff --git a/tools/buildsteps/windows/bootstrap-addons.bat b/tools/buildsteps/windows/bootstrap-addons.bat
new file mode 100644
index 0000000..cbd2b44
--- /dev/null
+++ b/tools/buildsteps/windows/bootstrap-addons.bat
@@ -0,0 +1,91 @@
+@ECHO OFF
+
+SETLOCAL
+
+SET EXITCODE=0
+
+SET clean=false
+if "%1" == "clean" (
+ SET clean=true
+) ELSE (
+ IF "%1" NEQ "" (
+ SET REPOSITORY=%1
+
+ IF "%2" NEQ "" (
+ SET REPOSITORY_REVISION=%2
+ )
+ )
+)
+
+PUSHD %~dp0\..\..\..
+SET WORKDIR=%CD%
+POPD
+
+rem setup some paths that we need later
+SET CUR_PATH=%CD%
+SET BASE_PATH=%WORKDIR%\cmake
+SET ADDONS_PATH=%BASE_PATH%\addons
+SET ADDONS_BOOTSTRAP_PATH=%ADDONS_PATH%\bootstrap
+SET BOOTSTRAP_BUILD_PATH=%ADDONS_PATH%\build\bootstrap
+SET ADDONS_DEFINITION_PATH=%ADDONS_PATH%\addons
+
+IF %clean% == true (
+ rem remove the build directory if it exists
+ IF EXIST "%BOOTSTRAP_BUILD_PATH%" (
+ ECHO Cleaning build directory...
+ RMDIR "%BOOTSTRAP_BUILD_PATH%" /S /Q > NUL
+ )
+
+ rem clean the addons definition path if it exists
+ IF EXIST "%ADDONS_DEFINITION_PATH%" (
+ ECHO Cleaning bootstrapped addons...
+ RMDIR "%ADDONS_DEFINITION_PATH%" /S /Q > NUL
+ )
+
+ GOTO END
+)
+
+rem create the build directory
+IF NOT EXIST "%BOOTSTRAP_BUILD_PATH%" MKDIR "%BOOTSTRAP_BUILD_PATH%"
+
+rem create the addons definition directory
+IF NOT EXIST "%ADDONS_DEFINITION_PATH%" MKDIR "%ADDONS_DEFINITION_PATH%"
+
+rem go into the build directory
+CD "%BOOTSTRAP_BUILD_PATH%"
+
+ECHO --------------------------------------------------
+ECHO Bootstrapping addons
+ECHO --------------------------------------------------
+
+rem execute cmake to generate makefiles processable by nmake
+cmake "%ADDONS_BOOTSTRAP_PATH%" -G "NMake Makefiles" ^
+ -DCMAKE_BUILD_TYPE=Release ^
+ -DCMAKE_INSTALL_PREFIX=%ADDONS_DEFINITION_PATH% ^
+ -DBUILD_DIR=%BOOTSTRAP_BUILD_PATH% ^
+ -DREPOSITORY_TO_BUILD="%REPOSITORY%" ^
+ -DREPOSITORY_REVISION="%REPOSITORY_REVISION%"
+IF ERRORLEVEL 1 (
+ ECHO cmake error level: %ERRORLEVEL%
+ GOTO ERROR
+)
+
+rem execute nmake to prepare the buildsystem
+nmake
+IF ERRORLEVEL 1 (
+ ECHO nmake failed with error level: %ERRORLEVEL%
+)
+rem everything was fine
+GOTO END
+
+:ERROR
+rem something went wrong
+ECHO Failed to bootstrap addons
+SET EXITCODE=1
+
+:END
+rem go back to the original directory
+cd %CUR_PATH%
+
+rem exit the script with the defined exitcode
+EXIT /B %EXITCODE%
diff --git a/tools/buildsteps/windows/buildffmpeg.sh b/tools/buildsteps/windows/buildffmpeg.sh
new file mode 100644
index 0000000..f2e72cb
--- /dev/null
+++ b/tools/buildsteps/windows/buildffmpeg.sh
@@ -0,0 +1,129 @@
+#!/bin/bash
+
+[[ -f buildhelpers.sh ]] &&
+ source buildhelpers.sh
+
+FFMPEG_CONFIG_FILE=/xbmc/tools/buildsteps/windows/ffmpeg_options.txt
+FFMPEG_VERSION_FILE=/xbmc/tools/depends/target/ffmpeg/FFMPEG-VERSION
+FFMPEG_BASE_OPTS="--disable-debug --disable-doc --enable-gpl --enable-w32threads"
+FFMPEG_DEFAULT_OPTS=""
+FFMPEG_TARGET_OS=mingw32
+
+do_loaddeps $FFMPEG_VERSION_FILE
+FFMPEGDESTDIR=$PREFIX
+
+do_getFFmpegConfig() {
+ if [[ -f "$FFMPEG_CONFIG_FILE" ]]; then
+ FFMPEG_OPTS_SHARED="$FFMPEG_BASE_OPTS $(cat "$FFMPEG_CONFIG_FILE" | sed -e 's:\\::g' -e 's/#.*//')"
+ else
+ FFMPEG_OPTS_SHARED="$FFMPEG_BASE_OPTS $FFMPEG_DEFAULT_OPTS"
+ fi
+
+ if [ "$ARCH" == "x86_64" ]; then
+ FFMPEG_TARGET_OS=mingw64
+ elif [ "$ARCH" == "x86" ]; then
+ FFMPEG_TARGET_OS=mingw32
+ do_addOption "--cpu=i686"
+ elif [ "$ARCH" == "arm" ]; then
+ FFMPEG_TARGET_OS=mingw32
+ do_addOption "--cpu=armv7"
+ fi
+
+ # add options for static modplug
+ if do_checkForOptions "--enable-libmodplug"; then
+ do_addOption "--extra-cflags=-DMODPLUG_STATIC"
+ fi
+
+ # handle gplv3 libs
+ if do_checkForOptions "--enable-libopencore-amrwb --enable-libopencore-amrnb \
+ --enable-libvo-aacenc --enable-libvo-amrwbenc"; then
+ do_addOption "--enable-version3"
+ fi
+
+ do_removeOption "--enable-nonfree"
+ do_removeOption "--enable-libfdk-aac"
+ do_removeOption "--enable-nvenc"
+ do_removeOption "--enable-libfaac"
+
+ # remove libs that don't work with shared
+ do_removeOption "--enable-decklink"
+ do_removeOption "--enable-libutvideo"
+ do_removeOption "--enable-libgme"
+}
+
+do_checkForOptions() {
+ local isPresent=1
+ for option in "$@"; do
+ for option2 in $option; do
+ if echo "$FFMPEG_OPTS_SHARED" | grep -q -E -e "$option2"; then
+ isPresent=0
+ fi
+ done
+ done
+ return $isPresent
+}
+
+do_addOption() {
+ local option=${1%% *}
+ local shared=$2
+ if ! do_checkForOptions "$option"; then
+ FFMPEG_OPTS_SHARED="$FFMPEG_OPTS_SHARED $option"
+ fi
+}
+
+do_removeOption() {
+ local option=${1%% *}
+ FFMPEG_OPTS_SHARED=$(echo "$FFMPEG_OPTS_SHARED" | sed "s/ *$option//g")
+}
+
+do_getFFmpegConfig
+
+# enable OpenSSL, because schannel has issues
+do_removeOption "--enable-gnutls"
+do_addOption "--disable-gnutls"
+do_addOption "--enable-openssl"
+do_addOption "--enable-nonfree"
+do_addOption "--toolchain=msvc"
+do_addOption "--disable-mediafoundation"
+
+if [ "$ARCH" == "x86_64" ]; then
+ FFMPEG_TARGET_OS=win64
+elif [ "$ARCH" = "x86" ]; then
+ FFMPEG_TARGET_OS=win32
+elif [ "$ARCH" = "arm" ]; then
+ FFMPEG_TARGET_OS=win32
+fi
+
+export CFLAGS=""
+export CXXFLAGS=""
+export LDFLAGS=""
+
+extra_cflags="-I$LOCALDESTDIR/include -I/depends/$TRIPLET/include -DWIN32_LEAN_AND_MEAN"
+extra_ldflags="-LIBPATH:\"$LOCALDESTDIR/lib\" -LIBPATH:\"$MINGW_PREFIX/lib\" -LIBPATH:\"/depends/$TRIPLET/lib\""
+if [ $win10 == "yes" ]; then
+ do_addOption "--enable-cross-compile"
+ extra_cflags=$extra_cflags" -MD -DWINAPI_FAMILY=WINAPI_FAMILY_APP -D_WIN32_WINNT=0x0A00"
+ extra_ldflags=$extra_ldflags" -APPCONTAINER WindowsApp.lib"
+fi
+
+# compile ffmpeg with debug symbols
+if do_checkForOptions "--enable-debug"; then
+ extra_cflags=$extra_cflags" -MDd"
+ extra_ldflags=$extra_ldflags" -NODEFAULTLIB:libcmt"
+fi
+
+cd $LOCALBUILDDIR
+
+do_clean_get $1
+[ -f config.mak ] && make distclean
+do_print_status "$LIBNAME-$VERSION (${TRIPLET})" "$blue_color" "Configuring"
+
+[[ -z "$extra_cflags" ]] && extra_cflags=-DPTW32_STATIC_LIB
+[[ -z "$extra_ldflags" ]] && extra_ldflags=-static-libgcc
+
+$LOCALSRCDIR/configure --target-os=$FFMPEG_TARGET_OS --prefix=$FFMPEGDESTDIR --arch=$ARCH \
+ $FFMPEG_OPTS_SHARED \
+ --extra-cflags="$extra_cflags" --extra-ldflags="$extra_ldflags"
+
+do_makelib
+exit $?
diff --git a/tools/buildsteps/windows/buildhelpers.sh b/tools/buildsteps/windows/buildhelpers.sh
new file mode 100644
index 0000000..2a059de
--- /dev/null
+++ b/tools/buildsteps/windows/buildhelpers.sh
@@ -0,0 +1,216 @@
+#!/bin/bash
+
+MAKEFLAGS="$1"
+BGPROCESSFILE="$2"
+
+cpuCount=1
+if [[ $NUMBER_OF_PROCESSORS > 1 ]]; then
+ if [[ $NUMBER_OF_PROCESSORS > 4 ]]; then
+ cpuCount=$NUMBER_OF_PROCESSORS
+ else
+ cpuCount=`expr $NUMBER_OF_PROCESSORS + $NUMBER_OF_PROCESSORS / 2`
+ fi
+fi
+if [[ ! $cpuCount =~ ^[0-9]+$ ]]; then
+ cpuCount="$(($(nproc)/2))"
+fi
+
+if which tput >/dev/null 2>&1; then
+ ncolors=$(tput colors)
+ if test -n "$ncolors" && test "$ncolors" -ge 8; then
+ bold_color=$(tput bold)
+ blue_color=$(tput setaf 4)
+ orange_color=$(tput setaf 3)
+ green_color=$(tput setaf 2)
+ red_color=$(tput setaf 1)
+ reset_color=$(tput sgr0)
+ fi
+ ncols=72
+fi
+
+if [[ ! -d /build/src ]]; then
+ mkdir /build/src
+fi
+
+do_wget() {
+ local URL="$1"
+ local archive="$2"
+
+ if [[ -z $archive ]]; then
+ wget --tries=5 --retry-connrefused --waitretry=2 --no-check-certificate -c -P /downloads/ $URL
+ else
+ wget --tries=5 --retry-connrefused --waitretry=2 --no-check-certificate -c $URL -O /downloads/$archive
+ fi
+}
+
+do_makeinstall() {
+ make -j"$cpuCount" "$@"
+ make install
+}
+
+do_makelib() {
+ do_print_status "$LIBNAME-$VERSION (${TRIPLET})" "$blue_color" "Compiling"
+ do_makeinstall $1
+ if [ $? == 0 ]; then
+ do_print_status "$LIBNAME-$VERSION (${TRIPLET})" "$green_color" "Done"
+ else
+ do_print_status "$LIBNAME-$VERSION (${TRIPLET})" "$red_color" "Error"
+ fi
+}
+
+do_print_status() {
+ local pad=$(printf '%0.1s' "."{1..72})
+ local padlen=$((${#pad}-${#1}-${#3}))
+ printf '%s %*.*s%s%s%s\n' "${bold_color}$1${reset_color}" 0 "$padlen" "$pad" " [$2" "$3" "$reset_color]"
+}
+
+do_print_progress() {
+ echo -e "\e]0;$* in $(get_first_subdir)\007"
+ echo -e "${bold_color}$* in $(get_first_subdir)${reset_color}"
+}
+
+get_first_subdir() {
+ local subdir="${PWD#*build/}"
+ if [[ "$subdir" != "$PWD" ]]; then
+ subdir="${subdir%%/*}"
+ echo "$subdir"
+ else
+ echo "."
+ fi
+}
+
+do_pkgConfig() {
+ local pkg=${1%% *}
+ local version=$2
+ [[ -z "$version" ]] && version="${1##*= }"
+ [[ "$version" = "$1" ]] && version="" || version=" $version"
+ local prefix=$(pkg-config --variable=prefix --silence-errors "$1")
+ [[ ! -z "$prefix" ]] && prefix="$(cygpath -u "$prefix")"
+ if [[ "$prefix" = "$LOCALDESTDIR" || "$prefix" = "/trunk${LOCALDESTDIR}" ]]; then
+ do_print_status "${pkg} ${version}" "$green_color" "Up-to-date"
+ return 1
+ else
+ do_print_status "${pkg} ${version}" "$red_color" "Not installed"
+ fi
+}
+
+do_autoreconf() {
+ if [[ ! -f $LOCALSRCDIR/configure ]]; then
+ local CURDIR=$(pwd)
+ cd $LOCALSRCDIR
+ autoreconf -fiv
+ cd $CURDIR
+ fi
+}
+
+do_clean() {
+ if [[ "$1" == "clean" ]]; then
+ if [ -d "$LIBBUILDDIR" ]; then
+ do_print_status "$LIBNAME ($TRIPLET)" "$red_color" "Removing"
+ rm -rf "$LIBBUILDDIR"
+ fi
+ fi
+}
+
+do_download() {
+ if [ ! -d "$LOCALSRCDIR" ]; then
+ if [ ! -f /downloads/$ARCHIVE ]; then
+ do_print_status "$LIBNAME-$VERSION" "$orange_color" "Downloading"
+ do_wget $BASE_URL/$VERSION.tar.gz $ARCHIVE
+ fi
+
+ do_print_status "$LIBNAME-$VERSION" "$blue_color" "Extracting"
+ mkdir $LOCALSRCDIR && cd $LOCALSRCDIR
+ tar -xaf /downloads/$ARCHIVE --strip 1
+ fi
+ # applying patches
+ local patches=(/xbmc/tools/buildsteps/windows/patches/*-$LIBNAME-*.patch)
+ for patch in ${patches[@]}; do
+ echo "Applying patch ${patch}"
+ if [[ -f $patch ]]; then
+ patch -p1 -d $LOCALSRCDIR -i $patch -N -r -
+ fi
+ done
+}
+
+do_loaddeps() {
+ local file="$1"
+ LIBNAME=$(grep "LIBNAME=" $file | sed 's/LIBNAME=//g;s/#.*$//g;/^$/d')
+ BASE_URL=$(grep "BASE_URL=" $file | sed 's/BASE_URL=//g;s/#.*$//g;/^$/d')
+ VERSION=$(grep "VERSION=" $file | sed 's/VERSION=//g;s/#.*$//g;/^$/d')
+ GITREV=$(git ls-remote $BASE_URL $VERSION | awk '{print substr($1, 1, 10)}')
+ if [[ -z "$GITREV" ]]; then
+ ARCHIVE=$LIBNAME-$(echo "${VERSION}" | sed 's/\//-/g').tar.gz
+ else
+ ARCHIVE=$LIBNAME-$GITREV.tar.gz
+ fi
+ BASE_URL=$BASE_URL/archive
+ local libsrcdir=$LIBNAME-$VERSION
+ if [[ ! -z "$GITREV" ]]; then
+ libsrcdir=$LIBNAME-$GITREV
+ fi
+ LOCALSRCDIR=$LOCALBUILDDIR/src/$libsrcdir
+ LIBBUILDDIR=$LOCALBUILDDIR/$LIBNAME-$TRIPLET
+}
+
+do_clean_get() {
+ do_clean $1
+ do_download
+
+ if [[ ! -d "$LIBBUILDDIR" ]]; then
+ mkdir "$LIBBUILDDIR"
+ fi
+ cd "$LIBBUILDDIR"
+}
+
+
+PATH_CHANGE_REV_FILENAME=".last_success_revision"
+
+#hash a dir based on the git revision and $TRIPLET
+#params paths to be hashed
+function getBuildHash ()
+{
+ local hashStr
+ hashStr="$(git rev-list HEAD --max-count=1 -- $@)"
+ hashStr="$hashStr $@ $TRIPLET"
+ echo $hashStr
+}
+
+#param1 path to be checked for changes
+function pathChanged ()
+{
+ local ret
+ local checkPath
+ ret="0"
+ #no optims in release builds!
+ if [ "$Configuration" == "Release" ]
+ then
+ echo "1"
+ return
+ fi
+
+ checkPath="$1"
+ shift 1
+ if [ -e $checkPath/$PATH_CHANGE_REV_FILENAME ]
+ then
+ if [ "$(cat $checkPath/$PATH_CHANGE_REV_FILENAME)" != "$(getBuildHash $checkPath $@)" ]
+ then
+ ret="1"
+ fi
+ else
+ ret="1"
+ fi
+
+ echo $ret
+}
+
+#param1 path to be tagged with hash
+function tagSuccessFulBuild ()
+{
+ local pathToTag
+ pathToTag="$1"
+ shift 1
+ # tag last successful build with revisions of the given dir
+ # needs to match the checks in function getBuildHash
+ echo "$(getBuildHash $pathToTag $@)" > $pathToTag/$PATH_CHANGE_REV_FILENAME
+}
diff --git a/tools/buildsteps/windows/download-dependencies.bat b/tools/buildsteps/windows/download-dependencies.bat
new file mode 100644
index 0000000..0a129fd
--- /dev/null
+++ b/tools/buildsteps/windows/download-dependencies.bat
@@ -0,0 +1,72 @@
+@ECHO OFF
+
+SETLOCAL
+
+PUSHD %~dp0\..\..\..
+SET WORKSPACE=%CD%
+POPD
+
+SET TARGETPLATFORM=%1
+SET NATIVEPLATFORM=%2
+
+IF "%TARGETPLATFORM%" == "" SET TARGETPLATFORM=win32
+IF "%NATIVEPLATFORM%" == "" SET NATIVEPLATFORM=win32
+
+ECHO TARGETPLATFORM: %TARGETPLATFORM%
+ECHO NATIVEPLATFORM: %NATIVEPLATFORM%
+
+REM If KODI_MIRROR is not set externally to this script, set it to the default mirror URL
+IF "%KODI_MIRROR%" == "" SET KODI_MIRROR=http://mirrors.kodi.tv
+echo Downloading from mirror %KODI_MIRROR%
+
+REM Locate the BuildDependencies directory, based on the path of this script
+SET BUILD_DEPS_PATH=%WORKSPACE%\project\BuildDependencies
+SET APP_PATH=%WORKSPACE%\project\BuildDependencies\%TARGETPLATFORM%
+SET TMP_PATH=%BUILD_DEPS_PATH%\scripts\tmp
+
+REM Change to the BuildDependencies directory, if we're not there already
+PUSHD %BUILD_DEPS_PATH%
+
+REM Can't run rmdir and md back to back. access denied error otherwise.
+IF EXIST %TMP_PATH% rmdir %TMP_PATH% /S /Q
+
+SET DL_PATH="%BUILD_DEPS_PATH%\downloads"
+SET WGET=%BUILD_DEPS_PATH%\bin\wget
+SET ZIP=%BUILD_DEPS_PATH%\..\Win32BuildSetup\tools\7z\7za
+
+IF NOT EXIST %DL_PATH% md %DL_PATH%
+
+md %TMP_PATH%
+
+cd scripts
+
+SET FORMED_OK_FLAG=%TMP_PATH%\got-all-formed-packages
+REM Trick to preserve console title
+start /b /wait cmd.exe /c get_formed.cmd
+IF NOT EXIST %FORMED_OK_FLAG% (
+ ECHO ERROR: Not all formed packages are ready!
+ ECHO.
+ ECHO I tried to get the packages from %KODI_MIRROR%;
+ ECHO if this download mirror seems to be having problems, try choosing another from
+ ECHO the list on http://mirrors.kodi.tv/timestamp.txt?mirrorlist, and setting %%KODI_MIRROR%% to
+ ECHO point to it, like so:
+ ECHO C:\^> SET KODI_MIRROR=http://example.com/pub/xbmc/
+ ECHO.
+ ECHO Then, rerun this script.
+
+ REM Restore the previous current directory
+ POPD
+
+ ENDLOCAL
+
+ EXIT /B 101
+)
+
+rmdir %TMP_PATH% /S /Q
+
+REM Restore the previous current directory
+POPD
+
+ENDLOCAL
+
+EXIT /B 0
diff --git a/tools/buildsteps/windows/download-msys2.bat b/tools/buildsteps/windows/download-msys2.bat
new file mode 100644
index 0000000..34c3472
--- /dev/null
+++ b/tools/buildsteps/windows/download-msys2.bat
@@ -0,0 +1,406 @@
+::-------------------------------------------------------------------------------------
+:: LICENSE -------------------------------------------------------------------------
+::-------------------------------------------------------------------------------------
+:: This Windows Batchscript is for setup a compiler environment for building ffmpeg and other media tools under Windows.
+::
+:: Copyright (C) 2013 jb_alvarado
+::
+:: This program is free software: you can redistribute it and/or modify
+:: it under the terms of the GNU General Public License as published by
+:: the Free Software Foundation, either version 3 of the License, or
+:: (at your option) any later version.
+::
+:: This program is distributed in the hope that it will be useful,
+:: but WITHOUT ANY WARRANTY; without even the implied warranty of
+:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+:: GNU General Public License for more details.
+::
+:: You should have received a copy of the GNU General Public License
+:: along with this program. If not, see <http://www.gnu.org/licenses/>.
+::-------------------------------------------------------------------------------------
+
+@echo off
+title msys2
+
+PUSHD %~dp0\..\..\..
+SET WORKSPACE=%CD%
+POPD
+
+set msysver=20210725
+set msys2=msys64
+set instdir=%WORKSPACE%\project\BuildDependencies
+set msyspackages=diffutils gcc make patch perl tar yasm
+set gaspreprocurl=https://github.com/FFmpeg/gas-preprocessor/archive/master.tar.gz
+set usemirror=yes
+set opt=mintty
+
+:: if KODI_MIRROR is not set externally to this script, set it to the default mirror URL
+if "%KODI_MIRROR%"=="" set KODI_MIRROR=http://mirrors.kodi.tv
+if "%usemirror%"=="yes" (
+ echo -------------------------------------------------------------------------------
+ echo. Downloading will be performed from mirror %KODI_MIRROR%
+ echo -------------------------------------------------------------------------------
+ set MSYS_MIRROR=%KODI_MIRROR%/build-deps/win32/msys2
+)
+
+set downloaddir=%instdir%\downloads2
+set unpack_exe=%instdir%\..\Win32BuildSetup\tools\7z\7za.exe
+
+for %%b in (%*) do (
+ if %%b==sh (set opt=sh)
+)
+
+:: use 32bit msys2 on x86 machine
+if %PROCESSOR_ARCHITECTURE%=="x86" set msys2=msys32
+if %msys2%==msys32 (set arch=i686) else (set arch=x86_64)
+set msysfile=msys2-base-%arch%-%msysver%.tar.xz
+if %opt%==mintty (
+ set sh=%instdir%\%msys2%\usr\bin\mintty.exe -d -i /msys2.ico /usr/bin/bash
+) else (
+ set sh=%instdir%\%msys2%\usr\bin\sh.exe
+)
+
+::------------------------------------------------------------------
+::download and install basic msys2 system:
+::------------------------------------------------------------------
+if exist "%instdir%\%msys2%\msys2_shell.cmd" GOTO minttySettings
+ if not exist %downloaddir% mkdir %downloaddir%
+
+:download
+if exist "%downloaddir%\%msysfile%" (
+ setlocal EnableDelayedExpansion
+ for /F "tokens=*" %%A in ("%downloaddir%\%msysfile%") do set fileSize=%%~zA
+ if !fileSize!==0 del %downloaddir%\%msysfile%
+ endlocal
+ )
+
+if exist "%downloaddir%\%msysfile%" GOTO unpack
+ echo -------------------------------------------------------------------------------
+ echo.- Download msys2 basic system (Kodi mirrors: %usemirror%)
+ echo -------------------------------------------------------------------------------
+
+ set msysurl=http://sourceforge.net/projects/msys2/files/Base/%arch%/%msysfile%/download
+ if %usemirror%==yes (
+ ::download msys2 from our mirror
+ set msysurl=%MSYS_MIRROR%/%msysfile%
+ )
+ %instdir%\bin\wget --tries=20 --retry-connrefused --waitretry=2 --no-check-certificate -c -O %downloaddir%\%msysfile% %msysurl%
+ if errorlevel == 1 (
+ if exist "%downloaddir%\%msysfile%" del %downloaddir%\%msysfile%
+ if %usemirror%==yes (
+ set usemirror=no
+ goto download
+ )
+ echo ERROR: Unable to download msys2!
+ exit /B 1
+ )
+
+:unpack
+if exist "%downloaddir%\%msysfile%" (
+ echo -------------------------------------------------------------------------------
+ echo.- Installing msys2 basic system
+ echo -------------------------------------------------------------------------------
+ %unpack_exe% x %downloaddir%\%msysfile% -so 2>NUL | %unpack_exe% x -aoa -si -ttar -o%instdir% >NUL 2>NUL
+ )
+
+if not exist %instdir%\%msys2%\usr\bin\msys-2.0.dll (
+ echo -------------------------------------------------------------------------------
+ echo.- Installing msys2 basic system failed,
+ echo -------------------------------------------------------------------------------
+ exit /B 1
+ )
+
+:minttySettings
+if exist "%instdir%\%msys2%\home\%USERNAME%\.minttyrc" GOTO updatemirrors
+if not exist "%instdir%\%msys2%\home\%USERNAME%" mkdir "%instdir%\%msys2%\home\%USERNAME%"
+ (
+ echo.BoldAsFont=no
+ echo.BackgroundColour=57,57,57
+ echo.ForegroundColour=221,221,221
+ echo.Transparency=medium
+ echo.FontHeight=^9
+ echo.FontSmoothing=full
+ echo.AllowBlinking=yes
+ echo.Columns=120
+ echo.Rows=30
+ echo.Term=xterm-256color
+ echo.CursorType=block
+ echo.ClicksPlaceCursor=yes
+ echo.Black=38,39,41
+ echo.Red=249,38,113
+ echo.Green=166,226,46
+ echo.Yellow=253,151,31
+ echo.Blue=102,217,239
+ echo.Magenta=158,111,254
+ echo.Cyan=94,113,117
+ echo.White=248,248,242
+ echo.BoldBlack=85,68,68
+ echo.BoldRed=249,38,113
+ echo.BoldGreen=166,226,46
+ echo.BoldYellow=253,151,31
+ echo.BoldBlue=102,217,239
+ echo.BoldMagenta=158,111,254
+ echo.BoldCyan=163,186,191
+ echo.BoldWhite=248,248,242
+ )>>"%instdir%\%msys2%\home\%USERNAME%\.minttyrc"
+
+:updatemirrors
+if not "%usemirror%"=="yes" GOTO rebase
+ echo.-------------------------------------------------------------------------------
+ echo.update pacman mirrors
+ echo.-------------------------------------------------------------------------------
+ setlocal EnableDelayedExpansion
+
+ for %%f in (msys,mingw32,mingw64) do (
+ set filename=%instdir%\%msys2%\etc\pacman.d\mirrorlist.%%f
+ set oldfile=!filename!.old
+ if not exist !oldfile! if exist !filename! (
+ set mirror=%MSYS_MIRROR%/repos/%%f
+ if %%f==msys set mirror=!mirror!2/$arch
+ move !filename! !oldfile!>nul
+ for /F "usebackq delims=" %%a in (!oldfile!) do (
+ echo %%a | find /i "server = http://repo.msys2.org/">nul && (
+ echo.Server = !mirror!
+ )>>!filename!
+ echo %%a>>!filename!
+ )
+ )
+ )
+ endlocal
+
+:rebase
+if %msys2%==msys32 (
+ echo.-------------------------------------------------------------------------------
+ echo.rebase msys32 system
+ echo.-------------------------------------------------------------------------------
+ call %instdir%\msys32\autorebase.bat
+ )
+
+:preparedirs
+if not exist %instdir%\build mkdir %instdir%\build
+if not exist %instdir%\downloads2 mkdir %instdir%\downloads2
+if not exist %instdir%\locals mkdir %instdir%\locals
+if not exist %instdir%\locals\win32 mkdir %instdir%\locals\win32
+if not exist %instdir%\locals\x64 mkdir %instdir%\locals\x64
+
+if not exist %instdir%\locals\win32\share (
+ echo.-------------------------------------------------------------------------------
+ echo.create local win32 folders
+ echo.-------------------------------------------------------------------------------
+ mkdir %instdir%\locals\win32\bin
+ mkdir %instdir%\locals\win32\etc
+ mkdir %instdir%\locals\win32\include
+ mkdir %instdir%\locals\win32\lib
+ mkdir %instdir%\locals\win32\lib\pkgconfig
+ mkdir %instdir%\locals\win32\share
+ )
+
+if not exist %instdir%\locals\x64\share (
+ echo.-------------------------------------------------------------------------------
+ echo.create local x64 folders
+ echo.-------------------------------------------------------------------------------
+ mkdir %instdir%\locals\x64\bin
+ mkdir %instdir%\locals\x64\etc
+ mkdir %instdir%\locals\x64\include
+ mkdir %instdir%\locals\x64\lib
+ mkdir %instdir%\locals\x64\lib\pkgconfig
+ mkdir %instdir%\locals\x64\share
+ )
+
+if not exist %instdir%\%msys2%\etc\fstab. GOTO writeFstab
+for /f "tokens=2 delims=/" %%a in ('findstr /i xbmc %instdir%\%msys2%\etc\fstab.') do set searchRes=%%a
+if "%searchRes%"=="xbmc" GOTO installbase
+
+:writeFstab
+echo -------------------------------------------------------------------------------
+echo.- write fstab mount file
+echo -------------------------------------------------------------------------------
+set cygdrive=no
+if exist %instdir%\%msys2%\etc\fstab. (
+ for /f %%b in ('findstr /i binary %instdir%\%msys2%\etc\fstab.') do set cygdrive=yes
+ )
+if "%cygdrive%"=="no" echo.none / cygdrive binary,posix=0,noacl,user 0 ^0>>%instdir%\%msys2%\etc\fstab.
+(
+ echo.
+ echo.%instdir%\build\ /build
+ echo.%instdir%\downloads\ /downloads
+ echo.%instdir%\locals\win32\ /local32
+ echo.%instdir%\locals\x64\ /local64
+ echo.%instdir%\%msys2%\mingw32\ /mingw32
+ echo.%instdir%\%msys2%\mingw64\ /mingw64
+ echo.%instdir%\downloads2\ /var/cache/pacman/pkg
+ echo.%instdir%\win32\ /depends/win32
+ echo.%instdir%\x64\ /depends/x64
+ echo.%instdir%\win10-arm\ /depends/win10-arm
+ echo.%instdir%\win10-win32\ /depends/win10-win32
+ echo.%instdir%\win10-x64\ /depends/win10-x64
+ echo.%instdir%\..\..\ /xbmc
+)>>%instdir%\%msys2%\etc\fstab.
+
+:installbase
+if exist "%instdir%\%msys2%\etc\pac-base-old.pk" del "%instdir%\%msys2%\etc\pac-base-old.pk"
+if exist "%instdir%\%msys2%\etc\pac-base-new.pk" ren "%instdir%\%msys2%\etc\pac-base-new.pk" pac-base-old.pk
+
+for %%i in (%msyspackages%) do echo.%%i>>%instdir%\%msys2%\etc\pac-base-new.pk
+
+if exist %instdir%\%msys2%\usr\bin\make.exe GOTO rebase2
+ echo.-------------------------------------------------------------------------------
+ echo.install msys2 base system
+ echo.-------------------------------------------------------------------------------
+ if exist %instdir%\pacman.sh del %instdir%\pacman.sh
+ (
+ echo.echo -ne "\033]0;install base system\007"
+ echo.pacman --noconfirm -S $(cat /etc/pac-base-new.pk ^| sed -e 's#\\##'^)
+ echo.sleep ^3
+ echo.exit
+ )>>%instdir%\pacman.sh
+ %sh% --login %instdir%\pacman.sh &
+ del %instdir%\pacman.sh
+
+ for %%i in (%instdir%\%msys2%\usr\ssl\cert.pem) do (
+ if %%~zi==0 (
+ echo.update-ca-trust>>cert.sh
+ echo.sleep ^3>>cert.sh
+ echo.exit>>cert.sh
+ %sh% --login %instdir%\cert.sh
+ del cert.sh
+ )
+ )
+
+:rebase2
+if %msys2%==msys32 (
+ echo.-------------------------------------------------------------------------------
+ echo.second rebase msys32 system
+ echo.-------------------------------------------------------------------------------
+ call %instdir%\msys32\autorebase.bat
+ )
+
+::------------------------------------------------------------------
+:: write config profiles:
+::------------------------------------------------------------------
+
+:writeProfile32
+if exist %instdir%\locals\win32\etc\profile.local GOTO writeProfile64
+ echo -------------------------------------------------------------------------------
+ echo.- write profile for 32 bit compiling
+ echo -------------------------------------------------------------------------------
+ (
+ echo.#
+ echo.# /local32/etc/profile.local
+ echo.#
+ echo.
+ echo.MSYSTEM=MINGW32
+ echo.
+ echo.alias dir='ls -la --color=auto'
+ echo.alias ls='ls --color=auto'
+ echo.export CC=gcc
+ echo.export python=/usr/bin/python
+ echo.
+ echo.MSYS2_PATH="/usr/local/bin:/usr/bin"
+ echo.MANPATH="/usr/share/man:/mingw32/share/man:/local32/man:/local32/share/man"
+ echo.INFOPATH="/usr/local/info:/usr/share/info:/usr/info:/mingw32/share/info"
+ echo.MINGW_PREFIX="/mingw32"
+ echo.MINGW_CHOST="i686-w64-mingw32"
+ echo.export MSYSTEM MINGW_PREFIX MINGW_CHOST
+ echo.
+ echo.DXSDK_DIR="/mingw32/i686-w64-mingw32"
+ echo.ACLOCAL_PATH="/mingw32/share/aclocal:/usr/share/aclocal"
+ echo.PKG_CONFIG_LOCAL_PATH="/local32/lib/pkgconfig"
+ echo.PKG_CONFIG_PATH="/local32/lib/pkgconfig:/mingw32/lib/pkgconfig"
+ echo.CPPFLAGS="-I/local32/include -D_FORTIFY_SOURCE=2"
+ echo.CFLAGS="-I/local32/include -mms-bitfields -mthreads -mtune=generic -pipe"
+ echo.CXXFLAGS="-I/local32/include -mms-bitfields -mthreads -mtune=generic -pipe"
+ echo.LDFLAGS="-L/local32/lib -mthreads -pipe"
+ echo.export DXSDK_DIR ACLOCAL_PATH PKG_CONFIG_PATH PKG_CONFIG_LOCAL_PATH CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MSYSTEM
+ echo.
+ echo.PYTHONHOME=/usr
+ echo.PYTHONPATH="/usr/lib/python2.7:/usr/lib/python2.7/Tools/Scripts"
+ echo.
+ echo.PATH=".:/local32/bin:/mingw32/bin:${MSYS2_PATH}:${INFOPATH}:${PYTHONHOME}:${PYTHONPATH}:${PATH}"
+ echo.PS1='\[\033[32m\]\u@\h \[\e[33m\]\w\[\e[0m\]\n\$ '
+ echo.export PATH PS1
+ echo.
+ echo.# package build directory
+ echo.LOCALBUILDDIR=/build
+ echo.# package installation prefix
+ echo.LOCALDESTDIR=/local32
+ echo.export LOCALBUILDDIR LOCALDESTDIR
+ )>>%instdir%\locals\win32\etc\profile.local
+ )
+
+:writeProfile64
+if exist %instdir%\locals\x64\etc\profile.local GOTO loadGasPreproc
+ echo -------------------------------------------------------------------------------
+ echo.- write profile for 64 bit compiling
+ echo -------------------------------------------------------------------------------
+ (
+ echo.#
+ echo.# /local64/etc/profile.local
+ echo.#
+ echo.
+ echo.MSYSTEM=MINGW64
+ echo.
+ echo.alias dir='ls -la --color=auto'
+ echo.alias ls='ls --color=auto'
+ echo.export CC=gcc
+ echo.export python=/usr/bin/python
+ echo.
+ echo.MSYS2_PATH="/usr/local/bin:/usr/bin"
+ echo.MANPATH="/usr/share/man:/mingw64/share/man:/local64/man:/local64/share/man"
+ echo.INFOPATH="/usr/local/info:/usr/share/info:/usr/info:/mingw64/share/info"
+ echo.MINGW_PREFIX="/mingw64"
+ echo.MINGW_CHOST="x86_64-w64-mingw32"
+ echo.export MSYSTEM MINGW_PREFIX MINGW_CHOST
+ echo.
+ echo.DXSDK_DIR="/mingw64/x86_64-w64-mingw32"
+ echo.ACLOCAL_PATH="/mingw64/share/aclocal:/usr/share/aclocal"
+ echo.PKG_CONFIG_LOCAL_PATH="/local64/lib/pkgconfig"
+ echo.PKG_CONFIG_PATH="/local64/lib/pkgconfig:/mingw64/lib/pkgconfig"
+ echo.CPPFLAGS="-I/local64/include -D_FORTIFY_SOURCE=2"
+ echo.CFLAGS="-I/local64/include -mms-bitfields -mthreads -mtune=generic -pipe"
+ echo.CXXFLAGS="-I/local64/include -mms-bitfields -mthreads -mtune=generic -pipe"
+ echo.LDFLAGS="-L/local64/lib -pipe"
+ echo.export DXSDK_DIR ACLOCAL_PATH PKG_CONFIG_PATH PKG_CONFIG_LOCAL_PATH CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MSYSTEM
+ echo.
+ echo.PYTHONHOME=/usr
+ echo.PYTHONPATH="/usr/lib/python2.7:/usr/lib/python2.7/Tools/Scripts"
+ echo.
+ echo.PATH=".:/local64/bin:/mingw64/bin:${MSYS2_PATH}:${INFOPATH}:${PYTHONHOME}:${PYTHONPATH}:${PATH}"
+ echo.PS1='\[\033[32m\]\u@\h \[\e[33m\]\w\[\e[0m\]\n\$ '
+ echo.export PATH PS1
+ echo.
+ echo.# package build directory
+ echo.LOCALBUILDDIR=/build
+ echo.# package installation prefix
+ echo.LOCALDESTDIR=/local64
+ echo.export LOCALBUILDDIR LOCALDESTDIR
+ )>>%instdir%\locals\x64\etc\profile.local
+ )
+
+:loadGasPreproc
+set gaspreprocfile=gas-preprocessor.tar.gz
+if exist %downloaddir%\%gaspreprocfile% goto extractGasPreproc
+ echo -------------------------------------------------------------------------------
+ echo.- Downloading gas-preprocessor.pl
+ echo -------------------------------------------------------------------------------
+ %instdir%\bin\wget --tries=20 --retry-connrefused --waitretry=2 --no-check-certificate -c -O %downloaddir%\%gaspreprocfile% %gaspreprocurl%
+
+:extractGasPreproc
+if exist %instdir%\%msys2%\usr\bin\gas-preprocessor.pl goto end
+ echo -------------------------------------------------------------------------------
+ echo.- Installing gas-preprocessor.pl
+ echo -------------------------------------------------------------------------------
+ %unpack_exe% x %downloaddir%\%gaspreprocfile% -so 2>NUL | %unpack_exe% e -si -ttar -o%instdir%\%msys2%\usr\bin *.pl -r >NUL 2>NUL
+
+:end
+cd %instdir%
+IF ERRORLEVEL == 1 (
+ ECHO Something goes wrong...
+ exit /B 1
+ )
+
+echo.-------------------------------------------------------------------------------
+echo.install msys2 system done
+echo.-------------------------------------------------------------------------------
+
+@echo on
diff --git a/tools/buildsteps/windows/ffmpeg_options.txt b/tools/buildsteps/windows/ffmpeg_options.txt
new file mode 100644
index 0000000..fbaf417
--- /dev/null
+++ b/tools/buildsteps/windows/ffmpeg_options.txt
@@ -0,0 +1,19 @@
+--disable-avdevice
+--disable-crystalhd
+--disable-cuda
+--disable-cuvid
+--disable-devices
+--disable-dxva2
+--disable-gnutls
+--disable-nvenc
+--disable-openssl
+--disable-programs
+--disable-shared
+--enable-encoder=ac3,aac,wmav2,png,mjpeg
+--enable-muxer=spdif,adts,asf,ipod
+--enable-postproc
+--enable-protocol=http
+--enable-runtime-cpudetect
+--enable-static
+--enable-zlib
+--enable-libdav1d
diff --git a/tools/buildsteps/windows/getbranch.bat b/tools/buildsteps/windows/getbranch.bat
new file mode 100644
index 0000000..a078c05
--- /dev/null
+++ b/tools/buildsteps/windows/getbranch.bat
@@ -0,0 +1,56 @@
+@echo off
+rem this gets the current branch from either the branchname (if we attached) or
+rem by using scientific branch fetching algorithms [tm] git is in detached HEAD state
+rem result will be in env var %BRANCH%
+SET BRANCH=
+SET DETACHED=1
+:: detect detached head
+git symbolic-ref HEAD >nul 2>&1
+IF %ERRORLEVEL%==0 (
+ SET DETACHED=0
+)
+rem find the branchname - if current branch is a pr we have to take this into account aswell
+rem (would be refs/heads/pr/number/head then)
+rem normal branch would be refs/heads/branchname
+IF %DETACHED%==0 (
+ FOR /f %%a IN ('git symbolic-ref HEAD') DO SET BRANCH=%%a
+ SETLOCAL EnableDelayedExpansion
+ SET BRANCH=!BRANCH:*/=!
+ SETLOCAL DisableDelayedExpansion
+ GOTO branchfound
+)
+
+:: when building with jenkins there's no branch. First git command gets the branches
+:: and then prefers a non pr branch if one exists
+:: (this mimics what the linux side does via sed and head -n1
+:: but is empty in a normal build environment. Second git command gets the branch there.
+SET command=git branch -r --points-at HEAD
+%command% >nul 2>&1
+IF NOT %ERRORLEVEL%==0 (
+ SET command=git branch -r --contains HEAD
+)
+
+%command% | findstr "%GITHUB_REPO%\/" | findstr /V "%GITHUB_REPO%\/pr\/" >nul
+IF %ERRORLEVEL%==0 (
+ FOR /f %%a IN ('%%command%% ^| findstr "%GITHUB_REPO%\/" ^| findstr /V "%GITHUB_REPO%\/pr\/"') DO (
+ SET BRANCH=%%a
+ GOTO branchfound
+ )
+) ELSE (
+ FOR /f %%a IN ('%%command%% ^| findstr "%GITHUB_REPO%\/"') DO (
+ SET BRANCH=%%a
+ GOTO branchfound
+ )
+)
+
+:branchfound
+SETLOCAL EnableDelayedExpansion
+IF NOT "!BRANCH!"=="" (
+ :: BRANCH is now (head|GITHUB_REPO)/(branchname|pr/number/(head|merge))
+ SET BRANCH=!BRANCH:/pr/=/PR!
+ SET BRANCH=!BRANCH:*/=!
+ SET BRANCH=!BRANCH:/=-!
+)
+SETLOCAL DisableDelayedExpansion
+
+ECHO.%BRANCH%
diff --git a/tools/buildsteps/windows/make-addons.bat b/tools/buildsteps/windows/make-addons.bat
new file mode 100644
index 0000000..b8e0ac5
--- /dev/null
+++ b/tools/buildsteps/windows/make-addons.bat
@@ -0,0 +1,169 @@
+@ECHO OFF
+
+SET EXITCODE=0
+
+SET install=false
+SET clean=false
+SET package=false
+SET addon=
+SET store=
+
+SETLOCAL EnableDelayedExpansion
+FOR %%b IN (%*) DO (
+ IF %%~b == install (
+ SET install=true
+ ) ELSE ( IF %%~b == clean (
+ SET clean=true
+ ) ELSE ( IF %%~b == package (
+ SET package=true
+ ) ELSE ( IF %%~b == win10 (
+ SET store=store
+ ) ELSE (
+ SET addon=!addon! %%~b
+ ))))
+)
+SETLOCAL DisableDelayedExpansion
+
+PUSHD %~dp0\..\..\..
+SET WORKDIR=%CD%
+POPD
+
+rem setup some paths that we need later
+SET CUR_PATH=%CD%
+SET BASE_PATH=%WORKDIR%\cmake
+SET SCRIPTS_PATH=%BASE_PATH%\scripts\windows%store%
+SET ADDONS_PATH=%BASE_PATH%\addons
+SET ADDON_DEPENDS_PATH=%ADDONS_PATH%\output
+SET ADDONS_BUILD_PATH=%ADDONS_PATH%\build
+
+SET ADDONS_SUCCESS_FILE=%ADDONS_PATH%\.success
+SET ADDONS_FAILURE_FILE=%ADDONS_PATH%\.failure
+
+SET ERRORFILE=%ADDONS_PATH%\make-addons.error
+
+rem remove the success and failure files from a previous build
+DEL /F %ADDONS_SUCCESS_FILE% > NUL 2>&1
+DEL /F %ADDONS_FAILURE_FILE% > NUL 2>&1
+
+IF %clean% == true (
+ rem remove the build directory if it exists
+ IF EXIST "%ADDONS_BUILD_PATH%" (
+ ECHO Cleaning build directory...
+ RMDIR "%ADDONS_BUILD_PATH%" /S /Q > NUL
+ )
+
+ rem remove the build directory if it exists
+ IF EXIST "%ADDON_DEPENDS_PATH%" (
+ ECHO Cleaning dependencies...
+ RMDIR "%ADDON_DEPENDS_PATH%" /S /Q > NUL
+ )
+
+ GOTO END
+)
+
+rem create the depends directory
+IF NOT EXIST "%ADDON_DEPENDS_PATH%" MKDIR "%ADDON_DEPENDS_PATH%"
+
+rem create the build directory
+IF NOT EXIST "%ADDONS_BUILD_PATH%" MKDIR "%ADDONS_BUILD_PATH%"
+
+rem go into the build directory
+CD "%ADDONS_BUILD_PATH%"
+
+rem determine the proper install path for the built addons
+IF %install% == true (
+ SET ADDONS_INSTALL_PATH=%WORKSPACE%\addons
+) ELSE (
+ SET ADDONS_INSTALL_PATH=%WORKDIR%\project\Win32BuildSetup\BUILD_WIN32\addons
+)
+
+ECHO --------------------------------------------------
+ECHO Building addons
+ECHO --------------------------------------------------
+
+IF "%addon%" NEQ "" (
+ SET CMAKE_EXTRA=%CMAKE_EXTRA% -DADDONS_TO_BUILD="%addon%"
+)
+
+IF "%ADDON_SRC_PREFIX%" NEQ "" (
+ SET CMAKE_EXTRA=%CMAKE_EXTRA% -DADDON_SRC_PREFIX=%ADDON_SRC_PREFIX%
+)
+
+IF "%ADDONS_DEFINITION_DIR" NEQ "" (
+ SET CMAKE_EXTRA=%CMAKE_EXTRA% -DADDONS_DEFINITION_DIR=%ADDONS_DEFINITION_DIR%
+)
+
+IF "%store%" NEQ "" (
+ SET CMAKE_EXTRA=%CMAKE_EXTRA% -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=%UCRTVersion%
+)
+
+rem execute cmake to generate makefiles processable by nmake
+cmake "%ADDONS_PATH%" -G "NMake Makefiles" ^
+ -DCMAKE_BUILD_TYPE=Release ^
+ -DCMAKE_USER_MAKE_RULES_OVERRIDE="%SCRIPTS_PATH%/CFlagOverrides.cmake" ^
+ -DCMAKE_USER_MAKE_RULES_OVERRIDE_CXX="%SCRIPTS_PATH%/CXXFlagOverrides.cmake" ^
+ -DCMAKE_INSTALL_PREFIX=%ADDONS_INSTALL_PATH% ^
+ -DCMAKE_SOURCE_DIR=%WORKDIR% ^
+ -DBUILD_DIR=%ADDONS_BUILD_PATH% ^
+ -DADDON_DEPENDS_PATH=%ADDON_DEPENDS_PATH% ^
+ -DPACKAGE_ZIP=ON ^
+ %CMAKE_EXTRA%
+
+IF ERRORLEVEL 1 (
+ ECHO cmake error level: %ERRORLEVEL% > %ERRORFILE%
+ GOTO ERROR
+)
+
+rem get the list of addons that can actually be built
+SET ADDONS_TO_MAKE=
+SETLOCAL EnableDelayedExpansion
+FOR /f "delims=" %%i IN ('cmake --build . --target supported_addons') DO (
+ SET line="%%i"
+ SET addons=!line:ALL_ADDONS_BUILDING=!
+ IF NOT "!addons!" == "!line!" (
+ SET ADDONS_TO_MAKE=!addons:~3,-1!
+ )
+)
+SETLOCAL DisableDelayedExpansion
+
+rem loop over all addons to build
+FOR %%a IN (%ADDONS_TO_MAKE%) DO (
+ ECHO Building %%a...
+ rem execute cmake to build the addons
+ cmake --build . --target %%a
+ IF ERRORLEVEL 1 (
+ ECHO nmake %%a error level: %ERRORLEVEL% > %ERRORFILE%
+ ECHO %%a >> %ADDONS_FAILURE_FILE%
+ ) ELSE (
+ if %package% == true (
+ nmake package-%%a
+ IF ERRORLEVEL 1 (
+ ECHO nmake package-%%a error level: %ERRORLEVEL% > %ERRORFILE%
+ ECHO %%a >> %ADDONS_FAILURE_FILE%
+ ) ELSE (
+ ECHO %%a >> %ADDONS_SUCCESS_FILE%
+ )
+ ) ELSE (
+ ECHO %%a >> %ADDONS_SUCCESS_FILE%
+ )
+ )
+)
+
+rem everything was fine
+GOTO END
+
+:ERROR
+rem something went wrong
+FOR %%a IN (%ADDONS_TO_BUILD%) DO (
+ ECHO %%a >> %ADDONS_FAILURE_FILE%
+)
+ECHO Failed to build addons
+ECHO See %ERRORFILE% for more details
+SET EXITCODE=1
+
+:END
+rem go back to the original directory
+cd %CUR_PATH%
+
+rem exit the script with the defined exitcode
+EXIT /B %EXITCODE%
diff --git a/tools/buildsteps/windows/make-mingwlibs.bat b/tools/buildsteps/windows/make-mingwlibs.bat
new file mode 100644
index 0000000..62c41f0
--- /dev/null
+++ b/tools/buildsteps/windows/make-mingwlibs.bat
@@ -0,0 +1,88 @@
+@ECHO OFF
+
+rem batch file to compile mingw libs via BuildSetup
+PUSHD %~dp0\..\..\..
+SET WORKDIR=%CD%
+POPD
+
+REM recreates clean ffmpeg build dir
+SET BUILD_DIR=%WORKDIR%\project\BuildDependencies\build
+IF EXIST %BUILD_DIR% rmdir %BUILD_DIR% /S /Q
+IF NOT EXIST %BUILD_DIR% mkdir %BUILD_DIR%
+
+SET PROMPTLEVEL=prompt
+SET BUILDMODE=clean
+SET opt=mintty
+SET build32=yes
+SET build64=no
+SET buildArm=no
+SET vcarch=x86
+SET msys2=msys64
+SET win10=no
+SET TARGETPLATFORM=win32
+
+FOR %%b in (%*) DO (
+ IF %%b==noprompt SET PROMPTLEVEL=noprompt
+ IF %%b==clean SET BUILDMODE=clean
+ IF %%b==noclean SET BUILDMODE=noclean
+ IF %%b==sh SET opt=sh
+ IF %%b==build64 (
+ SET build64=yes
+ SET build32=no
+ SET buildArm=no
+ SET vcarch=amd64
+ SET TARGETPLATFORM=x64
+ )
+ IF %%b==buildArm (
+ SET build64=no
+ SET build32=no
+ SET buildArm=yes
+ SET vcarch=arm
+ SET TARGETPLATFORM=arm
+ )
+ IF %%b==win10 (
+ SET win10=yes
+ )
+)
+:: Export full current PATH from environment into MSYS2
+set MSYS2_PATH_TYPE=inherit
+
+REM Prepend the msys and mingw paths onto %PATH%
+SET MSYS_INSTALL_PATH=%WORKDIR%\project\BuildDependencies\msys
+SET PATH=%MSYS_INSTALL_PATH%\mingw\bin;%MSYS_INSTALL_PATH%\bin;%PATH%
+SET ERRORFILE=%WORKDIR%\project\Win32BuildSetup\errormingw
+SET BS_DIR=%WORKDIR%\project\Win32BuildSetup
+
+IF EXIST %ERRORFILE% del %ERRORFILE% > NUL
+
+rem compiles a bunch of mingw libs and not more
+IF %opt%==sh (
+ IF EXIST %WORKDIR%\project\BuildDependencies\%msys2%\usr\bin\sh.exe (
+ ECHO starting sh shell
+ %WORKDIR%\project\BuildDependencies\%msys2%\usr\bin\sh.exe --login -i /xbmc/tools/buildsteps/windows/make-mingwlibs.sh --prompt=%PROMPTLEVEL% --mode=%BUILDMODE% --build32=%build32% --build64=%build64% --buildArm=%buildArm% --win10=%win10%
+ GOTO END
+ ) ELSE (
+ GOTO ENDWITHERROR
+ )
+)
+IF EXIST %WORKDIR%\project\BuildDependencies\%msys2%\usr\bin\mintty.exe (
+ ECHO starting mintty shell
+ %WORKDIR%\project\BuildDependencies\%msys2%\usr\bin\mintty.exe -d -i /msys2.ico /usr/bin/bash --login /xbmc/tools/buildsteps/windows/make-mingwlibs.sh --prompt=%PROMPTLEVEL% --mode=%BUILDMODE% --build32=%build32% --build64=%build64% --buildArm=%buildArm% --win10=%win10%
+ GOTO END
+)
+GOTO ENDWITHERROR
+
+:ENDWITHERROR
+ ECHO msys environment not found
+ ECHO bla>%ERRORFILE%
+ EXIT /B 1
+
+:END
+ ECHO exiting msys environment
+ IF EXIST %ERRORFILE% (
+ ECHO failed to build mingw libs
+ EXIT /B 1
+ )
+ EXIT /B 0
+
+ENDLOCAL
diff --git a/tools/buildsteps/windows/make-mingwlibs.sh b/tools/buildsteps/windows/make-mingwlibs.sh
new file mode 100644
index 0000000..e5a3594
--- /dev/null
+++ b/tools/buildsteps/windows/make-mingwlibs.sh
@@ -0,0 +1,162 @@
+[[ -f $(dirname $0)/buildhelpers.sh ]] &&
+ source $(dirname $0)/buildhelpers.sh
+
+Win32BuildSetup=/xbmc/project/Win32BuildSetup
+ERRORFILE=$Win32BuildSetup/errormingw
+TOUCH=/bin/touch
+RM=/bin/rm
+NOPROMPT=0
+MAKECLEAN=""
+MAKEFLAGS=""
+TRIPLET=""
+
+while true; do
+ case $1 in
+ --build32=* ) build32="${1#*=}"; shift ;;
+ --build64=* ) build64="${1#*=}"; shift ;;
+ --buildArm=* ) buildArm="${1#*=}"; shift ;;
+ --prompt=* ) PROMPTLEVEL="${1#*=}"; shift ;;
+ --mode=* ) BUILDMODE="${1#*=}"; shift ;;
+ --win10=* ) win10="${1#*=}"; shift ;;
+ -- ) shift; break ;;
+ -* ) shift ;;
+ * ) break ;;
+ esac
+done
+
+if [[ $build32 = "yes" ]]; then
+ TRIPLET=win32
+ ARCH=x86
+elif [[ $build64 = "yes" ]]; then
+ TRIPLET=x64
+ ARCH=x86_64
+elif [[ $buildArm = "yes" ]]; then
+ TRIPLET=arm
+ ARCH=arm
+else
+ echo "-------------------------------------------------------------------------------"
+ echo " none of build types (build32, build64 or buildArm) was specified "
+ echo "-------------------------------------------------------------------------------"
+ # wait for key press
+ if [ "$PROMPTLEVEL" != "noprompt" ]; then
+ echo press a key to close the window
+ read
+ fi
+ exit
+fi
+
+if [[ $win10 = "no" ]]; then
+ export _WIN32_WINNT=0x0600
+ export NTDDI_VERSION=0x06000000
+elif [[ $win10 = "yes" ]]; then
+ TRIPLET=win10-$TRIPLET
+fi
+
+export TRIPLET ARCH
+
+throwerror() {
+ $TOUCH $ERRORFILE
+ echo failed to compile $1
+ if [ $NOPROMPT == 0 ]; then
+ read
+ fi
+}
+
+checkfiles() {
+ for i in $@; do
+ if [ ! -f "$PREFIX/$i" ]; then
+ throwerror "$PREFIX/$i"
+ exit 1
+ fi
+ done
+}
+
+buildProcess() {
+export PREFIX=/xbmc/project/BuildDependencies/mingwlibs/$TRIPLET
+if [ "$(pathChanged $PREFIX /xbmc/tools/buildsteps/windows /xbmc/tools/depends/target/ffmpeg/FFMPEG-VERSION)" == "0" ]; then
+ return
+fi
+
+if [ -d "$PREFIX" ]; then
+ rm -rdf $PREFIX/*
+fi
+
+cd /xbmc/tools/buildsteps/windows
+
+# compile our mingw dlls
+echo "-------------------------------------------------------------------------------"
+echo " compiling mingw libs $TRIPLET"
+echo
+echo " NOPROMPT = $NOPROMPT"
+echo " MAKECLEAN = $MAKECLEAN"
+echo " WORKSPACE = $WORKSPACE"
+echo
+echo "-------------------------------------------------------------------------------"
+
+echo -ne "\033]0;building FFmpeg $TRIPLET\007"
+echo "-------------------------------------------------"
+echo " building FFmpeg $TRIPLET"
+echo "-------------------------------------------------"
+./buildffmpeg.sh $MAKECLEAN
+checkfiles lib/avcodec.lib lib/avformat.lib lib/avutil.lib lib/postproc.lib lib/swscale.lib lib/avfilter.lib lib/swresample.lib
+echo "-------------------------------------------------"
+echo " building of FFmpeg $TRIPLET done..."
+echo "-------------------------------------------------"
+echo "-------------------------------------------------------------------------------"
+echo " compile mingw libs $TRIPLET done..."
+echo "-------------------------------------------------------------------------------"
+
+tagSuccessFulBuild $PREFIX /xbmc/tools/buildsteps/windows /xbmc/tools/depends/target/ffmpeg/FFMPEG-VERSION
+}
+
+run_builds() {
+ local profile_path=""
+ if [[ $build32 = "yes" ]]; then
+ profile_path=/local32/etc/profile.local
+ elif [[ $build64 = "yes" ]]; then
+ profile_path=/local64/etc/profile.local
+ elif [[ $buildArm = "yes" ]]; then
+ profile_path=/local32/etc/profile.local
+ fi
+
+ if [ ! -z $profile_path ]; then
+ if [[ ! -f "$profile_path" ]]; then
+ echo "-------------------------------------------------------------------------------"
+ echo " $TRIPLET build environment not configured, please run download-msys2.bat"
+ echo "-------------------------------------------------------------------------------"
+ else
+ source $profile_path
+ buildProcess
+ echo "-------------------------------------------------------------------------------"
+ echo " compile all libs $TRIPLET done..."
+ echo "-------------------------------------------------------------------------------"
+ fi
+ fi
+}
+
+# cleanup
+if [ -f $ERRORFILE ]; then
+ $RM $ERRORFILE
+fi
+
+# check for noprompt
+if [ "$PROMPTLEVEL" == "noprompt" ]; then
+ NOPROMPT=1
+fi
+
+if [ "$BUILDMODE" == "clean" ]; then
+ MAKECLEAN="clean"
+else
+ MAKECLEAN="noclean"
+fi
+
+run_builds
+
+echo -e "\033]0;compiling done...\007"
+echo
+
+# wait for key press
+if [ $NOPROMPT == 0 ]; then
+ echo press a key to close the window
+ read
+fi
diff --git a/tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch b/tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch
new file mode 100644
index 0000000..b8e5b2f
--- /dev/null
+++ b/tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch
@@ -0,0 +1,25 @@
+From 08ae41e824e04ab48eafde763c72d1ff3e878a41 Mon Sep 17 00:00:00 2001
+From: Lukas Rusak <lorusak@gmail.com>
+Date: Sat, 10 Apr 2021 08:16:11 -0700
+Subject: [PATCH 1/4] ffmpeg: windows: configure: detect openssl
+
+---
+ configure | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/configure b/configure
+index d7a3f507e8..4b85e881b1 100755
+--- a/configure
++++ b/configure
+@@ -6530,6 +6530,8 @@ enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OP
+ check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto ||
+ check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 ||
+ check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 ||
++ check_lib openssl openssl/ssl.h OPENSSL_init_ssl -llibssl -llibcrypto -lws2_32 -lgdi32 -ladvapi32 -luser32 ||
++ check_lib openssl openssl/ssl.h SSL_library_init -llibeay32 -lssleay32 ||
+ die "ERROR: openssl not found"; }
+ enabled pocketsphinx && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init
+ enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/rk_mpi.h mpp_create &&
+--
+2.29.2
+
diff --git a/tools/buildsteps/windows/patches/0002-ffmpeg-windows-configure-fix-zlib-conflict.patch b/tools/buildsteps/windows/patches/0002-ffmpeg-windows-configure-fix-zlib-conflict.patch
new file mode 100644
index 0000000..064be1d
--- /dev/null
+++ b/tools/buildsteps/windows/patches/0002-ffmpeg-windows-configure-fix-zlib-conflict.patch
@@ -0,0 +1,26 @@
+From 1e57e7f49f1a74ee11d3c8dd5d407f35eecd5167 Mon Sep 17 00:00:00 2001
+From: Lukas Rusak <lorusak@gmail.com>
+Date: Sat, 10 Apr 2021 08:16:48 -0700
+Subject: [PATCH 2/4] ffmpeg: windows: configure: fix zlib conflict
+
+---
+ configure | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/configure b/configure
+index 4b85e881b1..da457705d1 100755
+--- a/configure
++++ b/configure
+@@ -7627,6 +7627,9 @@ print_config CONFIG_ "$config_files" $CONFIG_LIST \
+ $CONFIG_EXTRA \
+ $ALL_COMPONENTS \
+
++echo "#if defined(HAVE_UNISTD_H) && HAVE_UNISTD_H == 0" >> $TMPH
++echo "#undef HAVE_UNISTD_H" >> $TMPH
++echo "#endif" >> $TMPH
+ echo "#endif /* FFMPEG_CONFIG_H */" >> $TMPH
+ echo "endif # FFMPEG_CONFIG_MAK" >> ffbuild/config.mak
+
+--
+2.29.2
+
diff --git a/tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch b/tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch
new file mode 100644
index 0000000..bbb3e0a
--- /dev/null
+++ b/tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch
@@ -0,0 +1,34 @@
+From efb771d944e96bcbb24635bcae99a43dffab262e Mon Sep 17 00:00:00 2001
+From: Lukas Rusak <lorusak@gmail.com>
+Date: Sat, 10 Apr 2021 08:17:11 -0700
+Subject: [PATCH 3/4] ffmpeg: windows: configure: allow building static
+
+---
+ configure | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/configure b/configure
+index da457705d1..e3a8f45ff4 100755
+--- a/configure
++++ b/configure
+@@ -5440,6 +5440,8 @@ case $target_os in
+ enabled shared && ! enabled small && test_cmd $windres --version && enable gnu_windres
+ enabled x86_32 && check_ldflags -Wl,--large-address-aware
+ shlibdir_default="$bindir_default"
++ LIBPREF=""
++ LIBSUF=".lib"
+ SLIBPREF=""
+ SLIBSUF=".dll"
+ SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)'
+@@ -5489,6 +5491,8 @@ case $target_os in
+ fi
+ enabled x86_32 && check_ldflags -LARGEADDRESSAWARE
+ shlibdir_default="$bindir_default"
++ LIBPREF=""
++ LIBSUF=".lib"
+ SLIBPREF=""
+ SLIBSUF=".dll"
+ SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)'
+--
+2.29.2
+
diff --git a/tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch b/tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch
new file mode 100644
index 0000000..617c87a
--- /dev/null
+++ b/tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch
@@ -0,0 +1,25 @@
+From d475edac8c6890fbaea5ca20d552c60aead0f04a Mon Sep 17 00:00:00 2001
+From: Lukas Rusak <lorusak@gmail.com>
+Date: Sat, 10 Apr 2021 08:19:27 -0700
+Subject: [PATCH 4/4] ffmpeg: windows: configure: detect libdav1d
+
+---
+ configure | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure b/configure
+index e3a8f45ff4..983d7e1078 100755
+--- a/configure
++++ b/configure
+@@ -6358,7 +6358,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 &&
+ die "ERROR: libcelt must be installed and version must be >= 0.11.0."; }
+ enabled libcaca && require_pkg_config libcaca caca caca.h caca_create_canvas
+ enabled libcodec2 && require libcodec2 codec2/codec2.h codec2_create -lcodec2
+-enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.5.0" "dav1d/dav1d.h" dav1d_version
++enabled libdav1d && require libdav1d dav1d/dav1d.h dav1d_version -llibdav1d
+ enabled libdavs2 && require_pkg_config libdavs2 "davs2 >= 1.6.0" davs2.h davs2_decoder_open
+ enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new
+ enabled libdrm && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion
+--
+2.29.2
+
diff --git a/tools/buildsteps/windows/patches/readme.txt b/tools/buildsteps/windows/patches/readme.txt
new file mode 100644
index 0000000..80632dc
--- /dev/null
+++ b/tools/buildsteps/windows/patches/readme.txt
@@ -0,0 +1,6 @@
+The folder contains patches for libs which will be built by mingw
+in the following format:
+
+ dddd-libname-*.patch
+
+The build system will apply these patches automatically \ No newline at end of file
diff --git a/tools/buildsteps/windows/prepare-env.bat b/tools/buildsteps/windows/prepare-env.bat
new file mode 100644
index 0000000..bcbaded
--- /dev/null
+++ b/tools/buildsteps/windows/prepare-env.bat
@@ -0,0 +1,27 @@
+@ECHO OFF
+
+PUSHD %~dp0\..\..\..
+SET WORKSPACE=%CD%
+POPD
+
+ECHO Workspace is %WORKSPACE%
+
+cd %WORKSPACE%
+rem clean the BUILD_WIN32 at first to avoid problems with possible git files in there
+IF EXIST %WORKSPACE%\project\Win32BuildSetup\BUILD_WIN32 rmdir %WORKSPACE%\project\Win32BuildSetup\BUILD_WIN32 /S /Q
+
+rem also clean 'build' dir used to build ffmpeg as git clean has trouble to remove some times
+IF EXIST %WORKSPACE%\project\BuildDependencies\build rmdir %WORKSPACE%\project\BuildDependencies\build /S /Q
+
+rem daemonized executables block mingw from being cleaned with git
+TASKKILL /IM "dirmngr.exe" /F >nul 2>&1
+TASKKILL /IM "gpg-agent.exe" /F >nul 2>&1
+
+rem we assume git in path as this is a requirement
+rem git clean the untracked files and directories
+rem but keep the downloaded dependencies
+rem also keeps MSYS2 installation
+SET GIT_CLEAN_CMD=git clean -xffd -e "project/BuildDependencies/downloads" -e "project/BuildDependencies/downloads2" -e "project/BuildDependencies/mingwlibs" -e "project/BuildDependencies/msys64" -e "project/BuildDependencies/tools" -e "cmake/addons/build/download/msys2-base-*.tar.xz"
+
+ECHO running %GIT_CLEAN_CMD%
+%GIT_CLEAN_CMD%
diff --git a/tools/buildsteps/windows/run-tests.bat b/tools/buildsteps/windows/run-tests.bat
new file mode 100644
index 0000000..2bde835
--- /dev/null
+++ b/tools/buildsteps/windows/run-tests.bat
@@ -0,0 +1,70 @@
+@ECHO OFF
+SETLOCAL ENABLEDELAYEDEXPANSION
+
+REM setup all paths
+PUSHD %~dp0\..\..\..
+SET WORKSPACE=%CD%
+POPD
+cd %WORKSPACE%\kodi-build.%TARGET_PLATFORM%
+
+REM read the version values from version.txt
+FOR /f "tokens=1,2" %%i IN (%WORKSPACE%\version.txt) DO IF "%%i" == "APP_NAME" SET APP_NAME=%%j
+
+CLS
+COLOR 1B
+TITLE %APP_NAME% testsuite Build-/Runscript
+
+rem -------------------------------------------------------------
+rem CONFIG START
+SET exitcode=0
+SET useshell=sh
+SET buildconfig=Release
+SET PreferredToolArchitecture=x64
+
+
+ rem CONFIG END
+ rem -------------------------------------------------------------
+
+echo Building %buildconfig%
+IF EXIST buildlog.html del buildlog.html /q
+
+ECHO Compiling testsuite...
+cmake.exe --build . --config "%buildconfig%" --target %APP_NAME%-test
+
+IF %errorlevel%==1 (
+ set DIETEXT="%APP_NAME%-test.exe failed to build! See %CD%\..\vs2010express\XBMC\%buildconfig%\objs\XBMC.log"
+ type "%CD%\..\vs2010express\XBMC\%buildconfig%\objs\XBMC.log"
+ goto DIE
+)
+ECHO Done building!
+ECHO ------------------------------------------------------------
+
+:RUNTESTSUITE
+ECHO Running testsuite...
+ "%buildconfig%\%APP_NAME%-test.exe" --gtest_output=xml:%WORKSPACE%\gtestresults.xml
+
+ rem Adapt gtest xml output to be conform with junit xml
+ rem this basically looks for lines which have "notrun" in the <testcase /> tag
+ rem and adds a <skipped/> subtag into it. For example:
+ rem <testcase name="IsStarted" status="notrun" time="0" classname="TestWebServer"/>
+ rem becomes
+ rem <testcase name="IsStarted" status="notrun" time="0" classname="TestWebServer"><skipped/></testcase>
+ @PowerShell "(GC %WORKSPACE%\gtestresults.xml)|%%{$_ -Replace '(<testcase.+)("notrun")(.+)(/>)','$1$2$3><skipped/></testcase>'}|SC %WORKSPACE%\gtestresults-skipped.xml"
+ del %WORKSPACE%\gtestresults.xml
+ move %WORKSPACE%\gtestresults-skipped.xml %WORKSPACE%\gtestresults.xml
+ECHO Done running testsuite!
+ECHO ------------------------------------------------------------
+GOTO END
+
+:DIE
+ ECHO ------------------------------------------------------------
+ ECHO !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-
+ ECHO ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR
+ ECHO !-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-
+ set DIETEXT=ERROR: %DIETEXT%
+ echo %DIETEXT%
+ SET exitcode=1
+ ECHO ------------------------------------------------------------
+
+:END
+ EXIT /B %exitcode%
diff --git a/tools/buildsteps/windows/vswhere.bat b/tools/buildsteps/windows/vswhere.bat
new file mode 100644
index 0000000..b8c60b9
--- /dev/null
+++ b/tools/buildsteps/windows/vswhere.bat
@@ -0,0 +1,86 @@
+@ECHO OFF
+
+IF "%1"=="" (
+ ECHO ERROR! vswhere.bat: architecture not specified
+ EXIT /B 1
+)
+
+REM running vcvars more than once can cause problems; exit early if using the same configuration, error if different
+IF "%VSWHERE_SET%"=="%*" (
+ ECHO vswhere.bat: VC vars already configured for %VSWHERE_SET%
+ GOTO :EOF
+)
+IF "%VSWHERE_SET%" NEQ "" (
+ ECHO ERROR! vswhere.bat: VC vars are configured for %VSWHERE_SET%
+ EXIT /B 1
+)
+
+REM Trick to make the path absolute
+PUSHD %~dp0\..\..\..\project\BuildDependencies
+SET builddeps=%CD%
+POPD
+
+SET arch=%1
+SET vcarch=amd64
+SET vcstore=%2
+SET vcvars=no
+SET sdkver=
+
+SET vsver=
+SET toolsdir=%arch%
+
+IF "%arch%" NEQ "x64" (
+ SET vcarch=%vcarch%_%arch%
+)
+
+IF "%arch%"=="x86" (
+ SET toolsdir=win32
+)
+
+IF "%vcstore%"=="store" (
+ SET sdkver=10.0.18362.0
+ SET toolsdir="win10-%toolsdir%"
+)
+
+SET vswhere="%builddeps%\%toolsdir%\tools\vswhere\vswhere.exe"
+
+FOR /f "usebackq tokens=1* delims=" %%i in (`%vswhere% -latest -property installationPath`) do (
+ IF EXIST "%%i\VC\Auxiliary\Build\vcvarsall.bat" (
+ SET vcvars="%%i\VC\Auxiliary\Build\vcvarsall.bat"
+ SET vsver=15 2017
+ ECHO %%i | findstr "2019" >NUL 2>NUL
+ IF NOT ERRORLEVEL 1 SET vsver=16 2019
+ ECHO %%i | findstr "2022" >NUL 2>NUL
+ IF NOT ERRORLEVEL 1 SET vsver=17 2022
+ )
+)
+
+IF %vcvars%==no (
+ FOR /f "usebackq tokens=1* delims=" %%i in (`%vswhere% -legacy -property installationPath`) do (
+ ECHO %%i | findstr "14" >NUL 2>NUL
+ IF NOT ERRORLEVEL 1 (
+ IF EXIST "%%i\VC\vcvarsall.bat" (
+ SET vcvars="%%i\VC\vcvarsall.bat"
+ SET vsver=14 2015
+ )
+ )
+ )
+)
+
+IF %vcvars%==no (
+ ECHO "ERROR! Could not find vcvarsall.bat"
+ EXIT /B 1
+)
+
+REM vcvars changes the cwd so we need to store it and restore it
+PUSHD %~dp0
+CALL %vcvars% %vcarch% %vcstore% %sdkver%
+POPD
+
+IF ERRORLEVEL 1 (
+ ECHO "ERROR! something went wrong when calling"
+ ECHO %vcvars% %vcarch% %vcstore% %sdkver%
+ EXIT /B 1
+)
+
+SET VSWHERE_SET=%*
diff --git a/tools/buildsteps/windows/win32-uwp/BuildSetup.bat b/tools/buildsteps/windows/win32-uwp/BuildSetup.bat
new file mode 100644
index 0000000..5ddf234
--- /dev/null
+++ b/tools/buildsteps/windows/win32-uwp/BuildSetup.bat
@@ -0,0 +1,18 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x86 store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+
+SET cmakeGenerator=Visual Studio %vsver%
+SET cmakeArch=Win32
+SET TARGET_ARCHITECTURE=x86
+SET TARGET_PLATFORM=win32-uwp
+SET cmakeProps=-DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=%UCRTVersion%
+
+CALL BuildSetup.bat %*
+POPD
diff --git a/tools/buildsteps/windows/win32-uwp/bootstrap-addons.bat b/tools/buildsteps/windows/win32-uwp/bootstrap-addons.bat
new file mode 100644
index 0000000..0f67ddb
--- /dev/null
+++ b/tools/buildsteps/windows/win32-uwp/bootstrap-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x86 store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL bootstrap-addons %*
+POPD
diff --git a/tools/buildsteps/windows/win32-uwp/download-dependencies.bat b/tools/buildsteps/windows/win32-uwp/download-dependencies.bat
new file mode 100644
index 0000000..24ed2f1
--- /dev/null
+++ b/tools/buildsteps/windows/win32-uwp/download-dependencies.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-dependencies.bat win10-win32
+POPD
diff --git a/tools/buildsteps/windows/win32-uwp/download-msys2.bat b/tools/buildsteps/windows/win32-uwp/download-msys2.bat
new file mode 100644
index 0000000..8c041ba
--- /dev/null
+++ b/tools/buildsteps/windows/win32-uwp/download-msys2.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-msys2.bat %*
+POPD
diff --git a/tools/buildsteps/windows/win32-uwp/make-addons.bat b/tools/buildsteps/windows/win32-uwp/make-addons.bat
new file mode 100644
index 0000000..0893cee
--- /dev/null
+++ b/tools/buildsteps/windows/win32-uwp/make-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x86 store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-addons.bat win10 %*
+POPD
diff --git a/tools/buildsteps/windows/win32-uwp/make-mingwlibs.bat b/tools/buildsteps/windows/win32-uwp/make-mingwlibs.bat
new file mode 100644
index 0000000..f47434e
--- /dev/null
+++ b/tools/buildsteps/windows/win32-uwp/make-mingwlibs.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x86 store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-mingwlibs.bat win10 %*
+POPD
diff --git a/tools/buildsteps/windows/win32-uwp/prepare-env.bat b/tools/buildsteps/windows/win32-uwp/prepare-env.bat
new file mode 100644
index 0000000..354a5cf
--- /dev/null
+++ b/tools/buildsteps/windows/win32-uwp/prepare-env.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL prepare-env.bat
+POPD
diff --git a/tools/buildsteps/windows/win32/BuildSetup.bat b/tools/buildsteps/windows/win32/BuildSetup.bat
new file mode 100644
index 0000000..0c10f43
--- /dev/null
+++ b/tools/buildsteps/windows/win32/BuildSetup.bat
@@ -0,0 +1,18 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+
+CALL vswhere.bat x86
+IF ERRORLEVEL 1 (
+ ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+
+SET cmakeGenerator=Visual Studio %vsver%
+SET cmakeArch=Win32
+SET TARGET_ARCHITECTURE=x86
+SET TARGET_PLATFORM=%TARGET_ARCHITECTURE%
+
+CALL BuildSetup.bat %*
+POPD
diff --git a/tools/buildsteps/windows/win32/bootstrap-addons.bat b/tools/buildsteps/windows/win32/bootstrap-addons.bat
new file mode 100644
index 0000000..5918ad9
--- /dev/null
+++ b/tools/buildsteps/windows/win32/bootstrap-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x86
+IF ERRORLEVEL 1 (
+ ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL bootstrap-addons %*
+POPD
diff --git a/tools/buildsteps/windows/win32/download-dependencies.bat b/tools/buildsteps/windows/win32/download-dependencies.bat
new file mode 100644
index 0000000..ecb5897
--- /dev/null
+++ b/tools/buildsteps/windows/win32/download-dependencies.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-dependencies.bat win32
+POPD
diff --git a/tools/buildsteps/windows/win32/download-msys2.bat b/tools/buildsteps/windows/win32/download-msys2.bat
new file mode 100644
index 0000000..8c041ba
--- /dev/null
+++ b/tools/buildsteps/windows/win32/download-msys2.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-msys2.bat %*
+POPD
diff --git a/tools/buildsteps/windows/win32/make-addons.bat b/tools/buildsteps/windows/win32/make-addons.bat
new file mode 100644
index 0000000..7efc4ca
--- /dev/null
+++ b/tools/buildsteps/windows/win32/make-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x86
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-addons.bat %*
+POPD
diff --git a/tools/buildsteps/windows/win32/make-mingwlibs.bat b/tools/buildsteps/windows/win32/make-mingwlibs.bat
new file mode 100644
index 0000000..889b27e
--- /dev/null
+++ b/tools/buildsteps/windows/win32/make-mingwlibs.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x86
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-mingwlibs.bat %*
+POPD
diff --git a/tools/buildsteps/windows/win32/prepare-env.bat b/tools/buildsteps/windows/win32/prepare-env.bat
new file mode 100644
index 0000000..354a5cf
--- /dev/null
+++ b/tools/buildsteps/windows/win32/prepare-env.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL prepare-env.bat
+POPD
diff --git a/tools/buildsteps/windows/win32/run-tests.bat b/tools/buildsteps/windows/win32/run-tests.bat
new file mode 100644
index 0000000..1c07563
--- /dev/null
+++ b/tools/buildsteps/windows/win32/run-tests.bat
@@ -0,0 +1,13 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x86
+IF ERRORLEVEL 1 (
+ ECHO ERROR! run-tests.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+SET TARGET_PLATFORM=x86
+
+CALL run-tests.bat
+POPD
diff --git a/tools/buildsteps/windows/x64-uwp/BuildSetup.bat b/tools/buildsteps/windows/x64-uwp/BuildSetup.bat
new file mode 100644
index 0000000..8144248
--- /dev/null
+++ b/tools/buildsteps/windows/x64-uwp/BuildSetup.bat
@@ -0,0 +1,18 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x64 store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+
+SET cmakeGenerator=Visual Studio %vsver%
+SET cmakeArch=x64
+SET TARGET_ARCHITECTURE=x64
+SET TARGET_PLATFORM=%TARGET_ARCHITECTURE%-uwp
+SET cmakeProps=-DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=%UCRTVersion%
+
+CALL BuildSetup.bat %*
+POPD
diff --git a/tools/buildsteps/windows/x64-uwp/bootstrap-addons.bat b/tools/buildsteps/windows/x64-uwp/bootstrap-addons.bat
new file mode 100644
index 0000000..83eed23
--- /dev/null
+++ b/tools/buildsteps/windows/x64-uwp/bootstrap-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x64 store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL bootstrap-addons %*
+POPD
diff --git a/tools/buildsteps/windows/x64-uwp/download-dependencies.bat b/tools/buildsteps/windows/x64-uwp/download-dependencies.bat
new file mode 100644
index 0000000..4af0164
--- /dev/null
+++ b/tools/buildsteps/windows/x64-uwp/download-dependencies.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-dependencies.bat win10-x64
+POPD
diff --git a/tools/buildsteps/windows/x64-uwp/download-msys2.bat b/tools/buildsteps/windows/x64-uwp/download-msys2.bat
new file mode 100644
index 0000000..8c041ba
--- /dev/null
+++ b/tools/buildsteps/windows/x64-uwp/download-msys2.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-msys2.bat %*
+POPD
diff --git a/tools/buildsteps/windows/x64-uwp/make-addons.bat b/tools/buildsteps/windows/x64-uwp/make-addons.bat
new file mode 100644
index 0000000..82bd1af
--- /dev/null
+++ b/tools/buildsteps/windows/x64-uwp/make-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x64 store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-addons.bat win10 %*
+POPD
diff --git a/tools/buildsteps/windows/x64-uwp/make-mingwlibs.bat b/tools/buildsteps/windows/x64-uwp/make-mingwlibs.bat
new file mode 100644
index 0000000..9e1ef90
--- /dev/null
+++ b/tools/buildsteps/windows/x64-uwp/make-mingwlibs.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x64 store
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-mingwlibs.bat build64 win10 %*
+POPD
diff --git a/tools/buildsteps/windows/x64-uwp/prepare-env.bat b/tools/buildsteps/windows/x64-uwp/prepare-env.bat
new file mode 100644
index 0000000..354a5cf
--- /dev/null
+++ b/tools/buildsteps/windows/x64-uwp/prepare-env.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL prepare-env.bat
+POPD
diff --git a/tools/buildsteps/windows/x64/BuildSetup.bat b/tools/buildsteps/windows/x64/BuildSetup.bat
new file mode 100644
index 0000000..09acf3f
--- /dev/null
+++ b/tools/buildsteps/windows/x64/BuildSetup.bat
@@ -0,0 +1,17 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x64
+IF ERRORLEVEL 1 (
+ ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+
+SET cmakeGenerator=Visual Studio %vsver%
+SET cmakeArch=x64
+SET TARGET_ARCHITECTURE=x64
+SET TARGET_PLATFORM=%TARGET_ARCHITECTURE%
+
+CALL BuildSetup.bat %*
+POPD
diff --git a/tools/buildsteps/windows/x64/bootstrap-addons.bat b/tools/buildsteps/windows/x64/bootstrap-addons.bat
new file mode 100644
index 0000000..45c5de6
--- /dev/null
+++ b/tools/buildsteps/windows/x64/bootstrap-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x64
+IF ERRORLEVEL 1 (
+ ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL bootstrap-addons %*
+POPD
diff --git a/tools/buildsteps/windows/x64/download-dependencies.bat b/tools/buildsteps/windows/x64/download-dependencies.bat
new file mode 100644
index 0000000..a51c3d4
--- /dev/null
+++ b/tools/buildsteps/windows/x64/download-dependencies.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-dependencies.bat x64
+POPD
diff --git a/tools/buildsteps/windows/x64/download-msys2.bat b/tools/buildsteps/windows/x64/download-msys2.bat
new file mode 100644
index 0000000..8c041ba
--- /dev/null
+++ b/tools/buildsteps/windows/x64/download-msys2.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL download-msys2.bat %*
+POPD
diff --git a/tools/buildsteps/windows/x64/make-addons.bat b/tools/buildsteps/windows/x64/make-addons.bat
new file mode 100644
index 0000000..ec9803f
--- /dev/null
+++ b/tools/buildsteps/windows/x64/make-addons.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x64
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-addons.bat %*
+POPD
diff --git a/tools/buildsteps/windows/x64/make-mingwlibs.bat b/tools/buildsteps/windows/x64/make-mingwlibs.bat
new file mode 100644
index 0000000..41471e5
--- /dev/null
+++ b/tools/buildsteps/windows/x64/make-mingwlibs.bat
@@ -0,0 +1,11 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x64
+IF ERRORLEVEL 1 (
+ ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+CALL make-mingwlibs.bat build64 %*
+POPD
diff --git a/tools/buildsteps/windows/x64/prepare-env.bat b/tools/buildsteps/windows/x64/prepare-env.bat
new file mode 100644
index 0000000..354a5cf
--- /dev/null
+++ b/tools/buildsteps/windows/x64/prepare-env.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL prepare-env.bat
+POPD
diff --git a/tools/buildsteps/windows/x64/run-tests.bat b/tools/buildsteps/windows/x64/run-tests.bat
new file mode 100644
index 0000000..a21ea89
--- /dev/null
+++ b/tools/buildsteps/windows/x64/run-tests.bat
@@ -0,0 +1,13 @@
+@ECHO OFF
+
+PUSHD %~dp0\..
+CALL vswhere.bat x64
+IF ERRORLEVEL 1 (
+ ECHO ERROR! run-tests.bat: Something went wrong when calling vswhere.bat
+ POPD
+ EXIT /B 1
+)
+SET TARGET_PLATFORM=x64
+
+CALL run-tests.bat
+POPD
diff --git a/tools/codegenerator/Generator.groovy b/tools/codegenerator/Generator.groovy
new file mode 100644
index 0000000..79cfe4f
--- /dev/null
+++ b/tools/codegenerator/Generator.groovy
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import groovy.text.SimpleTemplateEngine
+import groovy.xml.XmlParser
+import groovy.xml.XmlUtil
+
+import Helper
+
+def usage()
+{
+ println "java/groovy -cp [...] " + getClass().getName() + " [-verbose] moduleSpecFile templateFile outputFile [doxygenoutputdir]";
+ System.exit 1
+}
+
+def verbose = false;
+
+newargs = []
+
+println args
+
+args.each {
+ if (it == '-verbose' || it == '--verbose' || it == '-v')
+ verbose = true
+ else
+ newargs.add(it)
+}
+
+if (newargs.size() != 3 && newargs.size() != 4)
+ usage()
+
+// set the doxygen xml directory on the Helper assuming the output file will be placed
+// in the same place the doxygen subdirectory is placed
+if (newargs.size() > 3)
+ Helper.setDoxygenXmlDir(new File(newargs[3]))
+
+File moduleSpec = new File(newargs[0])
+assert moduleSpec.exists() && moduleSpec.isFile(), 'Cannot locate the spec file "' + moduleSpec.getCanonicalPath() + '."'
+
+File templateFile = new File(newargs[1])
+assert templateFile.exists() && templateFile.isFile(), 'Cannot locate the template file "' + templateFile.getCanonicalPath() + '."'
+
+spec = [ 'module' : Helper.transformSwigXml(new XmlParser().parse(moduleSpec)), 'templateFile' : templateFile ]
+
+if (verbose)
+ println XmlUtil.serialize(spec['module'])
+
+te = new SimpleTemplateEngine()
+println 'Processing "' + templateFile + '" using the module specification for module "' + moduleSpec + '"'
+if (verbose) te.setVerbose(true)
+template = te.createTemplate(templateFile).make(spec)
+String output = template.toString()
+if (verbose) println output
+
+println 'writing'
+new File(newargs[2]).write output
+
diff --git a/tools/codegenerator/Helper.groovy b/tools/codegenerator/Helper.groovy
new file mode 100644
index 0000000..4308ffd
--- /dev/null
+++ b/tools/codegenerator/Helper.groovy
@@ -0,0 +1,882 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import groovy.xml.XmlParser
+import groovy.xml.XmlUtil
+import org.apache.commons.lang.StringEscapeUtils
+
+import groovy.text.SimpleTemplateEngine
+import java.util.regex.Pattern
+
+/**
+ * This class contains a series of helper methods for parsing a xbmc addon spec xml file. It is intended to be
+ * used from a bindings template.
+ *
+ * @author jim
+ *
+ */
+public class Helper
+{
+ private static List classes
+ private static Map outTypemap = [:]
+ private static def defaultOutTypeConversion = null
+ private static Map inTypemap = [:]
+ private static def defaultInTypeConversion = null
+ private static def doxygenXmlDir = null
+ public static String newline = System.getProperty("line.separator");
+ public static File curTemplateFile = null;
+
+ public static void setTemplateFile(File templateFile) { curTemplateFile = templateFile }
+
+ /**
+ * In order to use any of the typemap helper features, the Helper class needs to be initialized with
+ * this information.
+ * @param pclasses is the list of all class nodes from the module
+ * @param poutTypemap is the typemap table for output return values to the scripting language
+ * @param defaultOutTypemap is the default typemap to use when the type conversion is unknown
+ * @param pinTypemap is the typemap table for input parameters from the scripting language
+ * @param defaultInTypemap is the default typemap for the input parameters from the scripting language
+ */
+ public static void setup(def template,List pclasses, Map poutTypemap, def defaultOutTypemap,
+ Map pinTypemap, def defaultInTypemap)
+ {
+ setTemplateFile(template.binding.templateFile)
+ classes = pclasses ? pclasses : []
+ if (poutTypemap) outTypemap.putAll(poutTypemap)
+ if (defaultOutTypemap) defaultOutTypeConversion = defaultOutTypemap
+ if (pinTypemap) inTypemap.putAll(pinTypemap)
+ if (defaultInTypemap) defaultInTypeConversion = defaultInTypemap
+ }
+
+ public static class Sequence
+ {
+ private long cur = 0;
+
+ public long increment() { return ++cur }
+ }
+
+ private static ThreadLocal<Sequence> curSequence = new ThreadLocal<Sequence>();
+
+ public static void setDoxygenXmlDir(File dir) { doxygenXmlDir = dir }
+
+ private static String retrieveDocStringFromDoxygen(Node methodOrClass)
+ {
+ if (doxygenXmlDir == null)
+ return null
+
+ Node doc = null
+ def ret = ''
+
+ // make the class name or namespace
+ String doxygenId = findFullClassName(methodOrClass,'_1_1',true)
+ boolean isInClass = doxygenId != null
+ if (!doxygenId)
+ doxygenId = findNamespace(methodOrClass,'_1_1',false,true)
+ doxygenId = (isInClass ? 'class' : 'namespace') + doxygenId
+
+ String doxygenFilename = doxygenId + '.xml'
+ File doxygenXmlFile = new File(doxygenXmlDir,doxygenFilename)
+ if (! doxygenXmlFile.exists())
+ {
+ System.out.println("WARNING: Cannot find doxygen file for ${methodOrClass.toString()} which should be \"${doxygenXmlFile}\"")
+ return null
+ }
+
+ Node docspec = (new XmlParser().parse(doxygenXmlFile))
+ if (methodOrClass.name() == 'class')
+ doc = docspec.compounddef[0].detaileddescription[0]
+ else // it's a method of some sort ... or it better be
+ {
+ Node memberdef = docspec.depthFirst().find {
+ return (it instanceof String) ? false :
+ ((it.name() == 'memberdef' && (it.@kind == 'function' || it.@kind == 'variable') && it.@id.startsWith(doxygenId)) &&
+ (it.name != null && it.name.text().trim() == methodOrClass.@sym_name))
+ }
+
+ doc = memberdef != null ? memberdef.detaileddescription[0] : null
+ }
+
+ if (doc != null)
+ {
+ def indent = ' '
+ def curIndent = ''
+ def prevIndent = ''
+
+ def handleDoc
+ handleDoc = {
+ if (it instanceof String)
+ ret += it
+ else // it's a Node
+ {
+ if (it.name() == 'detaileddescription')
+ it.children().each handleDoc
+ else if (it.name() == 'para')
+ {
+ it.children().each handleDoc
+ ret += (it.parent()?.name() == 'listitem') ? newline : (newline + newline)
+ }
+ else if (it.name() == 'ref' || it.name() == "ulink")
+ ret += (it.text() + ' ')
+ else if (it.name() == 'verbatim')
+ ret += it.text().denormalize()
+ else if (it.name() == 'itemizedlist')
+ {
+ ret += newline
+ prevIndent = curIndent
+ curIndent += indent
+ it.children().each handleDoc
+ curIndent = prevIndent
+ }
+ else if (it.name() == 'listitem')
+ {
+ ret += (curIndent + '- ')
+ it.children().each handleDoc
+ }
+ else if (it.name() == 'linebreak')
+ ret += newline
+ else if (it.name() == 'ndash')
+ ret += "--"
+ else if (it.name() == 'emphasis')
+ {
+ ret += '*'
+ it.children().each handleDoc
+ }
+ else
+ System.out.println("WARNING: Cannot parse the following as part of the doxygen processing:" + XmlUtil.serialize(it))
+ }
+ }
+
+ doc.children().each handleDoc
+ }
+
+ return ret.denormalize()
+ }
+
+ /**
+ * <p>This method uses the previously set outTypemap and defaultOutTypemap to produce the chunk of code
+ * that will be used to return the method invocation result to the scripting language. For example, in
+ * python, if the return type from the method is a long, then the OutConversion could look something like:</p>
+ * <code>
+ * result = PyInt_FromLong(thingReturnedFromMethod);
+ * </code>
+ * <p>This could have resulted from a mini-template stored as the way to handle 'long's in the outTypemap:</p>
+ * <code>
+ * ${result} = PyInt_FromLong(${api});
+ * </code>
+ * @param apiType - is the Swig typecode that describes the return type from the native method
+ * @param method - is the node from the module xml that contains the method description
+ * @return the code chunk as a string ready to be placed into the generated code.
+ */
+ public static String getOutConversion(String apiType, String apiName, Node method, Map overrideBindings = null, boolean recurse = true)
+ {
+ def convertTemplate = outTypemap[apiType]
+
+ // String apiLType = SwigTypeParser.convertTypeToLType(apiType)
+ // if (convertTemplate == null) convertTemplate = outTypemap[apiLType]
+
+ // is the returns a pointer to a known class
+ String className = null
+ if (convertTemplate == null && apiType.startsWith('p.'))
+ {
+ Node classNode = findClassNodeByName(parents(method)[0], SwigTypeParser.getRootType(apiType),method)
+ if (classNode)
+ {
+ className = findFullClassName(classNode)
+ convertTemplate = defaultOutTypeConversion
+ }
+ }
+
+ if (convertTemplate == null)
+ {
+ // Look for Pattern for keys that might fit
+ convertTemplate = outTypemap.find({ key, value -> (key instanceof Pattern && key.matcher(apiType).matches()) })?.value
+ }
+
+ if (!convertTemplate)
+ {
+ String knownApiType = isKnownApiType(apiType,method)
+ if (knownApiType)
+ {
+ convertTemplate = defaultOutTypeConversion
+ className = knownApiType
+ }
+ }
+
+ if (!convertTemplate)
+ {
+ // check the typedef resolution
+ String apiTypeResolved = SwigTypeParser.SwigType_resolve_all_typedefs(apiType)
+ if (!apiTypeResolved.equals(apiType))
+ return getOutConversion(apiTypeResolved, apiName, method, overrideBindings, recurse)
+
+ if (recurse)
+ return getOutConversion(SwigTypeParser.SwigType_ltype(apiType),apiName,method,overrideBindings,false)
+ else if (!isKnownApiType(apiType,method))
+ throw new RuntimeException("WARNING: Cannot convert the return value of swig type ${apiType} for the call ${Helper.findFullClassName(method) + '::' + Helper.callingName(method)}")
+ }
+
+ boolean seqSetHere = false
+ Sequence seq = curSequence.get()
+ if (seq == null)
+ {
+ seqSetHere = true
+ seq = new Sequence()
+ curSequence.set(seq)
+ }
+
+ Map bindings = ['result' : apiName, 'api' : 'apiResult', 'type' : "${apiType}",
+ 'method' : method, 'helper' : Helper.class,
+ 'swigTypeParser' : SwigTypeParser.class,
+ 'sequence' : seq ]
+ if (className) bindings['classname'] = className
+
+ if (overrideBindings) bindings.putAll(overrideBindings)
+
+ if (convertTemplate instanceof List) /// then we expect the template string/file to be the first entry
+ {
+ Map additionalBindings = convertTemplate.size() > 1 ? convertTemplate[1] : [:]
+ bindings.putAll(additionalBindings)
+ convertTemplate = convertTemplate[0]
+ }
+
+ if (File.class.isAssignableFrom(convertTemplate.getClass()))
+ {
+ File cur = (File)convertTemplate
+ if (!cur.exists()) // see if the file is relative to the template file
+ {
+ File parent = curTemplateFile.getParentFile()
+ // find the relative path to the convertTemplate
+ File cwd = new File('.').getCanonicalFile()
+ String relative = cwd.getAbsoluteFile().toURI().relativize(convertTemplate.getAbsoluteFile().toURI()).getPath()
+ convertTemplate = new File(parent,relative)
+
+ // This is a fallback case which is hit occasionally on OSX as a result
+ // of case mismatches between the two paths in the relativize call above.
+ if (!convertTemplate.exists())
+ convertTemplate = new File(parent,cur.toString())
+ }
+ }
+
+ if (seqSetHere) curSequence.set(null)
+ return new SimpleTemplateEngine().createTemplate(convertTemplate).make(bindings).toString()
+ }
+
+ /**
+ * <p>This method uses the previously set inTypemap and defaultInTypemap to produce the chunk of code
+ * that will be used to convert input parameters from the scripting language to the native method invocation
+ * parameters. For example, if the native call takes a 'String' then the InConversion could look something like:</p>
+ * <code>
+ * if (pythonStringArgument) PyXBMCGetUnicodeString(cArgument,pythonStringArgument,"cArgumentName");
+ * </code>
+ * <p>This could have resulted from a mini-template stored as the way to handle 'long's in the outTypemap:</p>
+ * <code>
+ * if (${slarg}) PyXBMCGetUnicodeString(${api},${slarg},"${api}");
+ * </code>
+ * @param apiType - is the Swig typecode that describes the parameter type from the native method
+ * @param apiName - is the name of the parameter from the method parameter list in the api
+ * @param slName - is the name of the variable that holds the parameter from the scripting language
+ * @param method - is the node from the module xml that contains the method description
+ * @return the code chunk as a string ready to be placed into the generated code.
+ */
+ public static String getInConversion(String apiType, String apiName, String slName, Node method, Map overrideBindings = null)
+ {
+ return getInConversion(apiType, apiName, apiName, slName, method, overrideBindings);
+ }
+
+ /**
+ * <p>This method uses the previously set inTypemap and defaultInTypemap to produce the chunk of code
+ * that will be used to convert input parameters from the scripting language to the native method invocation
+ * parameters. For example, if the native call takes a 'String' then the InConversion could look something like:</p>
+ * <code>
+ * if (pythonStringArgument) PyXBMCGetUnicodeString(cArgument,pythonStringArgument,"cArgumentName");
+ * </code>
+ * <p>This could have resulted from a mini-template stored as the way to handle 'long's in the outTypemap:</p>
+ * <code>
+ * if (${slarg}) PyXBMCGetUnicodeString(${api},${slarg},"${api}");
+ * </code>
+ * @param apiType - is the Swig typecode that describes the parameter type from the native method
+ * @param apiName - is the name of the variable that holds the api parameter
+ * @param paramName - is the name of the parameter from the method parameter list in the api
+ * @param slName - is the name of the variable that holds the parameter from the scripting language
+ * @param method - is the node from the module xml that contains the method description
+ * @return the code chunk as a string ready to be placed into the generated code.
+ */
+ public static String getInConversion(String apiType, String apiName, String paramName, String slName, Node method, Map overrideBindings = null)
+ {
+ def convertTemplate = inTypemap[apiType]
+
+ String apiLType = SwigTypeParser.convertTypeToLTypeForParam(apiType)
+
+ if (convertTemplate == null) convertTemplate = inTypemap[apiLType]
+
+ // is the returns a pointer to a known class
+ if (convertTemplate == null && apiType.startsWith('p.'))
+ {
+ // strip off rval qualifiers
+ String thisNamespace = Helper.findNamespace(method)
+ Node clazz = classes.find { Helper.findFullClassName(it) == apiLType.substring(2) ||
+ (it.@sym_name == apiLType.substring(2) && thisNamespace == Helper.findNamespace(it)) }
+ if (clazz != null) convertTemplate = defaultInTypeConversion
+ }
+
+ // Look for Pattern for keys that might fit
+ if (convertTemplate == null)
+ convertTemplate = inTypemap.find({ key, value -> (key instanceof Pattern && key.matcher(apiType).matches()) })?.value
+
+ // Try the LType
+ if (convertTemplate == null)
+ convertTemplate = inTypemap.find({ key, value -> (key instanceof Pattern && key.matcher(apiLType).matches()) })?.value
+
+ if (!convertTemplate)
+ {
+ // check the typedef resolution
+ String apiTypeResolved = SwigTypeParser.SwigType_resolve_all_typedefs(apiType)
+ if (!apiTypeResolved.equals(apiType))
+ return getInConversion(apiTypeResolved, apiName, paramName, slName, method, overrideBindings)
+
+ // it's ok if this is a known type
+ if (!isKnownApiType(apiType,method) && !isKnownApiType(apiLType,method))
+ System.out.println("WARNING: Unknown parameter type: ${apiType} (or ${apiLType}) for the call ${Helper.findFullClassName(method) + '::' + Helper.callingName(method)}")
+ convertTemplate = defaultInTypeConversion
+ }
+
+ if (convertTemplate)
+ {
+ boolean seqSetHere = false
+ Sequence seq = curSequence.get()
+ if (seq == null)
+ {
+ seqSetHere = true
+ seq = new Sequence()
+ curSequence.set(seq)
+ }
+
+ Map bindings = [
+ 'type': "${apiType}", 'ltype': "${apiLType}",
+ 'slarg' : "${slName}", 'api' : "${apiName}",
+ 'param' : "${paramName}",
+ 'method' : method, 'helper' : Helper.class,
+ 'swigTypeParser' : SwigTypeParser.class,
+ 'sequence' : seq
+ ]
+
+ if (overrideBindings) bindings.putAll(overrideBindings)
+
+ if (convertTemplate instanceof List) /// then we expect the template string/file to be the first entry
+ {
+ Map additionalBindings = convertTemplate.size() > 1 ? convertTemplate[1] : [:]
+ bindings.putAll(additionalBindings)
+ convertTemplate = convertTemplate[0]
+ }
+
+ if (File.class.isAssignableFrom(convertTemplate.getClass()))
+ {
+ File cur = (File)convertTemplate
+ if (!cur.exists()) // see if the file is relative to the template file
+ {
+ File parent = curTemplateFile.getParentFile()
+ // find the relative path to the convertTemplate
+ File cwd = new File('.').getCanonicalFile()
+ String relative = cwd.getAbsoluteFile().toURI().relativize(convertTemplate.getAbsoluteFile().toURI()).getPath()
+ convertTemplate = new File(parent,relative)
+
+ // This is a fallback case which is hit occasionally on OSX as a result
+ // of case mismatches between the two paths in the relativize call above.
+ if (!convertTemplate.exists())
+ convertTemplate = new File(parent,cur.toString())
+ }
+ }
+
+ if (seqSetHere) curSequence.set(null);
+ return new SimpleTemplateEngine().createTemplate(convertTemplate).make(bindings).toString()
+ }
+
+ return ''
+ }
+
+ static def ignoreAttributes = ['classes', 'symtab', 'sym_symtab',
+ 'sym_overname', 'options', 'sym_nextSibling', 'csym_nextSibling',
+ 'sym_previousSibling' ]
+
+ /**
+ * <p>Transform a Swig generated xml file into something more manageable. For the most part this method will:</p>
+ *
+ * <li>1) Make all pertinent 'attributelist' elements actually be attributes of the parent element while
+ * an attribute with the name 'name' will become that parent element name.</li>
+ * <li>2) Filter out unused attributes</li>
+ * <li>3) Filter out the automatically included 'swig'swg'</li>
+ * <li>4) Flatten out the remaining 'include' elements</li>
+ * <li>5) Removes extraneous default argument function/method Node</li>
+ * <li>6) Converts all type tables to a single entry under the main module node removing all 1-1 mappings.</li>
+ * <li>7) Removes all non-public non-constructor methods.</li>
+ * @param swigxml is the raw swig output xml document
+ * @return the transformed document
+ */
+ public static Node transformSwigXml(Node swigxml)
+ {
+ Node node = transform(swigxml,
+ {
+ // do not include the 'include' entry that references the default swig.swg file.
+ !(it.name() == 'include' &&
+ // needs to also contain an attribute list with an attribute 'name' that matches the swig.swg file
+ it.find {
+ it.name() == 'attributelist' && it.find {
+ it.name() == 'attribute' && it.@name == 'name' && it.@value =~ /swig\.swg$/
+ }
+ } ||
+ // also don't include any typescope entries
+ it.name() == 'typescopesitem' || it.name() == 'typetabsitem'
+ )
+ },{ key, value -> !ignoreAttributes.contains(key) })
+
+ // now make sure the outer most node is an include and there's only one
+ assert node.include?.size() == 1 && node.include[0].module?.size() == 1 && node.include[0].module[0]?.@name != null,
+ "Invalid xml doc result. Expected a single child node of the root node call 'include' with a single 'module' child node but got " + XmlUtil.serialize(node)
+
+ // create an outermost 'module' node with the correct name
+ Node ret = new Node(null, 'module', [ 'name':node.include[0].module[0].@name] )
+ node.include[0].children().each { if (it.name() != 'module') ret.append(it) }
+
+ // flatten out all other 'include' elements, parmlists, and typescopes
+ flatten(ret,['include', 'parmlist', 'typescope' ])
+
+ // remove any function nodes with default arguments
+ List tmpl = []
+ tmpl.addAll(ret.depthFirst())
+ for (Node cur : tmpl)
+ {
+ if ((cur.name() == 'function' || cur.name() == 'constructor') && cur.@defaultargs != null)
+ cur.parent().remove(cur)
+ }
+
+ // now validate that no other methods are overloaded since we can't handle those right now.
+ functionNodesByOverloads(ret).each { key, value -> assert value.size() == 1, "Cannot handle overloaded methods unless simply using defaulting: " + value }
+
+ // now gather up all of the typetabs and add a nice single
+ // typetab entry with a better format in the main module
+ List allTypetabs = ret.depthFirst().findAll { it.name() == 'typetab' }
+ Node typenode = new Node(ret,'typetab')
+ allTypetabs.each {
+ it.attributes().each { key, value ->
+ if (key != 'id' && key != value)
+ {
+ Node typeentry = new Node(null,'entry')
+ String namespace = findNamespace(it)
+ typeentry.@namespace = namespace != null ? namespace.trim() : ''
+ typeentry.@type = key
+ typeentry.@basetype = value
+
+ if (typenode.find({ it.@basetype == typeentry.@basetype && it.@namespace == typeentry.@namespace }) == null)
+ typenode.append(typeentry)
+ }
+ }
+ it.parent().remove(it)
+ }
+
+ // now remove all non-public methods, but leave constructors
+ List allMethods = ret.depthFirst().findAll({ it.name() == 'function' || it.name() == 'destructor' || it.name() == 'constructor'})
+ allMethods.each {
+ if (it.@access != null && it.@access != 'public' && it.name() != 'constructor')
+ it.parent().remove(it)
+ else
+ {
+ def doc = retrieveDocStringFromDoxygen(it)
+ if (doc != null && doc != '' && doc.trim() != ' ')
+ new Node(it,'doc',['value' : doc])
+ }
+ }
+
+ // now remove all non-public variables
+ List allVariables = ret.depthFirst().findAll({ it.name() == 'variable' })
+ allVariables.each {
+ if (it.@access != null && it.@access != 'public')
+ it.parent().remove(it)
+ else
+ {
+ def doc = retrieveDocStringFromDoxygen(it)
+ if (doc != null && doc != '' && doc.trim() != ' ')
+ new Node(it,'doc',['value' : doc])
+ }
+ }
+
+ // add the doc string to the classes
+ List allClasses = ret.depthFirst().findAll({ it.name() == 'class'})
+ allClasses.each {
+ def doc = retrieveDocStringFromDoxygen(it)
+ if (doc != null && doc != '' && doc.trim() != ' ')
+ new Node(it,'doc',['value' : doc])
+ }
+
+ return ret
+ }
+
+ /**
+ * @return true if the class node has a defined constructor. false otherwise.
+ */
+ public static boolean hasDefinedConstructor(Node clazz)
+ {
+ return (clazz.constructor != null && clazz.constructor.size() > 0)
+ }
+
+ /**
+ * @return true id this Node has a docstring associated with it.
+ */
+ public static boolean hasDoc(Node methodOrClass)
+ {
+ return methodOrClass.doc != null && methodOrClass.doc[0] != null && methodOrClass.doc[0].@value != null
+ }
+
+ /**
+ * @return true of the class node has a constructor but it's hidden (not 'public'). false otherwise.
+ */
+ public static boolean hasHiddenConstructor(Node clazz)
+ {
+ return (hasDefinedConstructor(clazz) && clazz.constructor[0].@access != null && clazz.constructor[0].@access != 'public')
+ }
+
+ /**
+ * <p>This will look through the entire module and look up a class node by name. It will return null if
+ * that class node isn't found. It's meant to be used to look up base classes from a base class list
+ * so it's fairly robust. It goes through the following rules:</p>
+ *
+ * <li>Does the FULL classname (considering the namespace) match the name provided.</li>
+ * <li>Does the FULL classname match the reference nodes namespace + '::' + the provided classname.</li>
+ * <li>Does the class node's name (which may contain the full classname) match the classname provided.</li>
+ *
+ * <p>Note, this method is not likely to find the classnode if you just pass a simple name and
+ * no referenceNode in the case where namespaces are used extensively.</p>
+ */
+ public static Node findClassNodeByName(Node module, String classname, Node referenceNode = null)
+ {
+ return module.depthFirst().findAll({ it.name() == 'class' }).find {
+ // first check to see if this FULL class name matches
+ if (findFullClassName(it).trim() == classname.trim()) return true
+
+ // now check to see if it matches the straight name considering the reference node
+ if (referenceNode != null && (findNamespace(referenceNode) + classname) == findFullClassName(it)) return true
+
+ // now just see if it matches the straight name
+ if (it.@name == classname) return true
+
+ return false
+ }
+ }
+
+ /**
+ * Find me the class node that this node either is, or is within.
+ * If this node is not within a class node then it will return null.
+ */
+ public static Node findClassNode(Node node)
+ {
+ if (node.name() == 'class') return node
+ return node.parent() == null ? null : findClassNode(node.parent())
+ }
+
+ /**
+ * If this node is a class node, or a child of a class name (for example, a method) then
+ * the full classname, with the namespace will be returned. Otherwise, null.
+ */
+ public static String findFullClassName(Node node, String separator = '::', boolean filename = false)
+ {
+ String ret = null
+ List rents = parents(node, { it.name() == 'class' })
+ if (node.name() == 'class') rents.add(node)
+ rents.each {
+ if (ret == null)
+ ret = it.@sym_name
+ else
+ ret += separator + it.@sym_name
+ }
+
+ return ret ? findNamespace(node,separator,true,filename) + ret : null
+ }
+
+ /**
+ * Given the Node this method looks to see if it occurs within namespace and returns
+ * the namespace as a String. It includes the trailing '::'
+ */
+ public static String findNamespace(Node node, String separator = '::', boolean endingSeparator = true, boolean filename = false)
+ {
+ String ret = null
+ parents(node, { it.name() == 'namespace' }).each {
+ String data = it.@name
+ if (filename)
+ data = data.replaceAll("_", "__")
+ if (ret == null)
+ ret = data
+ else
+ ret += separator + data
+ }
+
+ return ret == null ? '' : (ret + (endingSeparator ? separator : ''))
+ }
+
+ /**
+ * Gather up all of the parent nodes in a list ordered from the top node, down to the
+ * node that's passed as a parameter.
+ */
+ public static List parents(Node node, Closure filter = null, List ret = null)
+ {
+ Node parent = node.parent()
+ if (parent != null)
+ {
+ ret = parents(parent,filter,ret)
+ if (filter == null || filter.call(parent))
+ ret += parent
+ }
+ else if (ret == null)
+ ret = []
+
+ return ret
+ }
+
+ /**
+ * Group together overloaded methods into a map keyed by the first method's id. Each
+ * entry in this map contains a list of nodes that represent overloaded versions of
+ * the same method.
+ */
+ public static Map functionNodesByOverloads(Node module)
+ {
+ // find function nodes
+ Map ret = [:]
+ module.depthFirst().each {
+ if (it.name() == 'function' || it.name() == 'constructor' || it.name() == 'destructor')
+ {
+ String id = it.@sym_overloaded != null ? it.@sym_overloaded : it.@id
+ if (ret[id] == null) ret[id] = [it]
+ else ret[id] += it
+ }
+ }
+ return ret
+ }
+
+ /**
+ * Because the return type of a property is a combination of the function
+ * 'decl' and the function 'type,' this method will construct a valid Swig
+ * typestring from the two.
+ */
+ public static String getPropertyReturnSwigType(Node method)
+ {
+ // we're going to take a shortcut here because it appears only the pointer indicator
+ // ends up attached to the decl.
+ String prefix = (method.@decl != null && method.@decl == 'p.') ? 'p.' : ''
+ return method.@type != null ? prefix + method.@type : 'void'
+ }
+
+ /**
+ * Because the return type is a combination of the function 'decl' and the
+ * function 'type,' this method will construct a valid Swig typestring from
+ * the two.
+ */
+ public static String getReturnSwigType(Node method)
+ {
+ // we're going to take a shortcut here because it appears only the pointer indicator
+ // ends up attached to the decl.
+ String prefix = (method.@decl != null && method.@decl.endsWith('.p.')) ? 'p.' : ''
+ return method.@type != null ? prefix + method.@type : 'void'
+ }
+
+ /**
+ * Given the method node this will produce the actual name of the method as if
+ * it's being called. In the case of a constructor it will do a 'new.' In the
+ * case of a destructor it will produce a 'delete.'
+ */
+ public static String callingName(Node method)
+ {
+ // if we're not in a class we need the fully qualified name
+ String clazz = findFullClassName(method)
+ // if we're in a class then we are going to assume we have a 'self' pointer
+ // that we are going to invoke this on.
+ if (clazz == null)
+ return method.@name
+
+ if (method.name() == 'constructor')
+ return "new ${findNamespace(method)}${method.@sym_name}"
+
+ if (method.name() == 'destructor')
+ return 'delete'
+
+ // otherwise it's just a call on a class being invoked on an instance
+ return method.@name
+ }
+
+ /**
+ * Swig has 'insert' nodes in it's parse tree that contain code chunks that are
+ * meant to be inserted into various positions in the generated code. This method
+ * will extract the nodes that refer to the specific section asked for. See the
+ * Swig documentation for more information.
+ */
+ public static List getInsertNodes(Node module, String section)
+ {
+ return module.insert.findAll { section == it.@section || (section == 'header' && it.@section == null) }
+ }
+
+ public static String unescape(Node insertSection) { return unescape(insertSection.@code) }
+
+ public static String unescape(String insertSection) { return StringEscapeUtils.unescapeHtml(insertSection) }
+
+ public static boolean isDirector(Node method)
+ {
+ Node clazz = findClassNode(method)
+ if (!clazz || !clazz.@feature_director)
+ return false
+ if (method.name() == 'destructor')
+ return false
+ if (method.name() == 'constructor')
+ return false
+ return method.@storage && method.@storage == 'virtual'
+ }
+
+ /**
+ * This method will search from the 'searchFrom' Node up to the root
+ * looking for a %feature("knownbasetypes") declaration that the given 'type' is
+ * known for 'searchFrom' Node.
+ */
+ public static boolean isKnownBaseType(String type, Node searchFrom)
+ {
+ return hasFeatureSetting(type,searchFrom,'feature_knownbasetypes',{ it.split(',').find({ it.trim() == type }) != null })
+ }
+
+ /**
+ * This method will search from the 'searchFrom' Node up to the root
+ * looking for a %feature("knownapitypes") declaration that the given 'type' is
+ * known for 'searchFrom' Node.
+ */
+ public static String isKnownApiType(String type, Node searchFrom)
+ {
+ String rootType = SwigTypeParser.getRootType(type)
+ String namespace = findNamespace(searchFrom,'::',false)
+ String lastMatch = null
+ hasFeatureSetting(type,searchFrom,'feature_knownapitypes',{ it.split(',').find(
+ {
+ if (it.trim() == rootType)
+ {
+ lastMatch = rootType
+ return true
+ }
+ // we assume the 'type' is defined within namespace and
+ // so we can walk up the namespace appending the type until
+ // we find a match.
+ while (namespace != '')
+ {
+// System.out.println('checking ' + (namespace + '::' + rootType))
+ if ((namespace + '::' + rootType) == it.trim())
+ {
+ lastMatch = it.trim()
+ return true
+ }
+ // truncate the last namespace
+ int chop = namespace.lastIndexOf('::')
+ namespace = (chop > 0) ? namespace.substring(0,chop) : ''
+ }
+ return false
+ }) != null })
+ return lastMatch
+ }
+
+ private static String hasFeatureSetting(String type, Node searchFrom, String feature, Closure test)
+ {
+ if (!searchFrom)
+ return null
+
+ Object attr = searchFrom.attribute(feature)
+ if (attr && test.call(attr))
+ return attr.toString()
+
+ return hasFeatureSetting(type,searchFrom.parent(),feature,test)
+ }
+
+ private static void flatten(Node node, List elementsToRemove)
+ {
+ for (boolean done = false; !done;)
+ {
+ done = true
+ for (Node child : node.breadthFirst())
+ {
+ if (elementsToRemove.contains(child.name()))
+ {
+ Node parent = child.parent()
+ parent.remove(child)
+ child.each { parent.append(it) }
+ done = false
+ break
+ }
+ }
+ }
+ }
+
+ private static Node transform(Node node, Closure nodeFilter, Closure attributeFilter)
+ {
+ // need to create a map and a list of nodes (which will be children) from the
+ // attribute list.
+ Map attributes = [:]
+ List nodes = []
+ node.each {
+ if (nodeFilter == null || nodeFilter.call(it) == true)
+ {
+ if (it.name() == 'attributelist')
+ {
+ Tuple results = transformSwigAttributeList(it)
+ attributes.putAll(results[0].findAll(attributeFilter))
+ List childNodes = results[1]
+ childNodes.each {
+ if (nodeFilter != null && nodeFilter.call(it) == true)
+ nodes.add(transform(it,nodeFilter,attributeFilter))
+ }
+ }
+ else
+ nodes.add(transform(it,nodeFilter,attributeFilter))
+ }
+ }
+
+ // transfer the addr attribute from the original node over to the 'id' attribute of the
+ // new node by adding it to the attributes map
+ if (node.@addr)
+ {
+ // copy over the other attributes
+ node.attributes().findAll { key,value -> if (key != 'addr' && key != 'id') attributes[key] = value }
+ attributes['id'] = node.@addr
+ }
+
+ // In the case when the Node is a cdecl, we really want to replace the node name
+ // with the 'kind' attribute value.
+ Node ret
+ if (node.name() == 'cdecl' && attributes.containsKey('kind'))
+ ret = new Node(null, attributes['kind'], attributes.findAll({key, value -> key != 'kind' } ))
+ else
+ ret = new Node(null, node.name(), attributes)
+ nodes.each { ret.append(it) }
+ return ret
+ }
+
+ private static Tuple transformSwigAttributeList(Node attributeList)
+ {
+ Map attributes = [:]
+ List nodes = []
+ attributeList.each {
+ if (it.name() == 'attribute')
+ attributes[it.@name] = it.@value
+ else
+ nodes.add(it)
+ }
+ return [attributes, nodes]
+ }
+}
+
diff --git a/tools/codegenerator/SwigTypeParser.groovy b/tools/codegenerator/SwigTypeParser.groovy
new file mode 100644
index 0000000..24dfa8f
--- /dev/null
+++ b/tools/codegenerator/SwigTypeParser.groovy
@@ -0,0 +1,617 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import groovy.xml.XmlParser
+
+/**
+ * These methods are somewhat ugly because they have been copied out of
+ * the Swig source code and simply made compilable with groovy. They could
+ * all be much cleaner and smaller if they were completely groovyfied but
+ * I have no intention of doing that since they are complicated and they work
+ * and I don't want to try to trace down problems that would be inevitable
+ * with such a refactor.
+ */
+public class SwigTypeParser
+{
+ /**
+ * This holds a mapping for typedefs from a type to it's base type.
+ */
+ private static Map typeTable = [:]
+
+ /**
+ * Add a typedef node to the global list of typedefs to be used later in
+ * parsing types.
+ */
+ public static void appendTypeTable(Node typetab) { typetab.each { typeTable[it.@namespace + it.@type] = it.@basetype } }
+
+ /**
+ * Convert the type to an ltype considering the overloaded conversions.
+ */
+ public static String convertTypeToLTypeForParam(String ty)
+ {
+ // in the case where we're converting from a type to an ltype for a parameter,
+ // and the type is a r.*, we are going to assume the ltype is
+ // a "pass-by-value" on the stack.
+ return (ty.trim().startsWith('r.') ? SwigTypeParser.SwigType_ltype(ty.trim().substring(2)) : SwigTypeParser.SwigType_ltype(ty.trim()))
+ }
+
+ /**
+ * This method will return the base type for the provided type string. For example,
+ * if the type string is p.MyType you will get MyType. If the string is
+ * p.q(const).int you will get 'int'
+ */
+ public static String getRootType(String ty)
+ {
+ int li = ty.lastIndexOf('.')
+ return li >= 0 ? ty.substring(li + 1) : ty
+ }
+
+ /**
+ * SwigType_str()
+ *
+ * Create a C string representation of a datatype.
+ */
+ public static String SwigType_str(String ty, String id = null)
+ {
+ String result = id ? id : ''
+ String nextelement
+ String forwardelement
+ List elements = SwigType_split(ty)
+ if (elements == null) elements = []
+ int nelements = elements.size()
+ String element = nelements > 0 ? elements[0] : null
+
+ /* Now, walk the type list and start emitting */
+ for (int i = 0; i < nelements; i++) {
+ if (i < (nelements - 1)) {
+ nextelement = elements[i + 1]
+ forwardelement = nextelement
+ if (nextelement.startsWith('q(')) {
+ if (i < (nelements - 2)) forwardelement = elements[i + 2]
+ }
+ } else {
+ nextelement = null
+ forwardelement = null
+ }
+ if (element.startsWith('q(')) {
+ String q = SwigType_parm(element)
+ result = q + ' ' + result
+ } else if (SwigType_ispointer(element)) {
+ result = "*" + result
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ result = "(" + result + ")"
+ }
+ } else if (SwigType_ismemberpointer(element)) {
+ String q = SwigType_parm(element);
+ result = q + "::*" + result
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ result = '(' + result + ')'
+ }
+ } else if (SwigType_isreference(element)) {
+ result = '&' + result
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ result = '(' + result + ')'
+ }
+ } else if (SwigType_isarray(element)) {
+ result += '[' + SwigType_parm(element) + ']'
+ } else if (SwigType_isfunction(element)) {
+ result += '('
+ List parms = SwigType_parmlist(element)
+ boolean didOne = false
+ for (String cur : parms) {
+ String p = SwigType_str(cur)
+ result += (didOne ? ',' : '') + p
+ didOne = true
+ }
+ result += ')'
+ } else {
+ if (element.startsWith("v(...)")) result = result + "..."
+ else {
+ String bs = SwigType_namestr(element);
+ result = bs + ' ' + result
+ }
+ }
+ element = nextelement;
+ }
+ // convert template parameters
+ return result.replaceAll('<\\(', '<').replaceAll('\\)>', '>')
+ }
+
+ /**
+ * This will resolve the typedefs given the parameter passed is a simple type.
+ * see SwigType_resolve_all_typedefs which will handle qualifiers, pointers,
+ * references, and typedef of typedefs to resolve all the way down to the
+ * most basic types.
+ */
+ public static String SwigType_typedef_resolve(String t)
+ {
+ String td = typeTable[t]
+ String ret = td == null ? t : td
+ return ret
+ }
+
+ /**
+ * This will resolve typedefs and handle qualifiers, pointers,
+ * references, and typedef of typedefs to resolve all the way down to the
+ * most basic types.
+ */
+ public static String SwigType_resolve_all_typedefs(String s)
+ {
+ String result = ''
+ String tc = s
+
+ /* Nuke all leading qualifiers, appending them to the result*/
+ while (SwigType_isqualifier(tc)) {
+ List tmpl = SwigType_pop(tc)
+ tc = tmpl[1]
+ result += tmpl[0]
+ }
+
+ if (SwigType_issimple(tc)) {
+ /* Resolve any typedef definitions */
+ String tt = tc
+ String td
+ while ((td = SwigType_typedef_resolve(tt)) != tt) {
+ if (td != tt) {
+ tt = td
+ break
+ }
+ else if (td != tt) tt = td
+ }
+ tc = td
+
+ return tc
+ }
+
+ List tmpl = SwigType_pop(tc)
+ result += tmpl[0]
+ result += SwigType_resolve_all_typedefs(tmpl[1])
+ return result
+ }
+
+ /**
+ * SwigType_ltype(const SwigType *ty)
+ *
+ * Create a locally assignable type
+ */
+ public static String SwigType_ltype(String s) {
+ String result = ''
+ String tc = s
+
+ /* Nuke all leading qualifiers */
+ while (SwigType_isqualifier(tc)) {
+ tc = SwigType_pop(tc)[1]
+ }
+
+ if (SwigType_issimple(tc)) {
+ /* Resolve any typedef definitions */
+ String tt = tc
+ String td
+ while ((td = SwigType_typedef_resolve(tt)) != tt) {
+ if ((td != tt) && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) {
+ /* We need to use the typedef type */
+ tt = td
+ break
+ }
+ else if (td != tt) tt = td
+ }
+ tc = td
+ }
+ List elements = SwigType_split(tc)
+ int nelements = elements.size()
+
+ /* Now, walk the type list and start emitting */
+ boolean notypeconv = false
+ boolean firstarray = true
+ for (int i = 0; i < nelements; i++) {
+ String element = elements[i]
+ /* when we see a function, we need to preserve the following types */
+ if (SwigType_isfunction(element)) {
+ notypeconv = true
+ }
+ if (SwigType_isqualifier(element)) {
+ /* Do nothing. Ignore */
+ } else if (SwigType_ispointer(element)) {
+ result += element
+ // this is a bit of a short circuit to avoid having to import the entire SwigType_typedef_resolve method which
+ // handles pointers to typedefed types, etc.
+ // collapse the rest of the list
+ String tmps = ''
+ for (int j = i + 1; j < nelements; j++) tmps += elements[j]
+ return result + SwigType_ltype(tmps)
+ //firstarray = false
+ } else if (SwigType_ismemberpointer(element)) {
+ result += element
+ firstarray = false
+ } else if (SwigType_isreference(element)) {
+ if (notypeconv) {
+ result += element
+ } else {
+ result += "p."
+ }
+ firstarray = false
+ } else if (SwigType_isarray(element) && firstarray) {
+ if (notypeconv) {
+ result += element
+ } else {
+ result += "p."
+ }
+ firstarray = false;
+ } else if (SwigType_isenum(element)) {
+ boolean anonymous_enum = (element == "enum ")
+ if (notypeconv || !anonymous_enum) {
+ result += element
+ } else {
+ result += "int"
+ }
+ } else {
+ result += element
+ }
+ }
+
+ return result
+ // convert template parameters
+ //return result.replaceAll('<\\(', '<').replaceAll('\\)>', '>')
+ }
+
+ /**
+ * SwigType_lrtype(const SwigType *ty)
+ *
+ * Create a locally assignable reference type
+ */
+ public static String SwigType_lrtype(String s) {
+ String ltype = SwigType_ltype(s);
+ if (SwigType_ispointer(s)) {
+ return ltype;
+ } else {
+ return "r." + ltype;
+ }
+ }
+
+ /**
+ * This creates the C++ declaration for a valid ltype for the type string
+ * given. For example, if the type is a "const char*" which is equivalent
+ * to the type string 'p.q(const).char', the return value from this method
+ * will be "char *".
+ */
+ public static String SwigType_lstr(String type)
+ {
+ return SwigType_str(convertTypeToLTypeForParam(type))
+ }
+
+ public static boolean SwigType_ispointer(String t)
+ {
+ if (t.startsWith('q(')) t = t.substring(t.indexOf('.') + 1)
+ return t.startsWith('p.')
+ }
+
+ public static String SwigType_makepointer(String t)
+ {
+ String prefix = (t.startsWith('q(')) ? t.substring(0,t.indexOf('.') + 1) : ""
+ String remainder = (t.startsWith('q(')) ? t.substring(t.indexOf('.') + 1) : t
+
+ return prefix + "p." + remainder
+ }
+
+ public static boolean SwigType_isarray(String t) { return t.startsWith('a(') }
+
+ public static boolean SwigType_ismemberpointer(String t) { return t?.startsWith('m(') }
+
+ public static boolean SwigType_isqualifier(String t) { return t?.startsWith('q(') }
+
+ public static boolean SwigType_isreference(String t) { return t.startsWith('r.') }
+
+ public static boolean SwigType_isenum(String t) { return t.startsWith('enum') }
+
+ public static String SwigType_istemplate(String t) {
+ int c = t.indexOf("<(")
+ return (c >= 0 && t.indexOf(')>',c+2) >= 0)
+ }
+
+ public static boolean SwigType_isfunction(String t)
+ {
+ if (t.startsWith('q(')) t = t.substring(t.indexOf('.') + 1,)
+ return t.startsWith('f(')
+ }
+
+ public static boolean SwigType_isconst(String t) {
+ int c = 0
+ if (t == null) return false
+ if (t.substring(c).startsWith("q(")) {
+ String q = SwigType_parm(t)
+ if (q.indexOf("const") >= 0) return true
+ }
+ /* Hmmm. Might be const through a typedef */
+ if (SwigType_issimple(t)) {
+ String td = SwigType_typedef_resolve(t)
+ if (td != t) return SwigType_isconst(td)
+ }
+ return false
+ }
+
+
+ private static String SwigType_parm(String t) {
+ int start = t.indexOf("(")
+ if (start < 0) return null
+ start++
+ int nparens = 0
+ int c = start
+ while (c < t.length()) {
+ if (t.charAt(c) == ')') {
+ if (nparens == 0) break;
+ nparens--;
+ }
+ else if (t.charAt(c) == '(') nparens++
+ c++;
+ }
+ return t.substring(start,c)
+ }
+
+ public static List SwigType_templateparmlist(String t)
+ {
+ int i = t.indexOf('<');
+ return SwigType_parmlist(t.substring(i))
+ }
+
+ /* -----------------------------------------------------------------------------
+ * SwigType_parmlist()
+ *
+ * Splits a comma separated list of parameters into its component parts
+ * The input is expected to contain the parameter list within () brackets
+ * Returns 0 if no argument list in the input, ie there are no round brackets ()
+ * Returns an empty List if there are no parameters in the () brackets
+ * For example:
+ *
+ * Foo(std::string,p.f().Bar<(int,double)>)
+ *
+ * returns 2 elements in the list:
+ * std::string
+ * p.f().Bar<(int,double)>
+ * ----------------------------------------------------------------------------- */
+
+ private static List SwigType_parmlist(String p) {
+ List list = []
+ int itemstart
+
+ assert p, "Cannot pass null to SwigType_parmlist"
+ itemstart = p.indexOf('(')
+ assert p.indexOf('.') == -1 || p.indexOf('.') > itemstart, p + " is expected to contain sub elements of a type"
+ itemstart++
+ int c = itemstart
+ while (c < p.length()) {
+ if (p.charAt(c) == ',') {
+ list.add(p.substring(itemstart,c))
+ itemstart = c + 1
+ } else if (p.charAt(c) == '(') {
+ int nparens = 1
+ c++
+ while (c < p.length()) {
+ if (p.charAt(c) == '(') nparens++
+ if (p.charAt(c) == ')') {
+ nparens--
+ if (nparens == 0) break
+ }
+ c++
+ }
+ } else if (p.charAt(c) == ')') {
+ break;
+ }
+ if (c < p.length()) c++
+ }
+
+ if (c != itemstart) {
+ list.add(p.substring(itemstart,c))
+ }
+ return list;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * SwigType_namestr()
+ *
+ * Returns a string of the base type. Takes care of template expansions
+ * ----------------------------------------------------------------------------- */
+
+ private static String SwigType_namestr(String t) {
+ int d = 0
+ int c = t.indexOf("<(")
+
+ if (c < 0 || t.indexOf(')>',c+2) < 0) return t
+
+ String r = t.substring(0,c)
+ if (t.charAt(c - 1) == '<') r += ' '
+ r += '<'
+
+ List p = SwigType_parmlist(t.substring(c + 1))
+ for (int i = 0; i < p.size(); i++) {
+ String str = SwigType_str(p[i], null);
+ /* Avoid creating a <: token, which is the same as [ in C++ - put a space after '<'. */
+ if (i == 0 && str.length() > 0) r += ' '
+ r += str
+ if ((i + 1) < p.size()) r += ','
+ }
+ r += ' >'
+ String suffix = SwigType_templatesuffix(t);
+ if (suffix.length() > 0) {
+ String suffix_namestr = SwigType_namestr(suffix);
+ r += suffix_namestr
+ } else {
+ r += suffix
+ }
+ return r;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * SwigType_templatesuffix()
+ *
+ * Returns text after a template substitution. Used to handle scope names
+ * for example:
+ *
+ * Foo<(p.int)>::bar
+ *
+ * returns "::bar"
+ * ----------------------------------------------------------------------------- */
+
+ private static String SwigType_templatesuffix(String t) {
+ int c = 0
+ while (c < t.length()) {
+ if ((t.charAt(c) == '<') && (t.charAt(c + 1) == '(')) {
+ int nest = 1
+ c++
+ while (c < t.length() && nest != 0) {
+ if (t.charAt(c) == '<') nest++
+ if (t.charAt(c) == '>') nest--
+ c++
+ }
+ return t.substring(c)
+ }
+ c++
+ }
+ return ''
+ }
+
+ /* -----------------------------------------------------------------------------
+ * SwigType_split()
+ *
+ * Splits a type into it's component parts and returns a list of string.
+ * ----------------------------------------------------------------------------- */
+
+ private static List SwigType_split(String t) {
+ List list = []
+ int c = 0
+ int len
+
+ while (c < t.length()) {
+ len = element_size(t.substring(c))
+ String item = t.substring(c,c + len)
+ list += item
+ c = c + len
+ if (c < t.length() && t.charAt(c) == '.') c++
+ }
+ return list;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * static element_size()
+ *
+ * This utility function finds the size of a single type element in a type string.
+ * Type elements are always delimited by periods, but may be nested with
+ * parentheses. A nested element is always handled as a single item.
+ *
+ * Returns the integer size of the element (which can be used to extract a
+ * substring, to chop the element off, or for other purposes).
+ * ----------------------------------------------------------------------------- */
+
+ private static int element_size(String s) {
+ int nparen
+ int c = 0
+ while (c < s.length()) {
+ if (s.charAt(c) == '.') {
+ c++
+ return c
+ } else if (s.charAt(c) == '(') {
+ nparen = 1
+ c++
+ while (c < s.length()) {
+ if (s.charAt(c) == '(') nparen++
+ if (s.charAt(c) == ')') {
+ nparen--
+ if (nparen == 0) break
+ }
+ c++
+ }
+ }
+ if (c < s.length()) c++
+ }
+ return c;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * SwigType_pop()
+ *
+ * Pop one type element off the type.
+ * Example: t in: q(const).p.Integer
+ * t out: p.Integer
+ * result: q(const).
+ * ----------------------------------------------------------------------------- */
+
+ private static Tuple SwigType_pop(String t) {
+ String result
+ int c = 0
+
+ if (t == null)
+ return null
+
+ int sz = element_size(t.substring(c))
+ return [ t.substring(c,c + sz), t.substring(c+sz) ]
+ }
+
+ private static boolean SwigType_issimple(String t) {
+ int c = 0
+ if (!t) return false
+ while (c < t.length()) {
+ if (t.charAt(c) == '<') {
+ int nest = 1
+ c++
+ while (c < t.length() && nest != 0) {
+ if (t.charAt(c) == '<') nest++
+ if (t.charAt(c) == '>') nest--
+ c++
+ }
+ c--
+ }
+ if (t.charAt(c) == '.')
+ return false
+ c++
+ }
+ return true
+ }
+
+
+ public static void main(String[] args)
+ {
+ String xmlText = '''
+ <typetab>
+ <entry basetype="std::vector&lt;(p.XBMCAddon::xbmcgui::ListItem)&gt;" type="ListItemList" namespace="XBMCAddon::xbmcgui::"/>
+ </typetab>
+ '''
+ Node xml = new XmlParser().parseText(xmlText)
+
+ SwigTypeParser.appendTypeTable(xml)
+
+ // testPrint('f(int,int,int)','foo')
+ // testPrint('p.a(10).p.f(int,p.f(int).int)','foo')
+ // testPrint('p.q(const).char','foo')
+ // testPrint('f(r.q(const).String,p.q(const).XBMCAddon::xbmcgui::ListItem,bool)','foo')
+ // testPrint('r.q(const).String','foo')
+ // testPrint('q(const).p.q(const).char','foo')
+ //testPrint('std::vector<(p.String)>','foo')
+ // testPrint('r.q(const).String')
+ //System.out.println "${convertTypeToLType('bool')}"
+ //testPrint('p.q(const).XBMCAddon::xbmcgui::ListItemList')
+ //testPrint('p.q(const).XBMCAddon::xbmcgui::ListItemList')
+ //testPrint(SwigTypeParser.SwigType_makepointer('r.q(const).std::map<(String,String)>'), 'foo')
+ testPrint(SwigTypeParser.SwigType_makepointer('q(const).p.q(const).char'),'bfoo')
+ }
+
+ private static void testPrint(String ty, String id = 'foo')
+ {
+ println SwigTypeParser.SwigType_ltype(ty) + "|" + SwigTypeParser.SwigType_str(SwigTypeParser.SwigType_ltype(ty),id) + ' ' + " = " + ty + '|' + SwigTypeParser.SwigType_str(ty,id)
+ }
+}
diff --git a/tools/codegenerator/example/AddonModuleXbmc.i b/tools/codegenerator/example/AddonModuleXbmc.i
new file mode 100644
index 0000000..3837828
--- /dev/null
+++ b/tools/codegenerator/example/AddonModuleXbmc.i
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+%module xbmc
+
+%include "native/ModuleXbmc.h"
diff --git a/tools/codegenerator/example/Example-lval-rval.template b/tools/codegenerator/example/Example-lval-rval.template
new file mode 100644
index 0000000..77d506e
--- /dev/null
+++ b/tools/codegenerator/example/Example-lval-rval.template
@@ -0,0 +1,18 @@
+<%
+import SwigTypeParser
+%>
+Module Name: ${module.@name}
+<%
+module.function.each { functionNode ->
+%>
+ function: ${functionNode.@name}
+<%
+ functionNode.parm.eachWithIndex { param, index ->
+%>
+ parameter ${index}= name:${param.@name}, type:${param.@type}<% if (param.@value) { %>, default value: ${param.@value} <% } %>
+ type:${SwigTypeParser.SwigType_str(param.@type)}
+ lvalue-type:${SwigTypeParser.SwigType_lstr(param.@type)}
+<%
+ }
+}
+%>
diff --git a/tools/codegenerator/example/Example.call.template b/tools/codegenerator/example/Example.call.template
new file mode 100644
index 0000000..bc17282
--- /dev/null
+++ b/tools/codegenerator/example/Example.call.template
@@ -0,0 +1,48 @@
+<%
+import SwigTypeParser
+import Helper
+
+Helper.setup(null,
+ [ 'void': 'Py_INCREF(Py_None); ${result} = Py_None;' ],
+ null,
+ [ 'p.q(const).char':'${api} = convertSlString(${slarg});',
+ 'int':'${api} = convertSlInt(${slarg});'],
+ null)
+%>
+Module Name: ${module.@name}
+<%
+module.function.each { functionNode ->
+%>
+ function: ${functionNode.@name}
+
+<%
+ functionNode.parm.eachWithIndex { param, index ->
+%>
+ parameter ${index}= name:${param.@name}, type:${param.@type}<% if (param.@value) { %>, default value: ${param.@value} <% } %>
+ lvalue:${SwigTypeParser.SwigType_lstr(param.@type)}
+ rvalue:${SwigTypeParser.SwigType_str(param.@type)}
+ code to handle parameter ${index} {
+ // declare and set the value that came in from the scripting language
+ ScriptingLanguageType sl_${param.@name} = /* set the value from the scripting language */;
+ // declare and set the variable that will contain the api parameter
+ ${SwigTypeParser.SwigType_lstr(param.@type)} p_${param.@name};
+ ${Helper.getInConversion(param.@type,'p_' + param.@name,'sl_' + param.@name, functionNode)}
+ }
+<%
+ }
+%>
+ code to invoke the api method {
+ ${Helper.callingName(functionNode)}( <%
+ functionNode.parm.eachWithIndex { param, i ->
+ %> p_${param.@name}${i < functionNode.parm.size() - 1 ? "," : ""} <% } %> );
+ }
+
+ code to handle return value {
+ // This is an example of how Python handles return values
+ Py_Object* result;
+ ${Helper.getOutConversion(Helper.getReturnSwigType(functionNode),'result',functionNode)}
+ return result;
+ }
+<%
+}
+%>
diff --git a/tools/codegenerator/example/Example.intypemap.template b/tools/codegenerator/example/Example.intypemap.template
new file mode 100644
index 0000000..b64a49c
--- /dev/null
+++ b/tools/codegenerator/example/Example.intypemap.template
@@ -0,0 +1,31 @@
+<%
+import SwigTypeParser
+import Helper
+
+Helper.setup(null,null,null,
+ [ 'p.q(const).char':'${api} = convertSlString(${slarg});',
+ 'int':'${api} = convertSlInt(${slarg});'],
+ null)
+%>
+Module Name: ${module.@name}
+<%
+module.function.each { functionNode ->
+%>
+ function: ${functionNode.@name}
+<%
+ functionNode.parm.eachWithIndex { param, index ->
+%>
+ parameter ${index}= name:${param.@name}, type:${param.@type}<% if (param.@value) { %>, default value: ${param.@value} <% } %>
+ type:${SwigTypeParser.SwigType_str(param.@type)}
+ lvalue-type:${SwigTypeParser.SwigType_lstr(param.@type)}
+ code to handle parameter ${index} {
+ // declare and set the value that came in from the scripting language
+ ScriptingLanguageType sl_${param.@name} = /* set the value from the scripting language */;
+ // declare and set the variable that will contain the api parameter
+ ${SwigTypeParser.SwigType_lstr(param.@type)} p_${param.@name};
+ ${Helper.getInConversion(param.@type,'p_' + param.@name,'sl_' + param.@name, functionNode)}
+ }
+<%
+ }
+}
+%>
diff --git a/tools/codegenerator/example/Example.returns.template b/tools/codegenerator/example/Example.returns.template
new file mode 100644
index 0000000..9f6f75d
--- /dev/null
+++ b/tools/codegenerator/example/Example.returns.template
@@ -0,0 +1,42 @@
+<%
+import SwigTypeParser
+import Helper
+
+Helper.setup(null,
+ [ 'void': 'Py_INCREF(Py_None); ${result} = Py_None;' ],
+ null,
+ [ 'p.q(const).char':'${api} = convertSlString(${slarg});',
+ 'int':'${api} = convertSlInt(${slarg});'],
+ null)
+%>
+Module Name: ${module.@name}
+<%
+module.function.each { functionNode ->
+%>
+ function: ${functionNode.@name}
+
+<%
+ functionNode.parm.eachWithIndex { param, index ->
+%>
+ parameter ${index}= name:${param.@name}, type:${param.@type}<% if (param.@value) { %>, default value: ${param.@value} <% } %>
+ type:${SwigTypeParser.SwigType_str(param.@type)}
+ lvalue-type:${SwigTypeParser.SwigType_lstr(param.@type)}
+ code to handle parameter ${index} {
+ // declare and set the value that came in from the scripting language
+ ScriptingLanguageType sl_${param.@name} = /* set the value from the scripting language */;
+ // declare and set the variable that will contain the api parameter
+ ${SwigTypeParser.SwigType_lstr(param.@type)} p_${param.@name};
+ ${Helper.getInConversion(param.@type,'p_' + param.@name,'sl_' + param.@name, functionNode)}
+ }
+<%
+ }
+%>
+ code to handle return value {
+ // This is an example of how Python handles return values
+ Py_Object* result;
+ ${Helper.getOutConversion(Helper.getReturnSwigType(functionNode),'result',functionNode)}
+ return result;
+ }
+<%
+}
+%>
diff --git a/tools/codegenerator/example/native/ModuleXbmc.h b/tools/codegenerator/example/native/ModuleXbmc.h
new file mode 100644
index 0000000..14dd80d
--- /dev/null
+++ b/tools/codegenerator/example/native/ModuleXbmc.h
@@ -0,0 +1 @@
+void log(const char* msg, int level = LOGNOTICE);
diff --git a/tools/depends/.gitignore b/tools/depends/.gitignore
new file mode 100644
index 0000000..4f750fb
--- /dev/null
+++ b/tools/depends/.gitignore
@@ -0,0 +1,51 @@
+/configure
+/Makefile.include
+/autom4te.cache/
+/**/.gitignore
+/**/.installed-*
+
+/native/*/.installed-*
+/native/*/x86-native/*
+/native/*/x86_64-linux-gnu-native/*
+/native/*/x86_64-darwin*.*.*-native/
+/native/*/*-darwin*.*.*-native/
+/native/*/armeabi-v7a-native/*
+
+/target/*/.installed-*
+/target/*/native/*
+/target/*/x86/*
+/target/*/x86_64-linux-android-**
+/target/*/x86_64-linux-gnu-**
+/target/*/armeabi-v7a-**
+/target/*/arm*-linux-gnueabihf-**
+/target/*/arm*-linux-androideabi-**
+/target/*/arm*-linux-gnueabi-**
+/target/*/aarch64-linux-**
+/target/*/macosx*-target-**
+/target/*/i686-linux-android-**
+/target/*/iphoneos*.*_arm*-target-**
+/target/*/iphonesimulator*.*_x86_64*-target-**
+/target/*/appletvos*.*_arm64*-target-**
+/target/*/appletvsimulator*.*_x86_64*-target-**
+
+/pre-depends/
+/pre-build-deps/
+Toolchain.cmake
+Toolchain-Native.cmake
+config.site
+config.site.native
+/native/*/*native/
+/JsonSchemaBuilder/bin/
+/TexturePacker/bin/
+/target/ffmpeg/.build-*
+/target/ffmpeg/.ffmpeg-installed
+/target/ffmpeg/ffmpeg-*-*.tar.gz
+/target/ffmpeg/ffmpeg-*-*/
+/tools/depends/target/ffmpeg/ffmpeg-install/
+/tools/depends/target/Toolchain_binaddons.cmake
+/tools/depends/target/config-binaddons.site
+/target/cross-file.meson
+/target/libfmt/fmt-*.tar.gz
+/target/rapidjson/rapidjson-*.tar.gz
+/target/flatbuffers/*.tar.gz
+/target/libspdlog/spdlog-*.tar.gz
diff --git a/tools/depends/Makefile b/tools/depends/Makefile
new file mode 100644
index 0000000..8f53370
--- /dev/null
+++ b/tools/depends/Makefile
@@ -0,0 +1,25 @@
+include Makefile.include
+
+NATIVE=native/.installed-$(NATIVEPLATFORM)
+target=target/.installed-$(PLATFORM)
+all: $(target)
+
+$(NATIVE):
+ $(MAKE) -C native
+
+$(target): $(NATIVE)
+ $(MAKE) -C target
+
+clean:
+ $(MAKE) -C native clean
+ $(MAKE) -C target clean
+
+test-dependencies:
+ $(MAKE) -C native test-dependencies
+ $(MAKE) -C native
+ $(MAKE) -C target test-dependencies
+
+distclean::
+ $(MAKE) -C native distclean
+ $(MAKE) -C target distclean
+
diff --git a/tools/depends/Makefile.include.in b/tools/depends/Makefile.include.in
new file mode 100644
index 0000000..3a36d20
--- /dev/null
+++ b/tools/depends/Makefile.include.in
@@ -0,0 +1,127 @@
+abs_top_srcdir=@abs_top_srcdir@
+
+DEBUG_BUILD=@use_debug@
+TOOLCHAIN=@use_toolchain@
+NDKROOT=@use_ndk_path@
+SDKROOT=@use_sdk_path@
+CMAKE_SOURCE_DIR=$(abspath $(abs_top_srcdir)/../../)
+TARBALLS_LOCATION=@use_tarballs@
+PLATFORM=@deps_dir@
+HOST=@use_host@
+BUILD=@use_build@
+BUILD_CPU=@use_buildcpu@
+CPU=@use_cpu@
+MESON_CPU=@meson_cpu@
+MESON_SYSTEM=@meson_system@
+NATIVEPLATFORM=@build_cpu@-@build_os@-native
+NDK_LEVEL=@use_ndk_api@
+RETRIEVE_TOOL=@CURL@
+ARCHIVE_TOOL=@TAR@
+PREFIX=@prefix@/@deps_dir@
+NATIVEPREFIX=@prefix@/@tool_dir@
+OS=@platform_os@
+NATIVE_OS=@build_os@
+CROSS_COMPILING=@cross_compiling@
+ARCH_DEFINES=@ARCH_DEFINES@
+NATIVE_ARCH_DEFINES=@NATIVE_ARCH_DEFINES@
+TARGET_PLATFORM=@target_platform@
+RENDER_SYSTEM=@app_rendersystem@
+WINDOW_SYSTEM=@app_winsystem@
+SHA512SUM=@SHA512SUM@
+SHA256SUM=@SHA256SUM@
+SHASUM=@SHASUM@
+HASH_TOOL_FLAGS=-c --status
+
+HAS_ZLIB=@has_zlib@
+NEED_LIBICONV=@need_libiconv@
+LINK_ICONV=@link_iconv@
+ENABLE_GPLV3=@use_gplv3@
+
+BASE_URL=http://mirrors.kodi.tv/build-deps/sources
+ifneq ($(KODI_MIRROR),)
+BASE_URL=$(KODI_MIRROR)/build-deps/sources
+endif
+RETRIEVE_TOOL_FLAGS=-LsS --create-dirs --retry 10 --retry-connrefused -O
+ARCHIVE_TOOL_FLAGS=--strip-components=1 -xf
+CONFIG_SUB=@prefix@/@tool_dir@/share/automake-1.16/config.sub
+CONFIG_GUESS=@prefix@/@tool_dir@/share/automake-1.16/config.guess
+
+USE_CCACHE=@use_ccache@
+
+LD=@LD@
+ifneq (@use_ccache@,yes)
+ CC=@CC@
+ CXX=@CXX@
+ CPP=@CPP@
+else
+ CC=@CCACHE@ @CC@
+ CXX=@CCACHE@ @CXX@
+ CPP=@CCACHE@ @CPP@
+endif
+AR=@AR@
+RANLIB=@RANLIB@
+AS=@AS@
+NM=@NM@
+STRIP=@STRIP@
+READELF=@READELF@
+OBJDUMP=@OBJDUMP@
+
+CMAKE=@prefix@/@tool_dir@/bin/cmake -DCMAKE_TOOLCHAIN_FILE=$(PREFIX)/share/Toolchain.cmake -DCMAKE_INSTALL_PREFIX=$(PREFIX)
+CFLAGS=@platform_cflags@ @platform_includes@ -isystem @prefix@/@deps_dir@/include
+LDFLAGS=-L@prefix@/@deps_dir@/lib @platform_ldflags@
+CXXFLAGS=@platform_cxxflags@ @platform_includes@ -isystem @prefix@/@deps_dir@/include
+CPPFLAGS=@platform_cflags@ @platform_includes@ -isystem @prefix@/@deps_dir@/include
+# set configured FFmpeg configure options
+FFMPEG_CONFIGURE_OPTIONS=@ffmpeg_options@
+
+
+ifneq (@use_build_toolchain@,)
+ PATH:=@use_build_toolchain@/bin:@use_build_toolchain@/usr/bin:$(PATH)
+endif
+PATH:=@prefix@/@tool_dir@/bin:$(PATH)
+LD_FOR_BUILD=@LD_FOR_BUILD@
+CC_BINARY_FOR_BUILD=@CC_FOR_BUILD@
+CXX_BINARY_FOR_BUILD=@CXX_FOR_BUILD@
+ifneq (@use_ccache@,yes)
+ CC_FOR_BUILD=@CC_FOR_BUILD@
+ CXX_FOR_BUILD=@CXX_FOR_BUILD@
+else
+ CC_FOR_BUILD=@CCACHE@ @CC_FOR_BUILD@
+ CXX_FOR_BUILD=@CCACHE@ @CXX_FOR_BUILD@
+ CCACHE=@CCACHE@
+endif
+AR_FOR_BUILD=@AR_FOR_BUILD@
+RANLIB_FOR_BUILD=@RANLIB_FOR_BUILD@
+AS_FOR_BUILD=@AS_FOR_BUILD@
+NM_FOR_BUILD=@NM_FOR_BUILD@
+STRIP_FOR_BUILD=@STRIP_FOR_BUILD@
+READELF_FOR_BUILD=@READELF_FOR_BUILD@
+OBJDUMP_FOR_BUILD=@OBJDUMP_FOR_BUILD@
+
+NATIVE_CFLAGS=@host_includes@ -I@prefix@/@tool_dir@/include
+NATIVE_LDFLAGS=@host_includes@ -L@prefix@/@tool_dir@/lib
+NATIVE_CPPFLAGS=@host_includes@ -I@prefix@/@tool_dir@/include
+NATIVE_CXXFLAGS=@host_includes@ -I@prefix@/@tool_dir@/include
+
+VERSION.TXT := $(CMAKE_SOURCE_DIR)/version.txt
+APP_NAME=$(shell awk '/APP_NAME/ {print tolower($$2)}' $(VERSION.TXT))
+
+# Python related vars
+PYTHON_VERSION=3.11
+PYTHON_SITE_PKG=@prefix@/@deps_dir@/lib/python${PYTHON_VERSION}/site-packages
+
+ifeq ($(CPU), arm64)
+ export GASPP_FIX_XCODE5=1
+endif
+export AUTOM4TE=@prefix@/@tool_dir@/bin/autom4te
+export AUTOMAKE=@prefix@/@tool_dir@/bin/automake
+export AUTOCONF=@prefix@/@tool_dir@/bin/autoconf
+export ACLOCAL=@prefix@/@tool_dir@/bin/aclocal
+export ACLOCAL_PATH=@prefix@/@deps_dir@/share/aclocal:@prefix@/@tool_dir@/share/aclocal
+export AUTOPOINT=@prefix@/@tool_dir@/bin/autopoint
+export AUTOHEADER=@prefix@/@tool_dir@/bin/autoheader
+export LIBTOOL=@prefix@/@tool_dir@/bin/libtool
+export LIBTOOLIZE=@prefix@/@tool_dir@/bin/libtoolize
+
+export AUTORECONF=@prefix@/@tool_dir@/bin/autoreconf
+export JSON_BUILDER=$(NATIVEPREFIX)/bin/JsonSchemaBuilder
diff --git a/tools/depends/README.md b/tools/depends/README.md
new file mode 100644
index 0000000..64fb3f0
--- /dev/null
+++ b/tools/depends/README.md
@@ -0,0 +1,56 @@
+![Kodi Logo](../../docs/resources/banner_slim.png)
+
+# Kodi's Unified Depends Build System
+This builds native tools and library dependencies for platforms that do not provide them. It is used on our continuous integration system, **[jenkins](http://jenkins.kodi.tv/)**. A nice side effect is that it allows us to use the same tools and library versions across all platforms.
+
+In terms of build system usage, largest percentage is Autotools, followed by CMake and, in rare cases, hand crafted Makefiles. Tools and libraries versions are picked for a reason. If you feel the urge to start bumping them, be prepared for robust testing. Some tools and libraries need patching, most do not.
+
+That said, we try to stay fairly current with used versions and send patches upstream whenever possible.
+
+
+* **Autotools driven tools and libraries** tend to just work **provided** the author(s) followed proper Autotools format. Execute `./bootstrap`, followed by `./configure --[...]` and you're all set. If `./configure --[...]` gives you problems, try `./autoreconf -vif` before `./configure --[...]`.
+Some authors do silly things and only a `config.site` can correct the errors. Watch for this in the config.site(.in) file(s). It is the only way to handle bad Autotools behaviour.
+
+* **CMake driven tools and libraries** also tend to just work. Setup CMake flags correctly and go. On rare cases, you might need to diddle the native CMake setup.
+
+* **Hand crafted Makefiles driven tools and libraries** typically require manual sed tweaks or patching. May give you nightmares.
+
+## Usage Examples
+Paths below are examples. If you want to build Kodi, follow our **[build guides](../../docs/README.md)**.
+### All platforms
+`./bootstrap`
+### Darwin
+**macOS (x86_64)**
+`./configure --host=x86_64-apple-darwin`
+
+**iOS (arm64)**
+`./configure --host=aarch64-apple-darwin`
+
+**tvOS**
+`./configure --host=aarch64-apple-darwin --with-platform=tvos`
+
+**NOTE:** You can target the same `--prefix=` path. Each setup will be done in an isolated directory. The last configure/make you do is the one used for Kodi/Xcode.
+
+### Android
+**arm**
+`./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=arm-linux-androideabi --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-ndk-r20 --prefix=$HOME/android-tools/xbmc-depends`
+
+**aarch64**
+`./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=aarch64-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-ndk-r20 --prefix=$HOME/android-tools/xbmc-depends`
+
+**x86**
+`./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=i686-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-ndk-r20 --prefix=$HOME/android-tools/xbmc-depends`
+
+**x86_64**
+`./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=x86_64-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-ndk-r20 --prefix=$HOME/android-tools/xbmc-depends`
+
+> **Note:** Android x86 and x86_64 are not maintained and are not 100% sure that everything works correctly!
+
+### Linux
+**ARM (codesourcery/lenaro/etc)**
+`./configure --with-toolchain=/opt/toolchains/my-example-toolchain/ --prefix=/opt/xbmc-deps --host=arm-linux-gnueabi --with-rendersystem=gles`
+
+**Native**
+`./configure --with-toolchain=/usr --prefix=/opt/xbmc-deps --host=x86_64-linux-gnu --with-rendersystem=gl`
+
+Cross compiling is a PITA.
diff --git a/tools/depends/bootstrap b/tools/depends/bootstrap
new file mode 100755
index 0000000..9f03bce
--- /dev/null
+++ b/tools/depends/bootstrap
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Some platforms may not have m4/autoconf. If not, build temporary copies in
+# order to bootstrap.
+DEPENDS=`dirname $0`
+export PATH="$DEPENDS/pre-build-deps/bin:$PATH"
+which m4 >/dev/null 2>/dev/null || make -C $DEPENDS/pre-depends/m4-pre-depends
+which autoconf >/dev/null 2>/dev/null || make -C $DEPENDS/pre-depends/autoconf-pre-depends
+which autoconf >/dev/null 2>/dev/null || \
+ (echo "autoconf was not found and could not be built. Aborting." && exit 1)
+
+autoconf -f
diff --git a/tools/depends/build-aux/config.guess b/tools/depends/build-aux/config.guess
new file mode 100644
index 0000000..c4bd827
--- /dev/null
+++ b/tools/depends/build-aux/config.guess
@@ -0,0 +1,1456 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2016 Free Software Foundation, Inc.
+
+timestamp='2016-05-15'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2016 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ /sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || \
+ echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-unknown
+ ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently (or will in the future) and ABI.
+ case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # Determine ABI tags.
+ case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}${abi}"
+ exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:Sortix:*:*)
+ echo ${UNAME_MACHINE}-unknown-sortix
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE=alpha ;;
+ "EV5 (21164)")
+ UNAME_MACHINE=alphaev5 ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE=alphaev56 ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE=alphapca56 ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE=alphapca57 ;;
+ "EV6 (21264)")
+ UNAME_MACHINE=alphaev6 ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE=alphaev67 ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE=alphaev69 ;;
+ "EV7 (21364)")
+ UNAME_MACHINE=alphaev7 ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE=alphaev79 ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH=i386
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH=x86_64
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = hppa2.0w ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH=hppa2.0w
+ else
+ HP_ARCH=hppa64
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case ${UNAME_PROCESSOR} in
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW64*:*)
+ echo ${UNAME_MACHINE}-pc-mingw64
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ *:MSYS*:*)
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ aarch64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ cris:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ crisv32:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ e2k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ frv:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ hexagon:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ k1om:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+ ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-${LIBC}
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-${LIBC}
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+ *) echo hppa-unknown-linux-${LIBC} ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-${LIBC}
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-${LIBC}
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-${LIBC}
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ tile*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+ exit ;;
+ x86_64:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configure will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ eval $set_cc_for_build
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = x86; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = 386; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo ${UNAME_MACHINE}-unknown-esx
+ exit ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
+esac
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite
+config.guess and config.sub with the latest versions from:
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/depends/build-aux/config.sub b/tools/depends/build-aux/config.sub
new file mode 100644
index 0000000..a1f8229
--- /dev/null
+++ b/tools/depends/build-aux/config.sub
@@ -0,0 +1,1823 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2016 Free Software Foundation, Inc.
+
+timestamp='2016-08-25'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2016 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray | -microblaze*)
+ os=
+ basic_machine=$1
+ ;;
+ -bluegene*)
+ os=-cnk
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | ba \
+ | be32 | be64 \
+ | bfin \
+ | c4x | c8051 | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | epiphany \
+ | fido | fr30 | frv | ft32 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pyramid \
+ | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
+ | we32k \
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | aarch64-* | aarch64_be-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | ba-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | e2k-* | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | k1om-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
+ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pyramid-* \
+ | riscv32-* | riscv64-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
+ | visium-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ asmjs)
+ basic_machine=asmjs-unknown
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ e500v[12])
+ basic_machine=powerpc-unknown
+ os=$os"spe"
+ ;;
+ e500v[12]-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=$os"spe"
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=-msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc | ppcbe) basic_machine=powerpc-unknown
+ ;;
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* | -cloudabi* | -sortix* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+ | -onefs* | -tirtos* | -phoenix*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -nacl*)
+ ;;
+ -ios)
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ c8051-*)
+ os=-elf
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -cnk*|-aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/depends/build-aux/install-sh b/tools/depends/build-aux/install-sh
new file mode 100644
index 0000000..a9244eb
--- /dev/null
+++ b/tools/depends/build-aux/install-sh
@@ -0,0 +1,527 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2011-01-19.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ # Protect names problematic for `test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ # Protect names problematic for `test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names problematic for `test' and other utilities.
+ case $src in
+ -* | [=\(\)!]) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+ dst=$dst_arg
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ [-=\(\)!]*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test X"$d" = X && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/tools/depends/configure.ac b/tools/depends/configure.ac
new file mode 100644
index 0000000..30adee3
--- /dev/null
+++ b/tools/depends/configure.ac
@@ -0,0 +1,856 @@
+AC_PREREQ(2.59)
+AC_INIT([xbmc-depends], [2.00], [https://github.com/xbmc/xbmc])
+:${CFLAGS=""}
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_FILES([native/config.site.native Makefile.include
+ target/config.site target/config-binaddons.site
+ target/Toolchain.cmake target/Toolchain_binaddons.cmake
+ native/Toolchain-Native.cmake])
+AC_CANONICAL_HOST
+AC_CANONICAL_BUILD
+
+m4_include([m4/xbmc_arch.m4])
+m4_include([m4/ax_cxx_compile_stdcxx.m4])
+m4_include([m4/ax_compare_version.m4])
+
+# check for not same cpu value
+AC_DEFUN([MC_CHECK_NOT_CPU],
+[
+ AC_MSG_CHECKING([for $2])
+ case $1 in
+ $2*)
+ AC_MSG_ERROR(error in configure of --with-cpu=$1)
+ ;;
+ *)
+ AC_MSG_RESULT([$1 is not $2])
+ esac
+])
+
+AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--enable-debug],
+ [enable debugging information (default is yes)])],
+ [use_debug=$enableval],
+ [use_debug=yes])
+
+AC_ARG_ENABLE([ccache],
+ [AS_HELP_STRING([--disable-ccache],
+ [disable ccache])],
+ [use_ccache=no],
+ [use_ccache=yes])
+
+AC_ARG_WITH([linker],
+ [AS_HELP_STRING([--with-linker],
+ [specify linker to use.])],
+ [use_linker=$withval])
+
+AC_ARG_WITH([toolchain],
+ [AS_HELP_STRING([--with-toolchain],
+ [specify path to toolchain. Auto set for android. Defaults to xcode root for darwin, /usr for linux])],
+ [use_toolchain=$withval])
+
+AC_ARG_WITH([platform],
+ [AS_HELP_STRING([--with-platform],
+ [target platform [auto]])],
+ [use_platform=$withval],
+ [use_platform=auto])
+
+AC_ARG_WITH([firmware],
+ [AS_HELP_STRING([--with-firmware],
+ [platform specific firmware []])],
+ [use_firmware=$withval])
+
+AC_ARG_WITH([tarballs],
+ [AS_HELP_STRING([--with-tarballs],
+ [path where tarballs will be saved [prefix/xbmc-tarballs]])],
+ [use_tarballs=$withval])
+
+AC_ARG_WITH([cpu],
+ [AS_HELP_STRING([--with-cpu],
+ [optional. specify target cpu. guessed if not specified])],
+ [use_cpu=$withval],
+ [use_cpu=auto])
+
+AC_ARG_WITH([ndk-path],
+ [AS_HELP_STRING([--with-ndk-path],
+ [specify path to ndk (required for android only)])],
+ [use_ndk_path=$withval])
+
+AC_ARG_WITH([sdk-path],
+ [AS_HELP_STRING([--with-sdk-path],
+ [specify path to sdk (required for android only)])],
+ [use_sdk_path=$withval])
+
+AC_ARG_WITH([sdk],
+ [AS_HELP_STRING([--with-sdk],
+ [specify sdk platform version.])],
+ [use_sdk=$withval])
+
+AC_ARG_WITH([ndk-api],
+ [AS_HELP_STRING([--with-ndk-api],
+ [specify ndk level (optional for android), default is 21.])],
+ [use_ndk_api=$withval],
+ [use_ndk_api=21])
+
+AC_ARG_ENABLE([gplv3],
+ [AS_HELP_STRING([--enable-gplv3],
+ [enable gplv3 components. default is yes])],
+ [use_gplv3=$enableval],
+ [use_gplv3=yes])
+
+AC_ARG_WITH([rendersystem],
+ [AS_HELP_STRING([--with-rendersystem],
+ [render system to use])],
+ [app_rendersystem=$withval])
+
+AC_ARG_WITH([windowsystem],
+ [AS_HELP_STRING([--with-windowsystem],
+ [Windowing system to use])],
+ [app_winsystem=$withval])
+
+AC_ARG_WITH([target-cflags],
+ [AS_HELP_STRING([--with-target-cflags],
+ [C compiler flags (target)])],
+ [target_cflags=$withval])
+
+AC_ARG_WITH([target-cxxflags],
+ [AS_HELP_STRING([--with-target-cxxflags],
+ [C++ compiler flags (target)])],
+ [target_cxxflags=$withval],
+ [target_cxxflags=$target_cflags])
+
+AC_ARG_WITH([target-ldflags],
+ [AS_HELP_STRING([--with-target-ldflags],
+ [linker flags. Use e.g. for -l<lib> (target)])],
+ [target_ldflags=$withval])
+
+AC_ARG_WITH([ffmpeg-options],
+ [AS_HELP_STRING([--with-ffmpeg-options],
+ [FFmpeg configure options, e.g. --enable-vaapi (target)])],
+ [ffmpeg_options=$withval],
+ [ffmpeg_options=default])
+
+
+if test "$use_ccache" = "yes"; then
+ AC_CHECK_PROG(HAVE_CCACHE,ccache,"yes","no",)
+ if test "x$HAVE_CCACHE" = "xno" ; then
+ use_ccache=no
+ fi
+fi
+
+AC_PATH_PROG(CURL,curl,"no")
+if test "x$CURL" = "xno" ; then
+ AC_MSG_ERROR("Missing program: curl")
+fi
+
+AC_PATH_PROG(TAR,tar,"no")
+if test "x$TAR" = "xno" ; then
+ AC_MSG_ERROR("Missing program: tar")
+fi
+
+if test "x$use_linker" = "x" ; then
+ use_linker=ld
+fi
+
+if test "$use_debug" = "yes"; then
+ build_type="debug"
+else
+ build_type="release"
+fi
+
+use_host=$host_alias
+use_build=$build_cpu-$build_vendor-$build_os
+use_buildcpu=$build_cpu
+
+cross_compiling="yes"
+if test "x$host" = "x$build"; then
+ use_host=$build_cpu-$build_os
+ cross_compiling="no"
+fi
+
+deps_dir=$use_host-$build_type
+tool_dir=$build_cpu-$build_os-native
+cross_compiling="yes"
+
+case $build in
+ aarch64*-*-linux-gnu*|aarch64*-*-linux-uclibc*)
+ build_os="linux"
+ ;;
+ arm*-*-linux-gnu*|arm*-*-linux-uclibc*)
+ build_os="linux"
+ ;;
+ *i686*-linux-gnu*|i*86*-*-linux-uclibc*)
+ build_os="linux"
+ ;;
+ x86_64*-linux-gnu*|x86_64-*-linux-uclibc*)
+ build_os="linux"
+ android_toolchain_name="linux-x86_64"
+ ;;
+ *darwin*)
+ build_os="osx"
+ if test "x$build_cpu" = "xx86_64"; then
+ host_includes="-arch x86_64 -mmacosx-version-min=10.13"
+ else
+ host_includes="-arch arm64 -mmacosx-version-min=11.0"
+ fi
+ use_xcrun=xcrun
+
+ # acquire build platform (native) sdk sysroot.
+ build_platform=macosx
+ native_sdk_path=[`$use_xcrun --show-sdk-path`]
+ host_sysroot="$native_sdk_path"
+ host_includes="${host_includes} -isysroot $native_sdk_path"
+
+ CC_FOR_BUILD=[`$use_xcrun --find clang`]
+ use_build_toolchain=[`$CC_FOR_BUILD --version | grep InstalledDir | awk '{ print $2}'`]
+
+ # Android NDK currently only x86_64 prebuilts - Arctic Fox 2020.3.1
+ android_toolchain_name="darwin-x86_64"
+
+ host_cxxflags="-std=c++17 -stdlib=libc++"
+
+ if test "x$prefix" = "xNONE"; then
+ prefix=/Users/Shared/xbmc-depends
+ fi
+ ;;
+ *)
+ AC_MSG_ERROR(unsupported native build platform: $build)
+esac
+
+
+if test "x$build_os" = "xosx"; then
+ AC_PATH_PROG(SHASUM,shasum,"no")
+ if test "x$SHASUM" = "xno" ; then
+ AC_MSG_ERROR("Missing program: shasum")
+ fi
+else
+ AC_PATH_PROG(SHA512SUM,sha512sum,"no")
+ if test "x$SHA512SUM" = "xno" ; then
+ AC_MSG_ERROR("Missing program: sha512sum")
+ fi
+
+ AC_PATH_PROG(SHA256SUM,sha256sum,"no")
+ if test "x$SHA256SUM" = "xno" ; then
+ AC_MSG_ERROR("Missing program: sha256sum")
+ fi
+fi
+
+if test -n $use_build_toolchain; then
+ PATH_FOR_BUILD=$use_build_toolchain:$use_build_toolchain/usr/bin:$use_toolchain/bin:$PATH
+else
+ PATH_FOR_BUILD=$PATH
+fi
+
+AC_PATH_PROG([RANLIB_FOR_BUILD], [ranlib], ranlib, $PATH_FOR_BUILD)
+AC_PATH_PROG([LD_FOR_BUILD], [ld], ld, $PATH_FOR_BUILD)
+AC_PATH_PROG([AR_FOR_BUILD], [ar], ar, $PATH_FOR_BUILD)
+AC_PATH_PROG([READELF_FOR_BUILD], [readelf],, $PATH_FOR_BUILD)
+AC_PATH_PROG([STRIP_FOR_BUILD], [strip], strip, $PATH_FOR_BUILD)
+AC_PATH_PROG([AS_FOR_BUILD], [as], as, $PATH_FOR_BUILD)
+AC_PATH_PROG([NM_FOR_BUILD], [nm], nm, $PATH_FOR_BUILD)
+AC_PATH_PROG([OBJDUMP_FOR_BUILD], [objdump], objdump, $PATH_FOR_BUILD)
+AC_PATH_PROG([CC_FOR_BUILD],[clang gcc llvm-gcc], gcc, $PATH_FOR_BUILD)
+AC_PATH_PROG([CXX_FOR_BUILD],[clang++ g++ llvm-g++], g++, $PATH_FOR_BUILD)
+
+platform_cc=gcc
+platform_cxx=g++
+
+case $host in
+ *-*linux-android*)
+ use_toolchain="${use_toolchain:-$use_ndk_path/toolchains/llvm/prebuilt/$android_toolchain_name}"
+ platform_cc=$use_host$use_ndk_api-clang
+ platform_cxx=$use_host$use_ndk_api-clang++
+
+ platform_tool_prefix=llvm-
+
+ case $host in
+ arm*-*linux-android*)
+ platform_cc=armv7a-linux-androideabi$use_ndk_api-clang
+ platform_cxx=armv7a-linux-androideabi$use_ndk_api-clang++
+ esac
+ ;;
+ *darwin*)
+ CC=[`$use_xcrun --find clang`]
+ platform_cxx=clang++
+ use_toolchain=[`$CC --version | grep InstalledDir | awk '{ print $2}'`]
+esac
+
+if test -n $use_toolchain; then
+ PATH_FOR_HOST=$use_toolchain:$use_toolchain/usr/bin:$use_toolchain/bin:$PATH
+else
+ PATH_FOR_HOST=$PATH
+fi
+
+AC_PATH_TOOL([RANLIB], [${platform_tool_prefix}ranlib],, $PATH_FOR_HOST)
+AC_PATH_TOOL([LD], [${use_linker}],, $PATH_FOR_HOST)
+AC_PATH_TOOL([AR], [${platform_tool_prefix}ar],, $PATH_FOR_HOST)
+AC_PATH_TOOL([READELF], [${platform_tool_prefix}readelf],, $PATH_FOR_HOST)
+AC_PATH_TOOL([STRIP], [${platform_tool_prefix}strip],, $PATH_FOR_HOST)
+AC_PATH_TOOL([AS], [${platform_tool_prefix}as],, $PATH_FOR_HOST)
+AC_PATH_TOOL([NM], [${platform_tool_prefix}nm],, $PATH_FOR_HOST)
+AC_PATH_TOOL([OBJDUMP], [${platform_tool_prefix}objdump],, $PATH_FOR_HOST)
+AC_PATH_TOOL([CC],[$platform_cc],,$PATH_FOR_HOST)
+AC_PATH_TOOL([CXX],[$platform_cxx],,$PATH_FOR_HOST)
+
+if test "x$LD" = "x"; then
+ AC_MSG_ERROR(No linker found with name ${use_linker}. You may want to provide using --with-linker=<linker>)
+fi
+
+case $build in
+ *darwin*)
+ # MacOS 11 requires explicit isysroot for autoconf compiler tests
+ # However we do not want to pollute CFLAGS/CXXFLAGS once compiler tests are complete
+ CFLAGS="${CFLAGS} $host_includes"
+ CXXFLAGS="${CXXFLAGS} $host_includes"
+esac
+
+AC_PROG_CPP
+
+case $build in
+ *darwin*)
+ CFLAGS=$(echo "$CFLAGS" | sed "s|$host_includes||")
+ CXXFLAGS=$(echo "$CXXFLAGS" | sed "s|$host_includes||")
+esac
+
+case $host in
+ *-*linux-android*)
+ deps_dir="$use_host-$use_ndk_api-$build_type"
+ platform_cflags="-DANDROID -D__ANDROID_API__=$use_ndk_api -fexceptions -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fPIC -DPIC"
+ optimize_flags="-Os"
+ platform_ldflags="-Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -L$prefix/$deps_dir/lib/android-$use_ndk_api"
+
+ case $host in
+ arm*-*linux-android*)
+ if test "x$use_cpu" = "xauto"; then
+ use_cpu="armeabi-v7a"
+ fi
+ if test "x$use_cpu" = "xarmeabi-v7a"; then
+ platform_cflags="${platform_cflags} -march=armv7-a -mtune=cortex-a9 -mfloat-abi=softfp -mfpu=neon"
+ fi
+ platform_ldflags="${platform_ldflags} -Wl,--exclude-libs,libunwind.a"
+ meson_cpu="arm"
+ ;;
+ aarch64*-*linux-android*)
+ if test "x$use_cpu" = "xauto"; then
+ use_cpu="arm64-v8a"
+ fi
+ if test "x$use_cpu" = "xarm64-v8a"; then
+ platform_cflags="${platform_cflags} -march=armv8-a -mtune=cortex-a53"
+ fi
+ meson_cpu="aarch64"
+ ;;
+ i*86*-linux-android*)
+ if test "x$use_cpu" = "xauto"; then
+ use_cpu=$host_cpu
+ fi
+ meson_cpu="x86"
+ ;;
+ x86_64*-linux-android*)
+ if test "x$use_cpu" = "xauto"; then
+ use_cpu=$host_cpu
+ fi
+ meson_cpu="x86_64"
+ ;;
+ *)
+ AC_MSG_ERROR(unsupported host ($use_host))
+ esac
+
+ platform_cxxflags="$platform_cflags -frtti"
+ platform_includes="-isystem $prefix/$deps_dir/include/android-$use_ndk_api"
+ platform_os="android"
+ meson_system="android"
+ #android builds are always cross
+ cross_compiling="yes"
+ ;;
+ arm*-*-linux-gnu*|arm*-*-linux-uclibc*|aarch64*-*-linux-gnu*|aarch*-*-linux-be*)
+ case $host in
+ arm*-*-linux-gnu*|arm*-*-linux-uclibc*)
+ meson_cpu="arm"
+ ;;
+ aarch64*-*-linux-gnu*|aarch*-*-linux-be*)
+ meson_cpu="aarch64"
+ ;;
+ esac
+ if test "x$use_cpu" = "xauto"; then
+ use_cpu=$host_cpu
+ fi
+ use_toolchain="${use_toolchain:-/usr}"
+ platform_cflags="-fPIC -DPIC"
+ optimize_flags="-Os"
+ platform_ldflags="-Wl,-rpath-link=$prefix/$deps_dir/lib"
+ platform_cxxflags="$platform_cflags"
+ platform_os="linux"
+ meson_system="linux"
+ target_platform="wayland gbm"
+ ;;
+ *i686*-linux-gnu*|i*86*-*-linux-uclibc*|x86_64*-linux-gnu*|x86_64-*-linux-uclibc*)
+ case $host in
+ *i686*-linux-gnu*|i*86*-*-linux-uclibc*)
+ meson_cpu="x86"
+ ;;
+ x86_64*-linux-gnu*|x86_64-*-linux-uclibc*)
+ meson_cpu="x86_64"
+ ;;
+ esac
+ use_cpu=$host_cpu
+ use_toolchain="${use_toolchain:-/usr}"
+ platform_cflags="-fPIC -DPIC"
+ optimize_flags="-O2"
+ platform_cxxflags="$platform_cflags"
+ platform_os="linux"
+ meson_system="linux"
+ ffmpeg_options_default="--enable-vaapi --enable-vdpau --cpu=$use_cpu"
+ target_platform="x11 wayland gbm"
+ ;;
+ *darwin*)
+ # darwin builds are always cross
+ cross_compiling="yes"
+
+ meson_system="darwin"
+
+ platform_cflags="-fheinous-gnu-extensions"
+ platform_ldflags="-Wl,-search_paths_first"
+
+ case $use_platform in
+ tvos)
+ target_platform=appletvos
+ platform_os="darwin_embedded"
+ ;;
+ ios)
+ target_platform=iphoneos
+ platform_os="darwin_embedded"
+ ;;
+ macos)
+ target_platform=macosx
+ platform_os="osx"
+ ;;
+ *)
+ AC_MSG_ERROR(error in configure no platform provided --with-platform)
+ ;;
+ esac
+
+ found_sdk_version=[`$use_xcrun --sdk $target_platform --show-sdk-version`]
+ use_sdk="${use_sdk:-$found_sdk_version}"
+ use_sdk_path=$($use_xcrun --sdk $target_platform --show-sdk-path)
+ sdk_name=$target_platform$use_sdk
+
+ case $host in
+ x86_64-apple-darwin)
+ MC_CHECK_NOT_CPU([$use_cpu], "arm*")
+
+ # setup which cpu to use
+ if test "x$use_cpu" = "xauto"; then
+ use_cpu=x86_64
+ meson_cpu=$use_cpu
+ else
+ AC_MSG_ERROR(invalid architecture (--with-cpu=$use_cpu))
+ fi
+
+ target_minver="10.13"
+
+ # check provided window system is valid_sdk
+ # if no window system supplied, default to SDL for now.
+ if test -n "$app_winsystem"; then
+ if test "$app_winsystem" != "native" && test "$app_winsystem" != "sdl"; then
+ AC_MSG_ERROR(Window system must be native or sdl)
+ fi
+ else
+ app_winsystem=sdl
+ fi
+ ;;
+ aarch64-apple-darwin*)
+ MC_CHECK_NOT_CPU([$use_cpu], "*86")
+
+ case $platform_os in
+ darwin_embedded)
+ target_minver="11.0"
+ ;;
+ osx)
+ target_minver="11.0"
+ app_winsystem=native
+ ;;
+ *)
+ AC_MSG_ERROR(invalid platform for architecture ($host))
+ ;;
+ esac
+
+ # setup which cpu to use
+ if test "x$use_cpu" = "xauto"; then
+ use_cpu=arm64
+ meson_cpu="aarch64"
+ else
+ AC_MSG_ERROR(invalid architecture (--with-cpu=$use_cpu))
+ fi
+
+ platform_cflags="${platform_cflags} -ftree-vectorize -pipe -Wno-trigraphs -fpascal-strings"
+ platform_cflags="${platform_cflags} -Wreturn-type -Wunused-variable -fmessage-length=0 -gdwarf-2"
+ optimize_flags="-O3"
+ platform_ldflags="${platform_ldflags} -L$use_sdk_path/usr/lib"
+ ;;
+ esac
+
+ AX_COMPARE_VERSION([$use_sdk], [ge], [$target_minver], , AC_MSG_ERROR("invalid SDK version provided (--with-sdk=$use_sdk) less than minimum supported ($target_minver)"))
+
+ platform_min_version="$target_platform-version-min=$target_minver"
+
+ platform_includes="-arch $use_cpu -m$platform_min_version -isysroot $use_sdk_path"
+ platform_ldflags="${platform_ldflags} $platform_includes -stdlib=libc++"
+ platform_cxxflags="${platform_cxxflags} -stdlib=libc++"
+ deps_dir="${sdk_name}_${use_cpu}-target-${build_type}"
+ ;;
+ *)
+ AC_MSG_ERROR(unsupported host ($use_host))
+esac
+
+case $use_platform in
+ ios|tvos|macos)
+ ;;
+ auto)
+ ;;
+ *)
+ AC_MSG_ERROR(unsupported platform ($use_platform))
+esac
+
+XBMC_SETUP_ARCH_DEFINES()
+
+case $build in
+ *darwin*)
+ if test "$platform_os" != "android"; then
+ # MacOS 11 requires explicit isysroot for autoconf link tests
+ # However we do not want to pollute LDFLAGS once lib link tests are complete
+ LDFLAGS="$platform_includes"
+ AC_CHECK_LIB([z], [main], has_zlib=1, AC_MSG_WARN("No zlib support in toolchain. Will build libz."); has_zlib=0)
+ fi
+esac
+
+if test "$platform_os" = "android"; then
+ need_libiconv=1
+else
+ AC_SEARCH_LIBS([iconv_open],iconv, link_iconv=$ac_cv_search_iconv_open, link_iconv=-liconv; AC_MSG_WARN("No iconv support in toolchain. Will build libiconv."); need_libiconv=1)
+fi
+
+case $build in
+ *darwin*)
+ LDFLAGS=$(echo "$LDFLAGS" | sed "s|$platform_includes||")
+esac
+
+if test "$link_iconv" = "none required"; then
+ link_iconv=
+fi
+
+if test "x$prefix" = "xNONE"; then
+ AC_MSG_ERROR([No prefix path defined. Use for ex: --prefix=/opt/xbmc-depends]);
+fi
+
+if test "$use_ccache" = "yes"; then
+ AC_PATH_TOOL([CCACHE], [ccache],, $PATH_FOR_HOST)
+fi
+
+if test -z $use_tarballs; then
+ use_tarballs=$prefix/xbmc-tarballs
+fi
+
+if test "$platform_os" = "linux"; then
+ if test "$app_rendersystem" != "gl" && test "$app_rendersystem" != "gles"; then
+ AC_MSG_ERROR(Rendersystem is required for linux - must be gl or gles)
+ fi
+fi
+
+if test "$platform_os" = "android"; then
+ if test -z $use_ndk_path; then
+ AC_MSG_ERROR("NDK path is required for android")
+ fi
+
+ if ([! test -f "$use_ndk_path/source.properties"] && [! test -f "$use_ndk_path/RELEASE.TXT"]) ; then
+ AC_MSG_ERROR("$use_ndk_path is not an NDK directory")
+ fi
+
+ if test -z $use_sdk_path; then
+ AC_MSG_ERROR("SDK path is required for android")
+ fi
+
+ if [ ! test -f $use_sdk_path/tools/bin/sdkmanager ]; then
+ AC_MSG_ERROR(verify sdk path)
+ fi
+
+ if [ ! test -f $use_ndk_path/sources/android/native_app_glue/android_native_app_glue.h ]; then
+ AC_MSG_ERROR(verify ndk path)
+ fi
+
+ #not all sort versions support -V - probe it...
+ SORT_PARAMS=""
+ sort -V /dev/null > /dev/null 2>&1 && SORT_PARAMS="-V"
+ build_tools_path=$use_sdk_path/tools:$use_sdk_path/platform-tools:$use_sdk_path/build-tools/`ls $use_sdk_path/build-tools | sort $SORT_PARAMS | tail -n 1`
+fi
+
+# darwin needs unzip in Codesign.command
+if test "$platform_os" = "android" || test "$platform_os" = "osx" || test "$platform_os" = "darwin_embedded"; then
+ AC_CHECK_PROG(HAVE_UNZIP,unzip,"yes","no",)
+ if test "x$HAVE_UNZIP" = "xno"; then
+ AC_MSG_ERROR("Missing program: unzip")
+ fi
+fi
+# darwin needs zip in Codesign.command
+# android needs zip in tools/android/packaging/Makefile sharedobb target
+if test "$platform_os" = "android" || test "$platform_os" = "osx" || test "$platform_os" = "darwin_embedded"; then
+ AC_CHECK_PROG(HAVE_ZIP,zip,"yes","no",)
+ if test "x$HAVE_ZIP" = "xno"; then
+ AC_MSG_ERROR("Missing program: zip")
+ fi
+fi
+
+# Some dumb checks to see if paths might be correct.
+if [ ! `mkdir -p $prefix/$deps_dir/include` ]; then
+ AC_MSG_ERROR(unable to create $prefix/$deps_dir/include. verify that the path and permissions are correct.)
+fi
+
+if [ ! `mkdir -p $prefix/$deps_dir/lib` ]; then
+ AC_MSG_ERROR(unable to create $prefix/$deps_dir/lib. verify that the path and permissions are correct.)
+fi
+
+if [ ! `mkdir -p $prefix/$deps_dir/share` ]; then
+ AC_MSG_ERROR(unable to create $prefix/$deps_dir/share. verify that the path and permissions are correct.)
+fi
+
+if [ ! `mkdir -p $prefix/$tool_dir/include` ]; then
+ AC_MSG_ERROR(unable to create $prefix/$tool_dir/include. verify that the path and permissions are correct.)
+fi
+
+if [ ! `mkdir -p $prefix/$tool_dir/lib` ]; then
+ AC_MSG_ERROR(unable to create $prefix/$tool_dir/lib. verify that the path and permissions are correct.)
+fi
+
+if [ ! `mkdir -p $prefix/$tool_dir/share` ]; then
+ AC_MSG_ERROR(unable to create $prefix/$tool_dir/share. verify that the path and permissions are correct.)
+fi
+
+if [ ! `mkdir -p $prefix/$tool_dir/bin` ]; then
+ AC_MSG_ERROR(unable to create $prefix/$tool_dir/share. verify that the path and permissions are correct.)
+fi
+
+if [ ! `mkdir -p $use_tarballs` ]; then
+ AC_MSG_ERROR(unable to create tarballs dir. verify that the path and permissions are correct.)
+fi
+
+# remove unwanted optimization flags
+tmp_cflags=$(echo $CFLAGS $platform_cflags | sed 's/-O@<:@123@:>@//g;s/-g //g;s/ \{2,\}//g')
+tmp_cxxflags=$(echo $CXXFLAGS $platform_cxxflags | sed 's/-O@<:@123@:>@//g;s/-g //g;s/ \{2,\}//g')
+
+release_cflags="-DNDEBUG=1"
+
+# newer xcode version accept -Og flag, but debugging doesn't work with it
+if test "$platform_os" = "osx" || test "$platform_os" = "darwin_embedded"; then
+ debug_cflags="-g -D_DEBUG"
+else
+ CFLAGS="$tmp_cflags -Og -g -D_DEBUG"
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE([int foo;])],
+ [debug_cflags="-Og -g -D_DEBUG"],
+ [debug_cflags="-g -D_DEBUG"])
+fi
+
+# add user supplied flags to the end, so they override our defaults
+platform_cflags_release="$tmp_cflags $release_cflags $optimize_flags $target_cflags"
+platform_cxxflags_release="$tmp_cxxflags $release_cflags $optimize_flags $target_cxxflags"
+platform_cflags_debug="$tmp_cflags $debug_cflags $target_cflags"
+platform_cxxflags_debug="$tmp_cxxflags $debug_cflags $target_cxxflags"
+platform_ldflags="${platform_ldflags} $target_ldflags $LIBS"
+
+if test "$use_debug" = "yes"; then
+ platform_cflags="$platform_cflags_debug"
+ platform_cxxflags="$platform_cxxflags_debug"
+else
+ platform_cflags="$platform_cflags_release"
+ platform_cxxflags="$platform_cxxflags_release"
+fi
+
+CXXFLAGS="$platform_cxxflags $platform_includes"
+CXX_CACHED="$CXX"
+AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
+CXX="$CXX_CACHED"
+platform_cxxflags="${platform_cxxflags} -std=c++17"
+
+if test "$ffmpeg_options" = "default"; then
+ ffmpeg_options="$ffmpeg_options_default"
+fi
+
+if test "$platform_os" = "android"; then
+echo -e
+ AC_SUBST(use_sdk_path)
+ AC_SUBST(use_ndk_path)
+ AC_SUBST(use_ndk_api)
+ AC_SUBST(build_tools_path)
+fi
+
+AC_SUBST(meson_system)
+AC_SUBST(meson_cpu)
+AC_SUBST(use_debug)
+AC_SUBST(use_host)
+AC_SUBST(use_build)
+AC_SUBST(deps_dir)
+AC_SUBST(tool_dir)
+AC_SUBST(use_buildcpu)
+AC_SUBST(use_cpu)
+AC_SUBST(use_toolchain)
+AC_SUBST(use_build_toolchain)
+AC_SUBST(use_tarballs)
+AC_SUBST(target_platform)
+AC_SUBST(use_firmware)
+AC_SUBST(cross_compiling)
+AC_SUBST(platform_cflags)
+AC_SUBST(platform_cxxflags)
+AC_SUBST(platform_cflags_release)
+AC_SUBST(platform_cxxflags_release)
+AC_SUBST(platform_cflags_debug)
+AC_SUBST(platform_cxxflags_debug)
+AC_SUBST(platform_ldflags)
+AC_SUBST(platform_includes)
+AC_SUBST(platform_os)
+AC_SUBST(build_os)
+AC_SUBST(has_zlib)
+AC_SUBST(link_iconv)
+AC_SUBST(need_libiconv)
+AC_SUBST(use_gplv3)
+AC_SUBST(use_ccache)
+AC_SUBST(host_includes)
+AC_SUBST(host_sysroot)
+AC_SUBST(host_cxxflags)
+AC_SUBST(app_rendersystem)
+AC_SUBST(app_winsystem)
+AC_SUBST(ffmpeg_options)
+
+[
+if test "x$CCACHE" = "x"
+then
+ MESON_CC="'$CC'"
+ MESON_CXX="'$CXX'"
+else
+ MESON_CC="['$CCACHE', '$CC']"
+ MESON_CXX="['$CCACHE', '$CXX']"
+fi
+
+# Parse and handle CFLAGS
+read -r CFLAGS_ARRAY << EOF
+$platform_cflags $platform_includes -isystem $prefix/$deps_dir/include
+EOF
+
+count=1
+for flag in $CFLAGS_ARRAY; do
+ if test "$flag" != "-g"
+ then
+ if test "$flag" != "-gdwarf-2"
+ then
+ MESON_CFLAGS="${MESON_CFLAGS:+${MESON_CFLAGS}, }'$flag'"
+ count=$((count + 1))
+ fi
+ fi
+done
+if test "$count" -gt "2"
+then
+ MESON_CFLAGS="[$MESON_CFLAGS]"
+fi
+
+# Parse and handle CXXFLAGS
+read -r CXXFLAGS_ARRAY << EOF
+$platform_cxxflags $platform_includes -isystem $prefix/$deps_dir/include
+EOF
+
+count=1
+for flag in $CXXFLAGS_ARRAY; do
+ if test "$flag" != "-g"
+ then
+ if test "$flag" != "-gdwarf-2"
+ then
+ MESON_CXXFLAGS="${MESON_CXXFLAGS:+${MESON_CXXFLAGS}, }'$flag'"
+ count=$((count + 1))
+ fi
+ fi
+done
+if test "$count" -gt "2"
+then
+ MESON_CXXFLAGS="[$MESON_CXXFLAGS]"
+fi
+
+# Parse and handle LDFLAGS
+read -r LDFLAGS_ARRAY << EOF
+-L$prefix/$deps_dir/lib $platform_ldflags
+EOF
+
+count=1
+for flag in $LDFLAGS_ARRAY; do
+ MESON_LDFLAGS="${MESON_LDFLAGS:+${MESON_LDFLAGS}, }'$flag'"
+ count=$((count + 1))
+done
+if test "$count" -gt "2"
+then
+ MESON_LDFLAGS="[$MESON_LDFLAGS]"
+fi
+
+cat > $prefix/$deps_dir/share/cross-file.meson << EOF
+[binaries]
+c = $MESON_CC
+cpp = $MESON_CXX
+ar = '$AR'
+strip = '$STRIP'
+pkgconfig = '$prefix/$tool_dir/bin/pkg-config'
+
+[host_machine]
+system = '$meson_system'
+cpu_family = '$meson_cpu'
+cpu = '$use_cpu'
+endian = 'little'
+
+[properties]
+pkg_config_libdir = '$prefix/$deps_dir/lib/pkgconfig'
+
+[built-in options]
+c_args = $MESON_CFLAGS
+c_link_args = $MESON_LDFLAGS
+cpp_args = $MESON_CXXFLAGS
+cpp_link_args = $MESON_LDFLAGS
+default_library = 'static'
+prefix = '$prefix/$deps_dir'
+libdir = 'lib'
+bindir = 'bin'
+includedir = 'include'
+EOF
+]
+
+AC_OUTPUT
+
+if test "$platform_os" = "darwin_embedded"; then
+ if test "$use_platform" = "ios"; then
+ simulator_sdk_path=[`$use_xcrun --sdk iphonesimulator --show-sdk-path`]
+ echo -e "use simulator:\t $simulator_sdk_path"
+ fi
+fi
+
+cp -vf target/config.site $prefix/$deps_dir/share
+cp -vf target/config-binaddons.site $prefix/$tool_dir/share
+cp -vf target/Toolchain.cmake $prefix/$deps_dir/share
+cp -vf target/Toolchain_binaddons.cmake $prefix/$deps_dir/share
+cp -vf native/config.site.native $prefix/$tool_dir/share/config.site
+cp -vf native/Toolchain-Native.cmake $prefix/$tool_dir/share
+
+
+echo -e "\n\n#------- configuration -------#"
+echo -e "ccache:\t\t $use_ccache"
+echo -e "build type:\t\t $build_type"
+echo -e "build system:\t $use_build"
+echo -e "build cpu:\t\t $use_buildcpu"
+echo -e "build includes:\t $host_includes"
+echo -e "toolchain:\t\t $use_toolchain"
+echo -e "cpu:\t\t\t $use_cpu"
+echo -e "host:\t\t $use_host"
+echo -e "CC:\t\t $CC"
+echo -e "CXX:\t\t $CXX"
+echo -e "cflags:\t\t $platform_cflags"
+echo -e "cxxflags:\t\t $platform_cxxflags"
+echo -e "ldflags:\t\t $platform_ldflags"
+echo -e "platform_includes:\t $platform_includes"
+echo -e "ffmpeg options:\t $ffmpeg_options"
+echo -e "prefix:\t\t $prefix"
+echo -e "depends:\t\t $prefix/$deps_dir"
+if test "$platform_os" = "android"; then
+ echo -e "ndk-api-level:\t $use_ndk_api"
+ echo -e "build-tools:\t $build_tools_path"
+fi
diff --git a/tools/depends/download-files.include b/tools/depends/download-files.include
new file mode 100644
index 0000000..3f41dfa
--- /dev/null
+++ b/tools/depends/download-files.include
@@ -0,0 +1,59 @@
+#
+HASH_FOUND = yes
+ifneq ($(SHA512),)
+ HASH_TYPE = sha512
+ HASH_TOOL ?= $(SHA512SUM)
+else ifneq ($(SHA256),)
+ HASH_TYPE = sha256
+ HASH_TOOL ?= $(SHA256SUM)
+else
+ HASH_FOUND = no
+ HASH_TYPE = sha512
+ HASH_TOOL = sha512sum
+endif
+
+SED_FLAG = -i
+ifeq ($(NATIVE_OS), osx)
+ HASH_TOOL = $(SHASUM) -a $(shell echo $(HASH_TYPE) | sed 's/^sha//')
+ SED_FLAG = -i ''
+endif
+
+# non-depends builds might not set this, use defaults
+ifeq ($(HASH_TOOL),)
+ HASH_TOOL = sha512sum
+ HASH_TOOL_FLAGS = -c --status
+endif
+
+HASH_SUM = $($(shell echo $(HASH_TYPE) | tr '[:lower:]' '[:upper:]'))
+
+.PHONY: $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+all: $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+
+$(TARBALLS_LOCATION)/$(ARCHIVE):
+ cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE)
+
+$(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE): $(TARBALLS_LOCATION)/$(ARCHIVE)
+ifeq ($(HASH_FOUND),no)
+ cd $(TARBALLS_LOCATION); $(HASH_TOOL) $(ARCHIVE) > $(ARCHIVE).$(HASH_TYPE)
+ $(HASH_TYPE)=$$(cat $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE) | cut -d ' ' -f 1) && \
+ sed $(SED_FLAG) -e "s/#SHA512#/SHA512=$${sha512}/" -e "s/#SHA256#/SHA256=$${sha256}/" Makefile
+endif
+ifeq ($(HASH_FOUND),yes)
+# we really need 2 spaces between sha hash and file name!
+# if the hash sum doesn't match we retry up to 3 times, add verbose curl output for diagnostics on retries
+# if we fail 3 times, cleanup anything downloaded (eg bad tar)
+ @cd $(TARBALLS_LOCATION); echo "$(HASH_SUM) $(ARCHIVE)" > $(ARCHIVE).$(HASH_TYPE) && $(HASH_TOOL) $(HASH_TOOL_FLAGS) $(ARCHIVE).$(HASH_TYPE) \
+ || {\
+ echo "Error: failed to verify hash sum of $(ARCHIVE), expected type: $(HASH_TYPE) value $(HASH_SUM), retrying.." ;\
+ tries=1 ;\
+ while [ $$tries -le 3 ]; do \
+ echo "download $(ARCHIVE) retry $$tries" ;\
+ rm $(TARBALLS_LOCATION)/$(ARCHIVE) ;\
+ sleep 3 ;\
+ $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) -v $(BASE_URL)/$(ARCHIVE) ;\
+ $(HASH_TOOL) $(HASH_TOOL_FLAGS) $(ARCHIVE).$(HASH_TYPE) && exit 0 || tries=$$((tries + 1)) ;\
+ done ;\
+ rm $(TARBALLS_LOCATION)/$(ARCHIVE) ;\
+ exit 1 ;\
+ }
+endif
diff --git a/tools/depends/m4/ax_compare_version.m4 b/tools/depends/m4/ax_compare_version.m4
new file mode 100644
index 0000000..ffb4997
--- /dev/null
+++ b/tools/depends/m4/ax_compare_version.m4
@@ -0,0 +1,177 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_compare_version.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+#
+# DESCRIPTION
+#
+# This macro compares two version strings. Due to the various number of
+# minor-version numbers that can exist, and the fact that string
+# comparisons are not compatible with numeric comparisons, this is not
+# necessarily trivial to do in a autoconf script. This macro makes doing
+# these comparisons easy.
+#
+# The six basic comparisons are available, as well as checking equality
+# limited to a certain number of minor-version levels.
+#
+# The operator OP determines what type of comparison to do, and can be one
+# of:
+#
+# eq - equal (test A == B)
+# ne - not equal (test A != B)
+# le - less than or equal (test A <= B)
+# ge - greater than or equal (test A >= B)
+# lt - less than (test A < B)
+# gt - greater than (test A > B)
+#
+# Additionally, the eq and ne operator can have a number after it to limit
+# the test to that number of minor versions.
+#
+# eq0 - equal up to the length of the shorter version
+# ne0 - not equal up to the length of the shorter version
+# eqN - equal up to N sub-version levels
+# neN - not equal up to N sub-version levels
+#
+# When the condition is true, shell commands ACTION-IF-TRUE are run,
+# otherwise shell commands ACTION-IF-FALSE are run. The environment
+# variable 'ax_compare_version' is always set to either 'true' or 'false'
+# as well.
+#
+# Examples:
+#
+# AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8])
+# AX_COMPARE_VERSION([3.15],[lt],[3.15.8])
+#
+# would both be true.
+#
+# AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8])
+# AX_COMPARE_VERSION([3.15],[gt],[3.15.8])
+#
+# would both be false.
+#
+# AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8])
+#
+# would be true because it is only comparing two minor versions.
+#
+# AX_COMPARE_VERSION([3.15.7],[eq0],[3.15])
+#
+# would be true because it is only comparing the lesser number of minor
+# versions of the two values.
+#
+# Note: The characters that separate the version numbers do not matter. An
+# empty string is the same as version 0. OP is evaluated by autoconf, not
+# configure, so must be a string, not a variable.
+#
+# The author would like to acknowledge Guido Draheim whose advice about
+# the m4_case and m4_ifvaln functions make this macro only include the
+# portions necessary to perform the specific comparison specified by the
+# OP argument in the final configure script.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Tim Toolan <toolan@ele.uri.edu>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 13
+
+dnl #########################################################################
+AC_DEFUN([AX_COMPARE_VERSION], [
+ AC_REQUIRE([AC_PROG_AWK])
+
+ # Used to indicate true or false condition
+ ax_compare_version=false
+
+ # Convert the two version strings to be compared into a format that
+ # allows a simple string comparison. The end result is that a version
+ # string of the form 1.12.5-r617 will be converted to the form
+ # 0001001200050617. In other words, each number is zero padded to four
+ # digits, and non digits are removed.
+ AS_VAR_PUSHDEF([A],[ax_compare_version_A])
+ A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
+ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/[[^0-9]]//g'`
+
+ AS_VAR_PUSHDEF([B],[ax_compare_version_B])
+ B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
+ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/[[^0-9]]//g'`
+
+ dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary
+ dnl # then the first line is used to determine if the condition is true.
+ dnl # The sed right after the echo is to remove any indented white space.
+ m4_case(m4_tolower($2),
+ [lt],[
+ ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"`
+ ],
+ [gt],[
+ ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"`
+ ],
+ [le],[
+ ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"`
+ ],
+ [ge],[
+ ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"`
+ ],[
+ dnl Split the operator from the subversion count if present.
+ m4_bmatch(m4_substr($2,2),
+ [0],[
+ # A count of zero means use the length of the shorter version.
+ # Determine the number of characters in A and B.
+ ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'`
+ ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'`
+
+ # Set A to no more than B's length and B to no more than A's length.
+ A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"`
+ B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"`
+ ],
+ [[0-9]+],[
+ # A count greater than zero means use only that many subversions
+ A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
+ B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
+ ],
+ [.+],[
+ AC_WARNING(
+ [invalid OP numeric parameter: $2])
+ ],[])
+
+ # Pad zeros at end of numbers to make same length.
+ ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`"
+ B="$B`echo $A | sed 's/./0/g'`"
+ A="$ax_compare_version_tmp_A"
+
+ # Check for equality or inequality as necessary.
+ m4_case(m4_tolower(m4_substr($2,0,2)),
+ [eq],[
+ test "x$A" = "x$B" && ax_compare_version=true
+ ],
+ [ne],[
+ test "x$A" != "x$B" && ax_compare_version=true
+ ],[
+ AC_WARNING([invalid OP parameter: $2])
+ ])
+ ])
+
+ AS_VAR_POPDEF([A])dnl
+ AS_VAR_POPDEF([B])dnl
+
+ dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.
+ if test "$ax_compare_version" = "true" ; then
+ m4_ifvaln([$4],[$4],[:])dnl
+ m4_ifvaln([$5],[else $5])dnl
+ fi
+]) dnl AX_COMPARE_VERSION
diff --git a/tools/depends/m4/ax_cxx_compile_stdcxx.m4 b/tools/depends/m4/ax_cxx_compile_stdcxx.m4
new file mode 100644
index 0000000..43087b2
--- /dev/null
+++ b/tools/depends/m4/ax_cxx_compile_stdcxx.m4
@@ -0,0 +1,951 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+# Check for baseline language coverage in the compiler for the specified
+# version of the C++ standard. If necessary, add switches to CXX and
+# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
+# or '14' (for the C++14 standard).
+#
+# The second argument, if specified, indicates whether you insist on an
+# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+# -std=c++11). If neither is specified, you get whatever works, with
+# preference for an extended mode.
+#
+# The third argument, if specified 'mandatory' or if left unspecified,
+# indicates that baseline support for the specified C++ standard is
+# required and that the macro should error out if no mode with that
+# support is found. If specified 'optional', then configuration proceeds
+# regardless, after defining HAVE_CXX${VERSION} if and only if a
+# supporting mode is found.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
+# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
+# Copyright (c) 2015 Paul Norman <penorman@mac.com>
+# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
+# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
+# Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 11
+
+dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
+dnl (serial version number 13).
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
+ m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
+ [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
+ [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
+ [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
+ m4_if([$2], [], [],
+ [$2], [ext], [],
+ [$2], [noext], [],
+ [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
+ m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
+ [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
+ [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
+ [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
+ AC_LANG_PUSH([C++])dnl
+ ac_success=no
+
+ m4_if([$2], [noext], [], [dnl
+ if test x$ac_success = xno; then
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ switch="-std=gnu++${alternative}"
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+ $cachevar,
+ [ac_save_CXX="$CXX"
+ CXX="$CXX $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXX="$ac_save_CXX"])
+ if eval test x\$$cachevar = xyes; then
+ CXX="$CXX $switch"
+ if test -n "$CXXCPP" ; then
+ CXXCPP="$CXXCPP $switch"
+ fi
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+
+ m4_if([$2], [ext], [], [dnl
+ if test x$ac_success = xno; then
+ dnl HP's aCC needs +std=c++11 according to:
+ dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+ dnl Cray's crayCC needs "-h std=c++11"
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+ $cachevar,
+ [ac_save_CXX="$CXX"
+ CXX="$CXX $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXX="$ac_save_CXX"])
+ if eval test x\$$cachevar = xyes; then
+ CXX="$CXX $switch"
+ if test -n "$CXXCPP" ; then
+ CXXCPP="$CXXCPP $switch"
+ fi
+ ac_success=yes
+ break
+ fi
+ done
+ if test x$ac_success = xyes; then
+ break
+ fi
+ done
+ fi])
+ AC_LANG_POP([C++])
+ if test x$ax_cxx_compile_cxx$1_required = xtrue; then
+ if test x$ac_success = xno; then
+ AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
+ fi
+ fi
+ if test x$ac_success = xno; then
+ HAVE_CXX$1=0
+ AC_MSG_NOTICE([No compiler with C++$1 support was found])
+ else
+ HAVE_CXX$1=1
+ AC_DEFINE(HAVE_CXX$1,1,
+ [define if the compiler supports basic C++$1 syntax])
+ fi
+ AC_SUBST(HAVE_CXX$1)
+])
+
+
+dnl Test body for checking C++11 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+)
+
+
+dnl Test body for checking C++14 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+)
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+)
+
+dnl Tests for new features in C++11
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+ namespace test_static_assert
+ {
+
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ }
+
+ namespace test_final_override
+ {
+
+ struct Base
+ {
+ virtual ~Base() {}
+ virtual void f() {}
+ };
+
+ struct Derived : public Base
+ {
+ virtual ~Derived() override {}
+ virtual void f() override {}
+ };
+
+ }
+
+ namespace test_double_right_angle_brackets
+ {
+
+ template < typename T >
+ struct check {};
+
+ typedef check<void> single_type;
+ typedef check<check<void>> double_type;
+ typedef check<check<check<void>>> triple_type;
+ typedef check<check<check<check<void>>>> quadruple_type;
+
+ }
+
+ namespace test_decltype
+ {
+
+ int
+ f()
+ {
+ int a = 1;
+ decltype(a) b = 2;
+ return a + b;
+ }
+
+ }
+
+ namespace test_type_deduction
+ {
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static const bool value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static const bool value = true;
+ };
+
+ template < typename T1, typename T2 >
+ auto
+ add(T1 a1, T2 a2) -> decltype(a1 + a2)
+ {
+ return a1 + a2;
+ }
+
+ int
+ test(const int c, volatile int v)
+ {
+ static_assert(is_same<int, decltype(0)>::value == true, "");
+ static_assert(is_same<int, decltype(c)>::value == false, "");
+ static_assert(is_same<int, decltype(v)>::value == false, "");
+ auto ac = c;
+ auto av = v;
+ auto sumi = ac + av + 'x';
+ auto sumf = ac + av + 1.0;
+ static_assert(is_same<int, decltype(ac)>::value == true, "");
+ static_assert(is_same<int, decltype(av)>::value == true, "");
+ static_assert(is_same<int, decltype(sumi)>::value == true, "");
+ static_assert(is_same<int, decltype(sumf)>::value == false, "");
+ static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+ return (sumf > 0.0) ? sumi : add(c, v);
+ }
+
+ }
+
+ namespace test_noexcept
+ {
+
+ int f() { return 0; }
+ int g() noexcept { return 0; }
+
+ static_assert(noexcept(f()) == false, "");
+ static_assert(noexcept(g()) == true, "");
+
+ }
+
+ namespace test_constexpr
+ {
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+ {
+ return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+ }
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c(const CharT *const s) noexcept
+ {
+ return strlen_c_r(s, 0UL);
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("1") == 1UL, "");
+ static_assert(strlen_c("example") == 7UL, "");
+ static_assert(strlen_c("another\0example") == 7UL, "");
+
+ }
+
+ namespace test_rvalue_references
+ {
+
+ template < int N >
+ struct answer
+ {
+ static constexpr int value = N;
+ };
+
+ answer<1> f(int&) { return answer<1>(); }
+ answer<2> f(const int&) { return answer<2>(); }
+ answer<3> f(int&&) { return answer<3>(); }
+
+ void
+ test()
+ {
+ int i = 0;
+ const int c = 0;
+ static_assert(decltype(f(i))::value == 1, "");
+ static_assert(decltype(f(c))::value == 2, "");
+ static_assert(decltype(f(0))::value == 3, "");
+ }
+
+ }
+
+ namespace test_uniform_initialization
+ {
+
+ struct test
+ {
+ static const int zero {};
+ static const int one {1};
+ };
+
+ static_assert(test::zero == 0, "");
+ static_assert(test::one == 1, "");
+
+ }
+
+ namespace test_lambdas
+ {
+
+ void
+ test1()
+ {
+ auto lambda1 = [](){};
+ auto lambda2 = lambda1;
+ lambda1();
+ lambda2();
+ }
+
+ int
+ test2()
+ {
+ auto a = [](int i, int j){ return i + j; }(1, 2);
+ auto b = []() -> int { return '0'; }();
+ auto c = [=](){ return a + b; }();
+ auto d = [&](){ return c; }();
+ auto e = [a, &b](int x) mutable {
+ const auto identity = [](int y){ return y; };
+ for (auto i = 0; i < a; ++i)
+ a += b--;
+ return x + identity(a + b);
+ }(0);
+ return a + b + c + d + e;
+ }
+
+ int
+ test3()
+ {
+ const auto nullary = [](){ return 0; };
+ const auto unary = [](int x){ return x; };
+ using nullary_t = decltype(nullary);
+ using unary_t = decltype(unary);
+ const auto higher1st = [](nullary_t f){ return f(); };
+ const auto higher2nd = [unary](nullary_t f1){
+ return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+ };
+ return higher1st(nullary) + higher2nd(nullary)(unary);
+ }
+
+ }
+
+ namespace test_variadic_templates
+ {
+
+ template <int...>
+ struct sum;
+
+ template <int N0, int... N1toN>
+ struct sum<N0, N1toN...>
+ {
+ static constexpr auto value = N0 + sum<N1toN...>::value;
+ };
+
+ template <>
+ struct sum<>
+ {
+ static constexpr auto value = 0;
+ };
+
+ static_assert(sum<>::value == 0, "");
+ static_assert(sum<1>::value == 1, "");
+ static_assert(sum<23>::value == 23, "");
+ static_assert(sum<1, 2>::value == 3, "");
+ static_assert(sum<5, 5, 11>::value == 21, "");
+ static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+ }
+
+ // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+ // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+ // because of this.
+ namespace test_template_alias_sfinae
+ {
+
+ struct foo {};
+
+ template<typename T>
+ using member = typename T::member_type;
+
+ template<typename T>
+ void func(...) {}
+
+ template<typename T>
+ void func(member<T>*) {}
+
+ void test();
+
+ void test() { func<foo>(0); }
+
+ }
+
+} // namespace cxx11
+
+#endif // __cplusplus >= 201103L
+
+]])
+
+
+dnl Tests for new features in C++14
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
+
+// If the compiler admits that it is not ready for C++14, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201402L
+
+#error "This is not a C++14 compiler"
+
+#else
+
+namespace cxx14
+{
+
+ namespace test_polymorphic_lambdas
+ {
+
+ int
+ test()
+ {
+ const auto lambda = [](auto&&... args){
+ const auto istiny = [](auto x){
+ return (sizeof(x) == 1UL) ? 1 : 0;
+ };
+ const int aretiny[] = { istiny(args)... };
+ return aretiny[0];
+ };
+ return lambda(1, 1L, 1.0f, '1');
+ }
+
+ }
+
+ namespace test_binary_literals
+ {
+
+ constexpr auto ivii = 0b0000000000101010;
+ static_assert(ivii == 42, "wrong value");
+
+ }
+
+ namespace test_generalized_constexpr
+ {
+
+ template < typename CharT >
+ constexpr unsigned long
+ strlen_c(const CharT *const s) noexcept
+ {
+ auto length = 0UL;
+ for (auto p = s; *p; ++p)
+ ++length;
+ return length;
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("x") == 1UL, "");
+ static_assert(strlen_c("test") == 4UL, "");
+ static_assert(strlen_c("another\0test") == 7UL, "");
+
+ }
+
+ namespace test_lambda_init_capture
+ {
+
+ int
+ test()
+ {
+ auto x = 0;
+ const auto lambda1 = [a = x](int b){ return a + b; };
+ const auto lambda2 = [a = lambda1(x)](){ return a; };
+ return lambda2();
+ }
+
+ }
+
+ namespace test_digit_separators
+ {
+
+ constexpr auto ten_million = 100'000'000;
+ static_assert(ten_million == 100000000, "");
+
+ }
+
+ namespace test_return_type_deduction
+ {
+
+ auto f(int& x) { return x; }
+ decltype(auto) g(int& x) { return x; }
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static constexpr auto value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static constexpr auto value = true;
+ };
+
+ int
+ test()
+ {
+ auto x = 0;
+ static_assert(is_same<int, decltype(f(x))>::value, "");
+ static_assert(is_same<int&, decltype(g(x))>::value, "");
+ return x;
+ }
+
+ }
+
+} // namespace cxx14
+
+#endif // __cplusplus >= 201402L
+
+]])
+
+
+dnl Tests for new features in C++17
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
+
+// If the compiler admits that it is not ready for C++17, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201703L
+
+#error "This is not a C++17 compiler"
+
+#else
+
+#include <initializer_list>
+#include <utility>
+#include <type_traits>
+
+namespace cxx17
+{
+
+ namespace test_constexpr_lambdas
+ {
+
+ constexpr int foo = [](){return 42;}();
+
+ }
+
+ namespace test::nested_namespace::definitions
+ {
+
+ }
+
+ namespace test_fold_expression
+ {
+
+ template<typename... Args>
+ int multiply(Args... args)
+ {
+ return (args * ... * 1);
+ }
+
+ template<typename... Args>
+ bool all(Args... args)
+ {
+ return (args && ...);
+ }
+
+ }
+
+ namespace test_extended_static_assert
+ {
+
+ static_assert (true);
+
+ }
+
+ namespace test_auto_brace_init_list
+ {
+
+ auto foo = {5};
+ auto bar {5};
+
+ static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
+ static_assert(std::is_same<int, decltype(bar)>::value);
+ }
+
+ namespace test_typename_in_template_template_parameter
+ {
+
+ template<template<typename> typename X> struct D;
+
+ }
+
+ namespace test_fallthrough_nodiscard_maybe_unused_attributes
+ {
+
+ int f1()
+ {
+ return 42;
+ }
+
+ [[nodiscard]] int f2()
+ {
+ [[maybe_unused]] auto unused = f1();
+
+ switch (f1())
+ {
+ case 17:
+ f1();
+ [[fallthrough]];
+ case 42:
+ f1();
+ }
+ return f1();
+ }
+
+ }
+
+ namespace test_extended_aggregate_initialization
+ {
+
+ struct base1
+ {
+ int b1, b2 = 42;
+ };
+
+ struct base2
+ {
+ base2() {
+ b3 = 42;
+ }
+ int b3;
+ };
+
+ struct derived : base1, base2
+ {
+ int d;
+ };
+
+ derived d1 {{1, 2}, {}, 4}; // full initialization
+ derived d2 {{}, {}, 4}; // value-initialized bases
+
+ }
+
+ namespace test_general_range_based_for_loop
+ {
+
+ struct iter
+ {
+ int i;
+
+ int& operator* ()
+ {
+ return i;
+ }
+
+ const int& operator* () const
+ {
+ return i;
+ }
+
+ iter& operator++()
+ {
+ ++i;
+ return *this;
+ }
+ };
+
+ struct sentinel
+ {
+ int i;
+ };
+
+ bool operator== (const iter& i, const sentinel& s)
+ {
+ return i.i == s.i;
+ }
+
+ bool operator!= (const iter& i, const sentinel& s)
+ {
+ return !(i == s);
+ }
+
+ struct range
+ {
+ iter begin() const
+ {
+ return {0};
+ }
+
+ sentinel end() const
+ {
+ return {5};
+ }
+ };
+
+ void f()
+ {
+ range r {};
+
+ for (auto i : r)
+ {
+ [[maybe_unused]] auto v = i;
+ }
+ }
+
+ }
+
+ namespace test_lambda_capture_asterisk_this_by_value
+ {
+
+ struct t
+ {
+ int i;
+ int foo()
+ {
+ return [*this]()
+ {
+ return i;
+ }();
+ }
+ };
+
+ }
+
+ namespace test_enum_class_construction
+ {
+
+ enum class byte : unsigned char
+ {};
+
+ byte foo {42};
+
+ }
+
+ namespace test_constexpr_if
+ {
+
+ template <bool cond>
+ int f ()
+ {
+ if constexpr(cond)
+ {
+ return 13;
+ }
+ else
+ {
+ return 42;
+ }
+ }
+
+ }
+
+ namespace test_selection_statement_with_initializer
+ {
+
+ int f()
+ {
+ return 13;
+ }
+
+ int f2()
+ {
+ if (auto i = f(); i > 0)
+ {
+ return 3;
+ }
+
+ switch (auto i = f(); i + 4)
+ {
+ case 17:
+ return 2;
+
+ default:
+ return 1;
+ }
+ }
+
+ }
+
+ namespace test_template_argument_deduction_for_class_templates
+ {
+
+ template <typename T1, typename T2>
+ struct pair
+ {
+ pair (T1 p1, T2 p2)
+ : m1 {p1},
+ m2 {p2}
+ {}
+
+ T1 m1;
+ T2 m2;
+ };
+
+ void f()
+ {
+ [[maybe_unused]] auto p = pair{13, 42u};
+ }
+
+ }
+
+ namespace test_non_type_auto_template_parameters
+ {
+
+ template <auto n>
+ struct B
+ {};
+
+ B<5> b1;
+ B<'a'> b2;
+
+ }
+
+ namespace test_structured_bindings
+ {
+
+ int arr[2] = { 1, 2 };
+ std::pair<int, int> pr = { 1, 2 };
+
+ auto f1() -> int(&)[2]
+ {
+ return arr;
+ }
+
+ auto f2() -> std::pair<int, int>&
+ {
+ return pr;
+ }
+
+ struct S
+ {
+ int x1 : 2;
+ volatile double y1;
+ };
+
+ S f3()
+ {
+ return {};
+ }
+
+ auto [ x1, y1 ] = f1();
+ auto& [ xr1, yr1 ] = f1();
+ auto [ x2, y2 ] = f2();
+ auto& [ xr2, yr2 ] = f2();
+ const auto [ x3, y3 ] = f3();
+
+ }
+
+ namespace test_exception_spec_type_system
+ {
+
+ struct Good {};
+ struct Bad {};
+
+ void g1() noexcept;
+ void g2();
+
+ template<typename T>
+ Bad
+ f(T*, T*);
+
+ template<typename T1, typename T2>
+ Good
+ f(T1*, T2*);
+
+ static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
+
+ }
+
+ namespace test_inline_variables
+ {
+
+ template<class T> void f(T)
+ {}
+
+ template<class T> inline T g(T)
+ {
+ return T{};
+ }
+
+ template<> inline void f<>(int)
+ {}
+
+ template<> int g<>(int)
+ {
+ return 5;
+ }
+
+ }
+
+} // namespace cxx17
+
+#endif // __cplusplus < 201703L
+
+]])
diff --git a/tools/depends/m4/xbmc_arch.m4 b/tools/depends/m4/xbmc_arch.m4
new file mode 100644
index 0000000..05b254d
--- /dev/null
+++ b/tools/depends/m4/xbmc_arch.m4
@@ -0,0 +1,84 @@
+AC_DEFUN([XBMC_SETUP_ARCH_DEFINES],[
+
+# build detection and setup - this is the native arch
+case $build in
+ i*86*-linux-gnu*|i*86*-*-linux-uclibc*)
+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX")
+ ;;
+ x86_64-*-linux-gnu*|x86_64-*-linux-uclibc*)
+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX")
+ ;;
+ i386-*-freebsd*)
+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_FREEBSD")
+ ;;
+ amd64-*-freebsd*)
+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_FREEBSD")
+ ;;
+ arm-apple-darwin*)
+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_DARWIN -DTARGET_DARWIN_OSX")
+ ;;
+ x86_64-apple-darwin*)
+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_DARWIN -DTARGET_DARWIN_OSX")
+ ;;
+ powerpc-*-linux-gnu*|powerpc-*-linux-uclibc*)
+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_POWERPC")
+ ;;
+ powerpc64-*-linux-gnu*|powerpc64-*-linux-uclibc*)
+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_POWERPC64")
+ ;;
+ arm*-*-linux-gnu*|arm*-*-linux-uclibc*|aarch64*-*-linux-gnu*|aarch64*-*-linux-uclibc*)
+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX")
+ ;;
+ *)
+ AC_MSG_ERROR(unsupported native build platform: $build)
+esac
+
+
+# host detection and setup - this is the target arch
+case $host in
+ i*86*-linux-gnu*|i*86*-*-linux-uclibc*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX")
+ ;;
+ x86_64-*-linux-gnu*|x86_64-*-linux-uclibc*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX")
+ ;;
+ i386-*-freebsd*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_FREEBSD")
+ ;;
+ amd64-*-freebsd*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_FREEBSD")
+ ;;
+ aarch64-apple-darwin*)
+ if test "$target_platform" = "macosx" ; then
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_DARWIN -DTARGET_DARWIN_OSX")
+ else
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_DARWIN -DTARGET_DARWIN_EMBEDDED")
+ fi
+ ;;
+ x86_64-apple-darwin*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_DARWIN -DTARGET_DARWIN_OSX")
+ ;;
+ powerpc-*-linux-gnu*|powerpc-*-linux-uclibc*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_POWERPC")
+ ;;
+ powerpc64*-*-linux-gnu*|powerpc64*-*-linux-uclibc*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_POWERPC64")
+ ;;
+ arm*-*-linux-gnu*|arm*-*-linux-uclibc*|aarch64*-*-linux-gnu*|aarch64*-*-linux-uclibc*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX")
+ ;;
+ mips*-*-linux-gnu*|mips*-*-linux-uclibc*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX")
+ ;;
+ *-*linux-android*)
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -DTARGET_ANDROID")
+ ;;
+ *)
+ AC_MSG_ERROR(unsupported build target: $host)
+esac
+
+if test "$target_platform" = "target_android" ; then
+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -DTARGET_ANDROID")
+fi
+
+])
diff --git a/tools/depends/native/JsonSchemaBuilder/CMakeLists.txt b/tools/depends/native/JsonSchemaBuilder/CMakeLists.txt
new file mode 100644
index 0000000..e1c6c21
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/CMakeLists.txt
@@ -0,0 +1,10 @@
+project(JsonSchemaBuilder)
+
+set(SOURCES src/JsonSchemaBuilder.cpp)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+add_executable(JsonSchemaBuilder ${SOURCES})
+
+install(TARGETS JsonSchemaBuilder DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
+ RENAME "${APP_NAME_LC}-JsonSchemaBuilder")
diff --git a/tools/depends/native/JsonSchemaBuilder/LICENSE.GPL b/tools/depends/native/JsonSchemaBuilder/LICENSE.GPL
new file mode 100644
index 0000000..c7e8863
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/LICENSE.GPL
@@ -0,0 +1,287 @@
+
+ You may use, distribute and copy JsonSchemaBuilder under the terms of GNU General
+ Public License version 2, which is displayed below.
+
+-------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+-------------------------------------------------------------------------
diff --git a/tools/depends/native/JsonSchemaBuilder/Makefile b/tools/depends/native/JsonSchemaBuilder/Makefile
new file mode 100644
index 0000000..78c4433
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/Makefile
@@ -0,0 +1,46 @@
+ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+-include ../../Makefile.include
+DEPS=Makefile
+
+ifeq ($(NATIVEPREFIX),)
+ PREFIX = $(ROOT_DIR)
+else
+ PREFIX = $(NATIVEPREFIX)
+endif
+
+ifeq ($(NATIVEPLATFORM),)
+ PLATFORM = native
+else
+ PLATFORM = $(NATIVEPLATFORM)
+ DEPS += ../../Makefile.include
+endif
+
+SOURCE=$(ROOT_DIR)/src
+
+CONFIGURE=./configure --prefix=$(PREFIX)
+APP=$(PLATFORM)/JsonSchemaBuilder
+APPBIN=$(PREFIX)/bin/JsonSchemaBuilder
+
+all: .installed-$(PLATFORM)
+
+$(PLATFORM): $(DEPS)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); cp -a $(SOURCE)/* .
+ cd $(PLATFORM); ./autogen.sh
+ cd $(PLATFORM); $(CONFIGURE)
+
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+ -rm -rf bin
diff --git a/tools/depends/native/JsonSchemaBuilder/README b/tools/depends/native/JsonSchemaBuilder/README
new file mode 100644
index 0000000..f6fcb8e
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/README
@@ -0,0 +1,5 @@
+JSON Schema Builder
+===================
+JSON Schema Builder is a tool used by XBMC to transform files containing JSON
+schema definitions of XBMC's JSON-RPC API into a C++ header file which can be
+parsed by XBMC's JSON-RPC implementation at runtime. \ No newline at end of file
diff --git a/tools/depends/native/JsonSchemaBuilder/src/JsonSchemaBuilder.cpp b/tools/depends/native/JsonSchemaBuilder/src/JsonSchemaBuilder.cpp
new file mode 100644
index 0000000..7f219bb
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/src/JsonSchemaBuilder.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2011 Tobias Arrskog
+ * https://github.com/topfs2/jsd_builder
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <fstream>
+#include <iostream>
+#include <regex>
+#include <string>
+
+void print_version(std::ifstream &in, std::ofstream &out)
+{
+ std::string line;
+ if (getline(in, line))
+ out << std::regex_replace(line, std::regex("(\\s+)?JSONRPC_VERSION\\s+|(\\s+)?#.*"), "");
+}
+
+void print_license(std::ifstream &in, std::ofstream &out)
+{
+ std::string line;
+
+ while (getline(in, line, '\n'))
+ out << line << std::endl;
+}
+
+void print_json(std::ifstream &in, std::ofstream &out)
+{
+ std::string line;
+ unsigned int count = 0;
+ bool closing = false;
+
+ while (getline(in, line, '\n'))
+ {
+ // No need to handle the last line
+ if (line == "}")
+ {
+ out << std::endl;
+ continue;
+ }
+
+ // If we just closed a whole object we need to print the separator
+ if (closing)
+ out << "," << std::endl;
+
+ out << " ";
+ bool started = false;
+ closing = false;
+ for (std::string::iterator itr = line.begin(); itr != line.end(); ++itr)
+ {
+ // Skip \r characters
+ if (*itr == '\r') {
+ break;
+ }
+
+ // Count opening { but ignore the first one
+ if (*itr == '{')
+ {
+ count++;
+ if (count == 1)
+ break;
+ }
+ // Replace tabs with 2 spaces
+ if (*itr == '\t')
+ {
+ out << " ";
+ continue;
+ }
+ // Count closing } but ignore the last one
+ if (*itr == '}')
+ {
+ count--;
+ if (count == 0)
+ break;
+
+ if (count == 1)
+ {
+ out << "\"}\"";
+ closing = true;
+ break;
+ }
+ }
+ // Only print a " before the first real sign
+ if (!started && *itr != ' ')
+ {
+ started = true;
+ out << '"';
+ }
+ // Add a backslash before a double-quote and backslashes
+ if (*itr == '"' || *itr == '\\')
+ out << '\\';
+ out << (*itr);
+ }
+ // Only print a closing " if there was real content on the line
+ if (started)
+ out << '"';
+
+ // Only print a newline if we haven't just closed a whole object
+ if (!closing)
+ out << std::endl;
+ }
+}
+
+void print_usage(const char *application)
+{
+ std::cout << application << " version.txt license.txt methods.json types.json notifications.json" << std::endl;
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc < 6)
+ {
+ print_usage(argv[0]);
+ return -1;
+ }
+
+ std::ofstream out ("ServiceDescription.h", std::ofstream::binary);
+
+ std::ifstream version(argv[1], std::ios_base::in);
+ std::ifstream license(argv[2], std::ios_base::in);
+ std::ifstream methods(argv[3], std::ios_base::in);
+ std::ifstream types(argv[4], std::ios_base::in);
+ std::ifstream notifications(argv[5], std::ios_base::in);
+
+ if (!(version && license && methods && types && notifications))
+ {
+ std::cout << "Failed to find one or more of version.txt, license.txt, methods.json, types.json or notifications.json" << std::endl;
+ return -1;
+ }
+
+ out << "#pragma once" << std::endl;
+
+ print_license(license, out);
+
+ out << std::endl;
+
+ out << "namespace JSONRPC" << std::endl;
+ out << "{" << std::endl;
+ out << " const char* const JSONRPC_SERVICE_ID = \"http://xbmc.org/jsonrpc/ServiceDescription.json\";" << std::endl;
+ out << " const char* const JSONRPC_SERVICE_VERSION = \""; print_version(version, out); out << "\";" << std::endl;
+ out << " const char* const JSONRPC_SERVICE_DESCRIPTION = \"JSON-RPC API of XBMC\";" << std::endl;
+ out << std::endl;
+
+ out << " const char* const JSONRPC_SERVICE_TYPES[] = {";
+ print_json(types, out);
+ out << " };" << std::endl;
+ out << std::endl;
+
+ out << " const char* const JSONRPC_SERVICE_METHODS[] = {";
+ print_json(methods, out);
+ out << " };" << std::endl;
+ out << std::endl;
+
+ out << " const char* const JSONRPC_SERVICE_NOTIFICATIONS[] = {";
+ print_json(notifications, out);
+ out << " };" << std::endl;
+
+ out << "}" << std::endl;
+
+ return 0;
+}
diff --git a/tools/depends/native/JsonSchemaBuilder/src/Makefile.am b/tools/depends/native/JsonSchemaBuilder/src/Makefile.am
new file mode 100644
index 0000000..99454a1
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/src/Makefile.am
@@ -0,0 +1,4 @@
+bin_PROGRAMS = JsonSchemaBuilder
+JsonSchemaBuilder_SOURCES = JsonSchemaBuilder.cpp
+AM_CXXFLAGS = -O2 -std=c++11
+
diff --git a/tools/depends/native/JsonSchemaBuilder/src/autogen.sh b/tools/depends/native/JsonSchemaBuilder/src/autogen.sh
new file mode 100755
index 0000000..872167c
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/src/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+autoreconf -vif
diff --git a/tools/depends/native/JsonSchemaBuilder/src/configure.ac b/tools/depends/native/JsonSchemaBuilder/src/configure.ac
new file mode 100644
index 0000000..54ebee2
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/src/configure.ac
@@ -0,0 +1,10 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(JsonSchemaBuilder, 1.0, me@mail.com)
+AC_CONFIG_AUX_DIR(config)
+AC_CONFIG_SRCDIR(JsonSchemaBuilder.cpp)
+
+AM_INIT_AUTOMAKE([foreign])
+
+AC_PROG_CXX
+
+AC_OUTPUT(Makefile)
diff --git a/tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.sln b/tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.sln
new file mode 100644
index 0000000..33a7195
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonSchemaBuilder", "JsonSchemaBuilder.vcxproj", "{6D4C9949-FF2B-4B14-83BB-D86AB27B855A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6D4C9949-FF2B-4B14-83BB-D86AB27B855A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6D4C9949-FF2B-4B14-83BB-D86AB27B855A}.Debug|Win32.Build.0 = Debug|Win32
+ {6D4C9949-FF2B-4B14-83BB-D86AB27B855A}.Release|Win32.ActiveCfg = Release|Win32
+ {6D4C9949-FF2B-4B14-83BB-D86AB27B855A}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.vcxproj b/tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.vcxproj
new file mode 100644
index 0000000..ab84c5c
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.vcxproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{6D4C9949-FF2B-4B14-83BB-D86AB27B855A}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>JsonSchemaBuilder</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\JsonSchemaBuilder.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.vcxproj.filters b/tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.vcxproj.filters
new file mode 100644
index 0000000..3c090a8
--- /dev/null
+++ b/tools/depends/native/JsonSchemaBuilder/win32/JsonSchemaBuilder.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="src">
+ <UniqueIdentifier>{7ce1989c-783c-4e53-bb32-8511e3adab08}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\JsonSchemaBuilder.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/tools/depends/native/Makefile b/tools/depends/native/Makefile
new file mode 100644
index 0000000..800270f
--- /dev/null
+++ b/tools/depends/native/Makefile
@@ -0,0 +1,105 @@
+include ../Makefile.include
+
+ifneq ($(shell test -f $(NATIVEPREFIX)/share/config.site && echo 1),1)
+ $(error Error: $(NATIVEPREFIX)/share/config.site is missing. Please reconfigure depends to generate it)
+endif
+
+# Keep in alphabetical order
+NATIVE= \
+ autoconf \
+ autoconf-archive \
+ automake \
+ cmake \
+ gas-preprocessor \
+ gettext \
+ giflib \
+ heimdal \
+ JsonSchemaBuilder \
+ libjpeg-turbo \
+ liblzo2 \
+ libpng \
+ libtool \
+ m4 \
+ meson \
+ nasm \
+ ninja \
+ openssl \
+ pcre \
+ perlmodule-parseyapp \
+ pkg-config \
+ python3 \
+ swig \
+ TexturePacker \
+ zlib
+
+ifneq ($(NATIVE_OS),osx)
+ NATIVE += libffi
+ LIBFFI = libffi
+endif
+
+ifeq ($(OS),darwin_embedded)
+ NATIVE += dpkg xz tar ldid
+endif
+
+ifeq ($(OS),linux)
+ NATIVE += expat wayland-scanner pugixml waylandpp-scanner
+ EXPAT = expat
+
+ ifeq ($(RENDER_SYSTEM),gles)
+ NATIVE += MarkupSafe Mako
+ endif
+endif
+
+.PHONY: $(NATIVE) native
+
+all: native
+ @echo "Dependencies built successfully."
+
+# Dependency layout for parallel builds
+autoconf-archive: autoconf
+autoconf: m4
+automake: autoconf
+dpkg: automake gettext libtool pkg-config tar
+heimdal: libtool
+JsonSchemaBuilder: automake
+libjpeg-turbo: cmake nasm
+libpng: zlib automake
+libtool: automake
+Mako: MarkupSafe
+meson: python3
+ninja: meson
+openssl: zlib
+pugixml: cmake
+python3: $(EXPAT) $(LIBFFI) pkg-config zlib openssl autoconf-archive
+swig: pcre
+tar: xz automake
+TexturePacker: automake pkg-config libpng liblzo2 giflib libjpeg-turbo
+wayland-scanner: expat pkg-config
+waylandpp-scanner: cmake pugixml
+
+# python installs are not thread safe when using easy_install method.
+# MarkupSafe doesn't really depend on ninja but we need to make the
+# build sequential
+MarkupSafe: ninja
+
+#liblzo2 has stale packaged automake files that cause borked host/build detection
+liblzo2: automake
+
+native: $(NATIVE)
+$(NATIVE):
+ $(MAKE) -C $@
+clean:
+ for d in $(NATIVE); do $(MAKE) -C $$d clean; done
+
+# Debug target, this will DELETE all data in staging!
+test-dependencies:
+ ( for d in $(NATIVE); do \
+ rm -rf $(NATIVEPREFIX); \
+ mkdir -p $(NATIVEPREFIX)/include $(NATIVEPREFIX)/share $(NATIVEPREFIX)/bin; \
+ cp -f config.site $(NATIVEPREFIX)/share/; \
+ $(MAKE) distclean; \
+ $(MAKE) $$d; done ) && echo "$@ built successfully"
+
+distclean::
+ for d in $(NATIVE); do $(MAKE) -C $$d distclean; done
+
diff --git a/tools/depends/native/Mako/Makefile b/tools/depends/native/Mako/Makefile
new file mode 100644
index 0000000..c31e462
--- /dev/null
+++ b/tools/depends/native/Mako/Makefile
@@ -0,0 +1,27 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=Mako
+VERSION=1.1.3
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=a9b94fa34a61e7794b6e4549fa0bada6ff84dfb0d9edb8d5c7f9b95d12184fa4499f42303cfee720b576a9f7e986a57d91ad3aeb26c9f93154dbc08fb2975952
+include ../../download-files.include
+
+all: .installed-$(PLATFORM)
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+
+.installed-$(PLATFORM): $(PLATFORM)
+ cd $(PLATFORM); $(PREFIX)/bin/python3 setup.py install --prefix=$(PREFIX)
+ touch $@
+
+clean:
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/MarkupSafe/Makefile b/tools/depends/native/MarkupSafe/Makefile
new file mode 100644
index 0000000..fa43727
--- /dev/null
+++ b/tools/depends/native/MarkupSafe/Makefile
@@ -0,0 +1,27 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=MarkupSafe
+VERSION=1.1.1
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=f3014e6131a3ab866914c5635b5397ef71906bffb1b6f8c5f2ed2acf167429ff7914236d38943e872683a57a9be9669f4c5aace6274f3307ab21ef25373db0b6
+include ../../download-files.include
+
+all: .installed-$(PLATFORM)
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+
+.installed-$(PLATFORM): $(PLATFORM)
+ cd $(PLATFORM); $(PREFIX)/bin/python3 setup.py install --prefix=$(PREFIX)
+ touch $@
+
+clean:
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/TexturePacker/CMakeLists.txt b/tools/depends/native/TexturePacker/CMakeLists.txt
new file mode 100644
index 0000000..97dc1d3
--- /dev/null
+++ b/tools/depends/native/TexturePacker/CMakeLists.txt
@@ -0,0 +1,54 @@
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
+
+if(APPLE)
+ set(CMAKE_FIND_ROOT_PATH ${NATIVEPREFIX})
+endif()
+
+find_package(Lzo2 REQUIRED)
+find_package(PNG REQUIRED)
+find_package(GIF REQUIRED)
+find_package(JPEG REQUIRED)
+
+if(GIF_VERSION LESS 4)
+ message(FATAL_ERROR "giflib < 4 not supported")
+else()
+ file(STRINGS ${GIF_INCLUDE_DIR}/gif_lib.h GIFSTRINGS)
+ string(REGEX MATCH "GIFLIB_MAJOR ([0-9])" GIFLIB_MAJOR ${GIFSTRINGS})
+ if(GIFLIB_MAJOR)
+ string(REPLACE " " ";" GIFLIB_MAJOR ${GIFLIB_MAJOR})
+ list(GET GIFLIB_MAJOR 1 GIFLIB_MAJOR)
+ else()
+ set(GIFLIB_MAJOR ${GIF_VERSION})
+ endif()
+ if(NOT GIFLIB_MAJOR OR GIFLIB_MAJOR LESS 5)
+ message(WARNING "giflib${GIFLIB_MAJOR} support is experimental. Consider updating to giflib5")
+ endif()
+endif()
+
+set(SOURCES src/md5.cpp
+ src/DecoderManager.cpp
+ src/TexturePacker.cpp
+ src/XBTFWriter.cpp
+ src/decoder/GIFDecoder.cpp
+ src/decoder/GifHelper.cpp
+ src/decoder/JPGDecoder.cpp
+ src/decoder/PNGDecoder.cpp
+ ${CMAKE_SOURCE_DIR}/xbmc/guilib/XBTF.cpp)
+
+set(CMAKE_POSITITION_INDEPENDENT_CODE 1)
+
+add_executable(TexturePacker ${SOURCES})
+target_include_directories(TexturePacker
+ PRIVATE ${PNG_INCLUDE_DIRS}
+ ${JPEG_INCLUDE_DIR}
+ ${GIF_INCLUDE_DIR}
+ ${CMAKE_SOURCE_DIR}/xbmc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/decoder)
+target_link_libraries(TexturePacker
+ PRIVATE ${SYSTEM_LDFLAGS}
+ ${GIF_LIBRARIES}
+ ${PNG_LIBRARIES}
+ ${JPEG_LIBRARIES}
+ ${LZO2_LIBRARIES})
+target_compile_options(TexturePacker PRIVATE ${ARCH_DEFINES} ${SYSTEM_DEFINES})
diff --git a/tools/depends/native/TexturePacker/Makefile b/tools/depends/native/TexturePacker/Makefile
new file mode 100644
index 0000000..f50dc87
--- /dev/null
+++ b/tools/depends/native/TexturePacker/Makefile
@@ -0,0 +1,62 @@
+ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+-include ../../Makefile.include
+DEPS=Makefile
+
+ifeq ($(NATIVEPREFIX),)
+ PREFIX = $(ROOT_DIR)
+else
+ PREFIX = $(NATIVEPREFIX)
+endif
+
+ifeq ($(NATIVEPLATFORM),)
+ PLATFORM = native
+ EXTRA_CONFIGURE = --enable-static
+else
+ PLATFORM = $(NATIVEPLATFORM)
+ DEPS += ../../Makefile.include
+endif
+
+ifeq ($(NATIVE_OS), linux)
+ EXTRA_CONFIGURE = --enable-static
+endif
+ifeq ($(NATIVE_OS), android)
+ EXTRA_CONFIGURE = --enable-static
+endif
+
+ifeq ($(CMAKE_SOURCE_DIR),)
+ CMAKE_SOURCE_DIR = $(ROOT_DIR)/../../../..
+endif
+
+SOURCE=$(ROOT_DIR)/src
+
+APP=$(PLATFORM)/TexturePacker
+APPBIN=$(PREFIX)/bin/TexturePacker
+
+all: .installed-$(PLATFORM)
+
+$(PLATFORM): $(DEPS)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); cp -a $(SOURCE)/* .
+ cd $(PLATFORM); ./autogen.sh
+ cd $(PLATFORM); ./configure --prefix=$(PREFIX) $(EXTRA_CONFIGURE) EXTRA_DEFINES="$(NATIVE_ARCH_DEFINES)"
+
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+ #TEMP workaround for skins: create legacy link. Remove me when skins are fixed
+ @mkdir -p $(CMAKE_SOURCE_DIR)/tools/TexturePacker
+ @[ -f $(CMAKE_SOURCE_DIR)/tools/TexturePacker/TexturePacker ] && rm $(CMAKE_SOURCE_DIR)/tools/TexturePacker/TexturePacker || :
+ @ln -sf $(APPBIN) $(CMAKE_SOURCE_DIR)/tools/TexturePacker/TexturePacker
+ @echo "all:" > $(CMAKE_SOURCE_DIR)/tools/TexturePacker/Makefile
+ @echo "\t@echo "WARNING: use of tools/TexturePacker/TexturePacker is deprecated, please update your skins Makefile"" >> $(CMAKE_SOURCE_DIR)/tools/TexturePacker/Makefile
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+ -rm -rf bin
diff --git a/tools/depends/native/TexturePacker/src/DecoderManager.cpp b/tools/depends/native/TexturePacker/src/DecoderManager.cpp
new file mode 100644
index 0000000..8f6a904
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/DecoderManager.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <cstdio>
+#include "DecoderManager.h"
+
+bool DecoderManager::verbose;
+std::vector<IDecoder *> DecoderManager::m_decoders;
+
+// ADD new decoders here
+// include decoders
+#include "PNGDecoder.h"
+#include "JPGDecoder.h"
+#include "GIFDecoder.h"
+
+void DecoderManager::InstantiateDecoders()
+{
+ m_decoders.push_back(new PNGDecoder());
+ m_decoders.push_back(new JPGDecoder());
+ m_decoders.push_back(new GIFDecoder());
+}
+
+void DecoderManager::FreeDecoders()
+{
+ for (unsigned int i = 0; i < m_decoders.size(); i++)
+ {
+ delete m_decoders[i];
+ }
+ m_decoders.clear();
+}
+
+// returns true for png, bmp, tga, jpg and dds files, otherwise returns false
+bool DecoderManager::IsSupportedGraphicsFile(char *strFileName)
+{
+ std::string filename = strFileName;
+ if (filename.length() < 4)
+ return false;
+
+ for (unsigned int i = 0; i < m_decoders.size(); i++)
+ {
+ const std::vector<std::string> extensions = m_decoders[i]->GetSupportedExtensions();
+ for (unsigned int n = 0; n < extensions.size(); n++)
+ {
+ int extLen = extensions[n].length();
+ if (std::string::npos != filename.rfind(extensions[n].c_str(), filename.length() - extLen, extLen))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool DecoderManager::LoadFile(const std::string &filename, DecodedFrames &frames)
+{
+ for (unsigned int i = 0; i < m_decoders.size(); i++)
+ {
+ if (m_decoders[i]->CanDecode(filename))
+ {
+ if (verbose)
+ fprintf(stdout, "This is a %s - lets load it via %s...\n",
+ m_decoders[i]->GetImageFormatName(), m_decoders[i]->GetDecoderName());
+ return m_decoders[i]->LoadFile(filename, frames);
+ }
+ }
+ return false;
+}
+
+void DecoderManager::FreeDecodedFrames(DecodedFrames &frames)
+{
+ frames.clear();
+}
diff --git a/tools/depends/native/TexturePacker/src/DecoderManager.h b/tools/depends/native/TexturePacker/src/DecoderManager.h
new file mode 100644
index 0000000..2c59aa2
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/DecoderManager.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "IDecoder.h"
+
+class DecoderManager
+{
+ public:
+ static void InstantiateDecoders();
+ static void FreeDecoders();
+ static bool IsSupportedGraphicsFile(char *strFileName);
+ static bool LoadFile(const std::string &filename, DecodedFrames &frames);
+ static void FreeDecodedFrames(DecodedFrames &frames);
+ static bool verbose;
+
+ private:
+ static std::vector<IDecoder *> m_decoders;
+};
diff --git a/tools/depends/native/TexturePacker/src/Makefile.am b/tools/depends/native/TexturePacker/src/Makefile.am
new file mode 100644
index 0000000..d6b676f
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Makefile.am
@@ -0,0 +1,29 @@
+AUTOMAKE_OPTIONS = subdir-objects
+
+AM_CFLAGS = -DTARGET_POSIX
+AM_CFLAGS += @EXTRA_DEFINES@
+AM_CXXFLAGS = $(AM_CFLAGS) -std=c++0x
+
+AM_CPPFLAGS = \
+ -I. \
+ -I./decoder \
+ -I@KODI_SRC_DIR@/xbmc \
+ -I@KODI_SRC_DIR@/xbmc/guilib \
+ @CPPFLAGS@
+
+AM_LDFLAGS = @LIBS@ @STATIC_FLAG@
+
+
+bin_PROGRAMS = TexturePacker
+TexturePacker_SOURCES = md5.cpp \
+ XBTFWriter.cpp \
+ TexturePacker.cpp \
+ DecoderManager.cpp \
+ decoder/PNGDecoder.cpp \
+ decoder/JPGDecoder.cpp \
+ decoder/GifHelper.cpp \
+ decoder/GIFDecoder.cpp \
+ XBTF.cpp
+
+XBTF.cpp:
+ @cp @KODI_SRC_DIR@/xbmc/guilib/XBTF.cpp .
diff --git a/tools/depends/native/TexturePacker/src/SimpleFS.h b/tools/depends/native/TexturePacker/src/SimpleFS.h
new file mode 100644
index 0000000..69d3342
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/SimpleFS.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <cstdio>
+#include <string>
+
+class CFile
+{
+public:
+ CFile()
+ {
+ m_file = NULL;
+ }
+
+ ~CFile()
+ {
+ Close();
+ }
+
+ bool Open(const std::string &file)
+ {
+ Close();
+ m_file = fopen(file.c_str(), "rb");
+ return NULL != m_file;
+ }
+
+ bool OpenForWrite(const std::string &file, bool overwrite)
+ {
+ Close();
+ m_file = fopen(file.c_str(), "wb");
+ return NULL != m_file;
+ }
+ void Close()
+ {
+ if (m_file)
+ fclose(m_file);
+ m_file = NULL;
+ }
+
+ uint64_t Read(void *data, uint64_t size)
+ {
+ if (fread(data, (size_t)size, 1, m_file) == 1)
+ return size;
+ return 0;
+ }
+
+ uint64_t Write(const void *data, uint64_t size)
+ {
+ if (fwrite(data, (size_t)size, 1, m_file) == 1)
+ return size;
+ return 0;
+ }
+
+ FILE *getFP()
+ {
+ return m_file;
+ }
+
+ uint64_t GetFileSize()
+ {
+ long curPos = ftell(m_file);
+ uint64_t fileSize = 0;
+ if (fseek(m_file, 0, SEEK_END) == 0)
+ {
+ long size = ftell(m_file);
+ if (size >= 0)
+ fileSize = (uint64_t)size;
+ }
+
+ // restore fileptr
+ Seek(curPos);
+
+ return fileSize;
+ }
+
+ uint64_t Seek(uint64_t offset)
+ {
+ uint64_t seekedBytes = 0;
+ int seekRet = fseek(m_file, offset, SEEK_SET);
+ if (seekRet == 0)
+ seekedBytes = offset;
+ return seekedBytes;
+ }
+
+private:
+ FILE* m_file;
+};
diff --git a/tools/depends/native/TexturePacker/src/TexturePacker.cpp b/tools/depends/native/TexturePacker/src/TexturePacker.cpp
new file mode 100644
index 0000000..a6fd428
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/TexturePacker.cpp
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2005-2014 Team XBMC
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef TARGET_WINDOWS
+#include <sys/types.h>
+#define __STDC_FORMAT_MACROS
+#include <cinttypes>
+#define platform_stricmp _stricmp
+#else
+#include <inttypes.h>
+#define platform_stricmp strcasecmp
+#endif
+#include <cerrno>
+#include <dirent.h>
+#include <map>
+
+#include "guilib/XBTF.h"
+#include "guilib/XBTFReader.h"
+
+#include "DecoderManager.h"
+
+#include "XBTFWriter.h"
+#include "md5.h"
+#include "cmdlineargs.h"
+
+#ifdef TARGET_WINDOWS
+#define strncasecmp _strnicmp
+#endif
+
+#include <lzo/lzo1x.h>
+#include <sys/stat.h>
+
+#define FLAGS_USE_LZO 1
+
+#define DIR_SEPARATOR '/'
+
+const char *GetFormatString(unsigned int format)
+{
+ switch (format)
+ {
+ case XB_FMT_DXT1:
+ return "DXT1 ";
+ case XB_FMT_DXT3:
+ return "DXT3 ";
+ case XB_FMT_DXT5:
+ return "DXT5 ";
+ case XB_FMT_DXT5_YCoCg:
+ return "YCoCg";
+ case XB_FMT_A8R8G8B8:
+ return "ARGB ";
+ case XB_FMT_A8:
+ return "A8 ";
+ default:
+ return "?????";
+ }
+}
+
+void CreateSkeletonHeaderImpl(CXBTFWriter& xbtfWriter,
+ const std::string& fullPath,
+ const std::string& relativePath)
+{
+ struct dirent* dp;
+ struct stat stat_p;
+ DIR *dirp = opendir(fullPath.c_str());
+
+ if (dirp)
+ {
+ for (errno = 0; (dp = readdir(dirp)); errno = 0)
+ {
+ if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+ {
+ continue;
+ }
+
+ //stat to check for dir type (reiserfs fix)
+ std::string fileN = fullPath + "/" + dp->d_name;
+ if (stat(fileN.c_str(), &stat_p) == 0)
+ {
+ if (dp->d_type == DT_DIR || stat_p.st_mode & S_IFDIR)
+ {
+ std::string tmpPath = relativePath;
+ if (tmpPath.size() > 0)
+ {
+ tmpPath += "/";
+ }
+
+ CreateSkeletonHeaderImpl(xbtfWriter, fullPath + DIR_SEPARATOR + dp->d_name, tmpPath + dp->d_name);
+ }
+ else if (DecoderManager::IsSupportedGraphicsFile(dp->d_name))
+ {
+ std::string fileName = "";
+ if (relativePath.size() > 0)
+ {
+ fileName += relativePath;
+ fileName += "/";
+ }
+
+ fileName += dp->d_name;
+
+ CXBTFFile file;
+ file.SetPath(fileName);
+ xbtfWriter.AddFile(file);
+ }
+ }
+ }
+ if (errno)
+ fprintf(stderr, "Error reading directory %s (%s)\n", fullPath.c_str(), strerror(errno));
+
+ closedir(dirp);
+ }
+ else
+ {
+ fprintf(stderr, "Error opening %s (%s)\n", fullPath.c_str(), strerror(errno));
+ }
+}
+
+void CreateSkeletonHeader(CXBTFWriter& xbtfWriter, const std::string& fullPath)
+{
+ std::string temp;
+ CreateSkeletonHeaderImpl(xbtfWriter, fullPath, temp);
+}
+
+CXBTFFrame appendContent(CXBTFWriter &writer, int width, int height, unsigned char *data, unsigned int size, unsigned int format, bool hasAlpha, unsigned int flags)
+{
+ CXBTFFrame frame;
+ lzo_uint packedSize = size;
+
+ if ((flags & FLAGS_USE_LZO) == FLAGS_USE_LZO)
+ {
+ // grab a temporary buffer for unpacking into
+ packedSize = size + size / 16 + 64 + 3; // see simple.c in lzo
+ unsigned char *packed = new unsigned char[packedSize];
+ unsigned char *working = new unsigned char[LZO1X_999_MEM_COMPRESS];
+ if (packed && working)
+ {
+ if (lzo1x_999_compress(data, size, packed, &packedSize, working) != LZO_E_OK || packedSize > size)
+ {
+ // compression failed, or compressed size is bigger than uncompressed, so store as uncompressed
+ packedSize = size;
+ writer.AppendContent(data, size);
+ }
+ else
+ { // success
+ lzo_uint optimSize = size;
+ if (lzo1x_optimize(packed, packedSize, data, &optimSize, NULL) != LZO_E_OK || optimSize != size)
+ { //optimisation failed
+ packedSize = size;
+ writer.AppendContent(data, size);
+ }
+ else
+ { // success
+ writer.AppendContent(packed, packedSize);
+ }
+ }
+ delete[] working;
+ delete[] packed;
+ }
+ }
+ else
+ {
+ writer.AppendContent(data, size);
+ }
+ frame.SetPackedSize(packedSize);
+ frame.SetUnpackedSize(size);
+ frame.SetWidth(width);
+ frame.SetHeight(height);
+ frame.SetFormat(hasAlpha ? format : format | XB_FMT_OPAQUE);
+ frame.SetDuration(0);
+ return frame;
+}
+
+bool HasAlpha(unsigned char *argb, unsigned int width, unsigned int height)
+{
+ unsigned char *p = argb + 3; // offset of alpha
+ for (unsigned int i = 0; i < 4*width*height; i += 4)
+ {
+ if (p[i] != 0xff)
+ return true;
+ }
+ return false;
+}
+
+CXBTFFrame createXBTFFrame(RGBAImage &image, CXBTFWriter& writer, double maxMSE, unsigned int flags)
+{
+
+ int width, height;
+ unsigned int format = 0;
+ unsigned char* argb = (unsigned char*)image.pixels;
+
+ width = image.width;
+ height = image.height;
+ bool hasAlpha = HasAlpha(argb, width, height);
+
+ CXBTFFrame frame;
+ format = XB_FMT_A8R8G8B8;
+ frame = appendContent(writer, width, height, argb, (width * height * 4), format, hasAlpha, flags);
+
+ return frame;
+}
+
+void Usage()
+{
+ puts("Usage:");
+ puts(" -help Show this screen.");
+ puts(" -input <dir> Input directory. Default: current dir");
+ puts(" -output <dir> Output directory/filename. Default: Textures.xbt");
+ puts(" -dupecheck Enable duplicate file detection. Reduces output file size. Default: off");
+}
+
+static bool checkDupe(struct MD5Context* ctx,
+ std::map<std::string, unsigned int>& hashes,
+ std::vector<unsigned int>& dupes, unsigned int pos)
+{
+ unsigned char digest[17];
+ MD5Final(digest,ctx);
+ digest[16] = 0;
+ char hex[33];
+ sprintf(hex, "%02X%02X%02X%02X%02X%02X%02X%02X"\
+ "%02X%02X%02X%02X%02X%02X%02X%02X", digest[0], digest[1], digest[2],
+ digest[3], digest[4], digest[5], digest[6], digest[7], digest[8],
+ digest[9], digest[10], digest[11], digest[12], digest[13], digest[14],
+ digest[15]);
+ hex[32] = 0;
+ std::map<std::string, unsigned int>::iterator it = hashes.find(hex);
+ if (it != hashes.end())
+ {
+ dupes[pos] = it->second;
+ return true;
+ }
+
+ hashes.insert(std::make_pair(hex,pos));
+ dupes[pos] = pos;
+
+ return false;
+}
+
+int createBundle(const std::string& InputDir, const std::string& OutputFile, double maxMSE, unsigned int flags, bool dupecheck)
+{
+ CXBTFWriter writer(OutputFile);
+ if (!writer.Create())
+ {
+ fprintf(stderr, "Error creating file\n");
+ return 1;
+ }
+
+ std::map<std::string, unsigned int> hashes;
+ std::vector<unsigned int> dupes;
+ CreateSkeletonHeader(writer, InputDir);
+
+ std::vector<CXBTFFile> files = writer.GetFiles();
+ dupes.resize(files.size());
+ if (!dupecheck)
+ {
+ for (unsigned int i=0;i<dupes.size();++i)
+ dupes[i] = i;
+ }
+
+ for (size_t i = 0; i < files.size(); i++)
+ {
+ struct MD5Context ctx;
+ MD5Init(&ctx);
+ CXBTFFile& file = files[i];
+
+ std::string fullPath = InputDir;
+ fullPath += file.GetPath();
+
+ std::string output = file.GetPath();
+ output = output.substr(0, 40);
+ while (output.size() < 46)
+ output += ' ';
+
+ DecodedFrames frames;
+ bool loaded = DecoderManager::LoadFile(fullPath, frames);
+
+ if (!loaded)
+ {
+ fprintf(stderr, "...unable to load image %s\n", file.GetPath().c_str());
+ continue;
+ }
+
+ printf("%s\n", output.c_str());
+ bool skip=false;
+ if (dupecheck)
+ {
+ for (unsigned int j = 0; j < frames.frameList.size(); j++)
+ MD5Update(&ctx,
+ (const uint8_t*)frames.frameList[j].rgbaImage.pixels,
+ frames.frameList[j].rgbaImage.height * frames.frameList[j].rgbaImage.pitch);
+
+ if (checkDupe(&ctx,hashes,dupes,i))
+ {
+ printf("**** duplicate of %s\n", files[dupes[i]].GetPath().c_str());
+ file.GetFrames().insert(file.GetFrames().end(),
+ files[dupes[i]].GetFrames().begin(),
+ files[dupes[i]].GetFrames().end());
+ skip = true;
+ }
+ }
+
+ if (!skip)
+ {
+ for (unsigned int j = 0; j < frames.frameList.size(); j++)
+ {
+ printf(" frame %4i (delay:%4i) ", j, frames.frameList[j].delay);
+ CXBTFFrame frame = createXBTFFrame(frames.frameList[j].rgbaImage, writer, maxMSE, flags);
+ frame.SetDuration(frames.frameList[j].delay);
+ file.GetFrames().push_back(frame);
+ printf("%s%c (%d,%d @ %" PRIu64 " bytes)\n", GetFormatString(frame.GetFormat()), frame.HasAlpha() ? ' ' : '*',
+ frame.GetWidth(), frame.GetHeight(), frame.GetUnpackedSize());
+ }
+ }
+ DecoderManager::FreeDecodedFrames(frames);
+ file.SetLoop(0);
+
+ writer.UpdateFile(file);
+ }
+
+ if (!writer.UpdateHeader(dupes))
+ {
+ fprintf(stderr, "Error writing header to file\n");
+ return 1;
+ }
+
+ if (!writer.Close())
+ {
+ fprintf(stderr, "Error closing file\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ if (lzo_init() != LZO_E_OK)
+ return 1;
+ bool valid = false;
+ unsigned int flags = 0;
+ bool dupecheck = false;
+ CmdLineArgs args(argc, (const char**)argv);
+
+ // setup some defaults, lzo packing,
+ flags = FLAGS_USE_LZO;
+
+ if (args.size() == 1)
+ {
+ Usage();
+ return 1;
+ }
+
+ std::string InputDir;
+ std::string OutputFilename = "Textures.xbt";
+
+ for (unsigned int i = 1; i < args.size(); ++i)
+ {
+ if (!platform_stricmp(args[i], "-help") || !platform_stricmp(args[i], "-h") || !platform_stricmp(args[i], "-?"))
+ {
+ Usage();
+ return 1;
+ }
+ else if (!platform_stricmp(args[i], "-input") || !platform_stricmp(args[i], "-i"))
+ {
+ InputDir = args[++i];
+ valid = true;
+ }
+ else if (!strcmp(args[i], "-dupecheck"))
+ {
+ dupecheck = true;
+ }
+ else if (!strcmp(args[i], "-verbose"))
+ {
+ DecoderManager::verbose = true;
+ }
+ else if (!platform_stricmp(args[i], "-output") || !platform_stricmp(args[i], "-o"))
+ {
+ OutputFilename = args[++i];
+ valid = true;
+#ifdef TARGET_POSIX
+ char *c = NULL;
+ while ((c = (char *)strchr(OutputFilename.c_str(), '\\')) != NULL) *c = '/';
+#endif
+ }
+ else
+ {
+ fprintf(stderr, "Unrecognized command line flag: %s\n", args[i]);
+ }
+ }
+
+ if (!valid)
+ {
+ Usage();
+ return 1;
+ }
+
+ size_t pos = InputDir.find_last_of(DIR_SEPARATOR);
+ if (pos != InputDir.length() - 1)
+ InputDir += DIR_SEPARATOR;
+
+ double maxMSE = 1.5; // HQ only please
+ DecoderManager::InstantiateDecoders();
+ createBundle(InputDir, OutputFilename, maxMSE, flags, dupecheck);
+ DecoderManager::FreeDecoders();
+}
diff --git a/tools/depends/native/TexturePacker/src/Win32/TexturePacker.sln b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.sln
new file mode 100644
index 0000000..07cd920
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.30723.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TexturePacker", "TexturePacker.vcxproj", "{57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Debug|Win32.Build.0 = Debug|Win32
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Release|Win32.ActiveCfg = Release|Win32
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj
new file mode 100644
index 0000000..8f540ed
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}</ProjectGuid>
+ <RootNamespace>TexturePacker</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>NotSet</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>NotSet</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\..\..\..\project\BuildDependencies\include</IncludePath>
+ <LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;..\..\..\..\..\..\project\BuildDependencies\lib</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\..\..\..\project\BuildDependencies\include</IncludePath>
+ <LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;..\..\..\..\..\..\project\BuildDependencies\lib</LibraryPath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..;..\decoder;..\..\..\..\..\..\xbmc;..\..\..\..\..\..\project\BuildDependencies\win32\include</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;TARGET_WINDOWS;_ITERATOR_DEBUG_LEVEL=0;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>jpeg-staticd.lib;libpng16_staticd.lib;gifd.lib;zlibstaticd.lib;lzo2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <IgnoreSpecificDefaultLibraries>libcmtd.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>..\..\..\..\..\..\project\BuildDependencies\win32\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>.;..;..\decoder;..\..\..\..\..\..\xbmc;..\..\..\..\..\..\project\BuildDependencies\win32\include</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;TARGET_WINDOWS;_ITERATOR_DEBUG_LEVEL=0;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>jpeg-static.lib;libpng16_static.lib;gif.lib;zlibstatic.lib;lzo2.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <IgnoreSpecificDefaultLibraries>libc.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>..\..\..\..\..\..\project\BuildDependencies\win32\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\DecoderManager.cpp" />
+ <ClCompile Include="..\decoder\GIFDecoder.cpp" />
+ <ClCompile Include="..\decoder\GifHelper.cpp" />
+ <ClCompile Include="..\decoder\JPGDecoder.cpp" />
+ <ClCompile Include="..\decoder\PNGDecoder.cpp" />
+ <ClCompile Include="..\md5.cpp" />
+ <ClCompile Include="..\TexturePacker.cpp" />
+ <ClCompile Include="dirent.c" />
+ <ClCompile Include="..\..\..\..\..\..\xbmc\guilib\XBTF.cpp" />
+ <ClCompile Include="..\XBTFWriter.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\cmdlineargs.h" />
+ <ClInclude Include="..\DecoderManager.h" />
+ <ClInclude Include="..\decoder\GIFDecoder.h" />
+ <ClInclude Include="..\decoder\GifHelper.h" />
+ <ClInclude Include="..\decoder\IDecoder.h" />
+ <ClInclude Include="..\decoder\JPGDecoder.h" />
+ <ClInclude Include="..\decoder\PNGDecoder.h" />
+ <ClInclude Include="..\rgbaimage.h" />
+ <ClInclude Include="dirent.h" />
+ <ClInclude Include="..\md5.h" />
+ <ClInclude Include="..\..\..\..\..\..\xbmc\guilib\XBTF.h" />
+ <ClInclude Include="..\XBTFWriter.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="version.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj.filters b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj.filters
new file mode 100644
index 0000000..f045d9c
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj.filters
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ <Filter Include="decoder">
+ <UniqueIdentifier>{c79bff3f-9118-4c2d-bc31-68b25f7dfbba}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="dirent.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\..\..\xbmc\guilib\XBTF.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\XBTFWriter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\md5.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\decoder\GIFDecoder.cpp">
+ <Filter>decoder</Filter>
+ </ClCompile>
+ <ClCompile Include="..\decoder\GifHelper.cpp">
+ <Filter>decoder</Filter>
+ </ClCompile>
+ <ClCompile Include="..\decoder\JPGDecoder.cpp">
+ <Filter>decoder</Filter>
+ </ClCompile>
+ <ClCompile Include="..\decoder\PNGDecoder.cpp">
+ <Filter>decoder</Filter>
+ </ClCompile>
+ <ClCompile Include="..\TexturePacker.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\DecoderManager.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\cmdlineargs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="dirent.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\md5.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\..\..\xbmc\guilib\XBTF.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\XBTFWriter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\rgbaimage.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\GIFDecoder.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\GifHelper.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\IDecoder.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\JPGDecoder.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\PNGDecoder.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\DecoderManager.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/tools/depends/native/TexturePacker/src/Win32/dirent.c b/tools/depends/native/TexturePacker/src/Win32/dirent.c
new file mode 100644
index 0000000..7598516
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/dirent.c
@@ -0,0 +1,145 @@
+/*
+
+ Implementation of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003 and July 2012.
+
+ Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dirent.h>
+#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
+
+struct DIR
+{
+ handle_type handle; /* -1 for failed rewind */
+ struct _finddata_t info;
+ struct dirent result; /* d_name null iff first time */
+ char *name; /* null-terminated char string */
+};
+
+DIR *opendir(const char *name)
+{
+ DIR *dir = 0;
+
+ if(name && name[0])
+ {
+ size_t base_length = strlen(name);
+ const char *all = /* search pattern must end with suitable wildcard */
+ strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+ if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
+ (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
+ {
+ strcat(strcpy(dir->name, name), all);
+
+ if ((dir->handle = (handle_type)_findfirst(dir->name, &dir->info)) != -1)
+ {
+ dir->result.d_name = 0;
+ dir->result.d_type = 0;
+ }
+ else /* rollback */
+ {
+ free(dir->name);
+ free(dir);
+ dir = 0;
+ }
+ }
+ else /* rollback */
+ {
+ free(dir);
+ dir = 0;
+ errno = ENOMEM;
+ }
+ }
+ else
+ {
+ errno = EINVAL;
+ }
+
+ return dir;
+}
+
+int closedir(DIR *dir)
+{
+ int result = -1;
+
+ if(dir)
+ {
+ if(dir->handle != -1)
+ {
+ result = _findclose(dir->handle);
+ }
+
+ free(dir->name);
+ free(dir);
+ }
+
+ if(result == -1) /* map all errors to EBADF */
+ {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ struct dirent *result = 0;
+
+ if(dir && dir->handle != -1)
+ {
+ if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
+ {
+ result = &dir->result;
+ result->d_name = dir->info.name;
+ result->d_type = (dir->info.attrib == _A_SUBDIR) ? DT_DIR : DT_UNKNOWN;
+ }
+ }
+ else
+ {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+void rewinddir(DIR *dir)
+{
+ if(dir && dir->handle != -1)
+ {
+ _findclose(dir->handle);
+ dir->handle = (handle_type)_findfirst(dir->name, &dir->info);
+ dir->result.d_name = 0;
+ dir->result.d_type = 0;
+ }
+ else
+ {
+ errno = EBADF;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tools/depends/native/TexturePacker/src/Win32/dirent.h b/tools/depends/native/TexturePacker/src/Win32/dirent.h
new file mode 100644
index 0000000..e57b250
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/dirent.h
@@ -0,0 +1,53 @@
+/*
+
+ Declaration of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003.
+
+ Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+*/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct DIR DIR;
+
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+struct dirent
+{
+ char *d_name;
+ unsigned char d_type;
+};
+
+DIR *opendir(const char *);
+int closedir(DIR *);
+struct dirent *readdir(DIR *);
+void rewinddir(DIR *);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/depends/native/TexturePacker/src/Win32/version.rc b/tools/depends/native/TexturePacker/src/Win32/version.rc
new file mode 100644
index 0000000..7ccb57f
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/version.rc
Binary files differ
diff --git a/tools/depends/native/TexturePacker/src/XBTFWriter.cpp b/tools/depends/native/TexturePacker/src/XBTFWriter.cpp
new file mode 100644
index 0000000..1607db1
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/XBTFWriter.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#define __STDC_FORMAT_MACROS
+#include <cinttypes>
+#if defined(TARGET_FREEBSD) || defined(TARGET_DARWIN)
+#include <cstdlib>
+#elif !defined(TARGET_DARWIN)
+#include <malloc.h>
+#endif
+#include <memory.h>
+#include <cstring>
+
+#include "XBTFWriter.h"
+#include "guilib/XBTFReader.h"
+#include "utils/EndianSwap.h"
+
+
+#define WRITE_STR(str, size, file) fwrite(str, size, 1, file)
+#define WRITE_U32(i, file) { uint32_t _n = Endian_SwapLE32(i); fwrite(&_n, 4, 1, file); }
+#define WRITE_U64(i, file) { uint64_t _n = i; _n = Endian_SwapLE64(i); fwrite(&_n, 8, 1, file); }
+
+CXBTFWriter::CXBTFWriter(const std::string& outputFile)
+ : m_outputFile(outputFile),
+ m_file(nullptr),
+ m_data(nullptr),
+ m_size(0)
+{ }
+
+CXBTFWriter::~CXBTFWriter()
+{
+ Close();
+}
+
+bool CXBTFWriter::Create()
+{
+ m_file = fopen(m_outputFile.c_str(), "wb");
+ if (m_file == nullptr)
+ return false;
+
+ return true;
+}
+
+bool CXBTFWriter::Close()
+{
+ if (m_file == nullptr || m_data == nullptr)
+ return false;
+
+ fwrite(m_data, 1, m_size, m_file);
+
+ Cleanup();
+
+ return true;
+}
+
+void CXBTFWriter::Cleanup()
+{
+ free(m_data);
+ m_data = nullptr;
+ m_size = 0;
+ if (m_file)
+ {
+ fclose(m_file);
+ m_file = nullptr;
+ }
+}
+
+bool CXBTFWriter::AppendContent(unsigned char const* data, size_t length)
+{
+ unsigned char *new_data = (unsigned char *)realloc(m_data, m_size + length);
+
+ if (new_data == nullptr)
+ { // OOM - cleanup and fail
+ Cleanup();
+ return false;
+ }
+
+ m_data = new_data;
+
+ memcpy(m_data + m_size, data, length);
+ m_size += length;
+
+ return true;
+}
+
+bool CXBTFWriter::UpdateHeader(const std::vector<unsigned int>& dupes)
+{
+ if (m_file == nullptr)
+ return false;
+
+ uint64_t headerSize = GetHeaderSize();
+ uint64_t offset = headerSize;
+
+ WRITE_STR(XBTF_MAGIC.c_str(), 4, m_file);
+ WRITE_STR(XBTF_VERSION.c_str(), 1, m_file);
+
+ auto files = GetFiles();
+ WRITE_U32(files.size(), m_file);
+ for (size_t i = 0; i < files.size(); i++)
+ {
+ CXBTFFile& file = files[i];
+
+ // Convert path to lower case and store it into a fixed size array because
+ // we need to store the path as a fixed length 256 byte character array.
+ std::string path = file.GetPath();
+ char pathMem[CXBTFFile::MaximumPathLength];
+ memset(pathMem, 0, sizeof(pathMem));
+
+ for (std::string::iterator ch = path.begin(); ch != path.end(); ++ch)
+ pathMem[std::distance(path.begin(), ch)] = tolower(*ch);
+
+ WRITE_STR(pathMem, CXBTFFile::MaximumPathLength, m_file);
+ WRITE_U32(file.GetLoop(), m_file);
+
+ std::vector<CXBTFFrame>& frames = file.GetFrames();
+ WRITE_U32(frames.size(), m_file);
+ for (size_t j = 0; j < frames.size(); j++)
+ {
+ CXBTFFrame& frame = frames[j];
+ if (dupes[i] != i)
+ frame.SetOffset(files[dupes[i]].GetFrames()[j].GetOffset());
+ else
+ {
+ frame.SetOffset(offset);
+ offset += frame.GetPackedSize();
+ }
+
+ WRITE_U32(frame.GetWidth(), m_file);
+ WRITE_U32(frame.GetHeight(), m_file);
+ WRITE_U32(frame.GetFormat(true), m_file);
+ WRITE_U64(frame.GetPackedSize(), m_file);
+ WRITE_U64(frame.GetUnpackedSize(), m_file);
+ WRITE_U32(frame.GetDuration(), m_file);
+ WRITE_U64(frame.GetOffset(), m_file);
+ }
+ }
+
+ // Sanity check
+ int64_t pos = ftell(m_file);
+ if (pos != static_cast<int64_t>(headerSize))
+ {
+ printf("Expected header size (%" PRIu64 ") != actual size (%" PRId64 ")\n", headerSize, pos);
+ return false;
+ }
+
+ return true;
+}
diff --git a/tools/depends/native/TexturePacker/src/XBTFWriter.h b/tools/depends/native/TexturePacker/src/XBTFWriter.h
new file mode 100644
index 0000000..1e6496d
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/XBTFWriter.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "guilib/XBTF.h"
+
+#include <cstdio>
+#include <string>
+#include <vector>
+
+class CXBTFWriter : public CXBTFBase
+{
+public:
+ CXBTFWriter(const std::string& outputFile);
+ ~CXBTFWriter() override;
+
+ bool Create();
+ bool Close();
+ bool AppendContent(unsigned char const* data, size_t length);
+ bool UpdateHeader(const std::vector<unsigned int>& dupes);
+
+private:
+ void Cleanup();
+
+ std::string m_outputFile;
+ FILE* m_file;
+ unsigned char *m_data;
+ size_t m_size;
+};
+
diff --git a/tools/depends/native/TexturePacker/src/autogen.sh b/tools/depends/native/TexturePacker/src/autogen.sh
new file mode 100755
index 0000000..bbec436
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/autogen.sh
@@ -0,0 +1,3 @@
+#/bin/sh
+
+autoreconf -vif
diff --git a/tools/depends/native/TexturePacker/src/cmdlineargs.h b/tools/depends/native/TexturePacker/src/cmdlineargs.h
new file mode 100644
index 0000000..d0b9d03
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/cmdlineargs.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#ifdef TARGET_POSIX
+char* GetCommandLine();
+#define _snprintf snprintf
+#else
+#include <windows.h>
+#endif
+#include <vector>
+#include <string>
+
+class CmdLineArgs : public std::vector<char*>
+{
+public:
+ CmdLineArgs ()
+ {
+ // Save local copy of the command line string, because
+ // ParseCmdLine() modifies this string while parsing it.
+ char* cmdline = GetCommandLine();
+ m_cmdline = new char [strlen (cmdline) + 1];
+ if (m_cmdline)
+ {
+ strcpy (m_cmdline, cmdline);
+ ParseCmdLine();
+ } else {
+#ifdef TARGET_POSIX
+ delete[] cmdline;
+#endif
+ }
+ }
+
+ CmdLineArgs (const int argc, const char **argv)
+ {
+ std::string cmdline;
+#ifdef TARGET_POSIX
+ cmdline = "\"";
+#endif
+ for (int i = 0 ; i<argc ; i++)
+ {
+ cmdline += std::string(argv[i]);
+ if ( i != (argc-1) )
+ {
+#ifdef TARGET_POSIX
+ cmdline += "\" \"";
+#else
+ cmdline += " ";
+#endif
+ }
+ }
+#ifdef TARGET_POSIX
+ cmdline += "\"";
+#endif
+ m_cmdline = new char [cmdline.length() + 1];
+ if (m_cmdline)
+ {
+ strcpy(m_cmdline, cmdline.c_str());
+ ParseCmdLine();
+ }
+ }
+
+ ~CmdLineArgs()
+ {
+ delete[] m_cmdline;
+ }
+
+private:
+ char* m_cmdline; // the command line string
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Parse m_cmdline into individual tokens, which are delimited by spaces. If a
+ // token begins with a quote, then that token is terminated by the next quote
+ // followed immediately by a space or terminator. This allows tokens to contain
+ // spaces.
+ // This input string: This "is" a ""test"" "of the parsing" alg"o"rithm.
+ // Produces these tokens: This, is, a, "test", of the parsing, alg"o"rithm
+ ////////////////////////////////////////////////////////////////////////////////
+ void ParseCmdLine ()
+ {
+ enum { TERM = '\0',
+ QUOTE = '\"' };
+
+ bool bInQuotes = false;
+ char* pargs = m_cmdline;
+
+ while (*pargs)
+ {
+ while (isspace (*pargs)) // skip leading whitespace
+ pargs++;
+
+ bInQuotes = (*pargs == QUOTE); // see if this token is quoted
+
+ if (bInQuotes) // skip leading quote
+ pargs++;
+
+ push_back (pargs); // store position of current token
+
+ // Find next token.
+ // NOTE: Args are normally terminated by whitespace, unless the
+ // arg is quoted. That's why we handle the two cases separately,
+ // even though they are very similar.
+ if (bInQuotes)
+ {
+ // find next quote followed by a space or terminator
+ while (*pargs &&
+ !(*pargs == QUOTE && (isspace (pargs[1]) || pargs[1] == TERM)))
+ pargs++;
+ if (*pargs)
+ {
+ *pargs = TERM; // terminate token
+ if (pargs[1]) // if quoted token not followed by a terminator
+ pargs += 2; // advance to next token
+ }
+ }
+ else
+ {
+ // skip to next non-whitespace character
+ while (*pargs && !isspace (*pargs))
+ pargs++;
+ if (*pargs && isspace (*pargs)) // end of token
+ {
+ *pargs = TERM; // terminate token
+ pargs++; // advance to next token or terminator
+ }
+ }
+ } // while (*pargs)
+ } // ParseCmdLine()
+}; // class CmdLineArgs
+
diff --git a/tools/depends/native/TexturePacker/src/configure.ac b/tools/depends/native/TexturePacker/src/configure.ac
new file mode 100644
index 0000000..4b83b5e
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/configure.ac
@@ -0,0 +1,41 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(TexturePacker, 1.0)
+AC_CONFIG_AUX_DIR(config)
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_SRCDIR(TexturePacker.cpp)
+AM_INIT_AUTOMAKE([foreign])
+AC_PROG_CXX
+AC_LANG([C++])
+AC_C_BIGENDIAN
+
+abs_top_srcdir=${abs_top_srcdir=$(cd $srcdir; pwd)}
+KODI_SRC_DIR=${KODI_SRC_DIR:-"${abs_top_srcdir}/../../../../.."}
+
+AC_ARG_ENABLE([static],
+ [AS_HELP_STRING([--enable-static],
+ [build static TexturePacker (default is no)])],
+ [STATIC_FLAG="-static"],
+ [STATIC_FLAG=""])
+
+
+PKG_CHECK_MODULES([PNG], [libpng],
+ [INCLUDES="$PNG_CFLAGS"; LIBS="$LIBS $(${PKG_CONFIG} --silence-errors --static --libs libpng)"],
+ AC_MSG_ERROR("libpng not found"))
+
+AC_CHECK_HEADER([gif_lib.h],, AC_MSG_ERROR("gif_lib.h not found"))
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <gif_lib.h>]], [[
+#if !defined GIFLIB_MAJOR || GIFLIB_MAJOR < 5
+#error libgif version < 5;
+#endif ]])], [], [AC_MSG_NOTICE([[WARNING: libgif version is unsupported, please consider upgrading to 5.0.5 or higher.]])])
+
+AC_CHECK_LIB([gif],[main],, AC_MSG_ERROR("libgif not found"))
+AC_CHECK_HEADER([jpeglib.h],, AC_MSG_ERROR("jpeglib.h not found"))
+AC_CHECK_LIB([jpeg],[main],, AC_MSG_ERROR("libjpeg not found"))
+AC_CHECK_HEADER([lzo/lzo1x.h],, AC_MSG_ERROR("lzo/lzo1x.h not found"))
+AC_CHECK_LIB([lzo2],[main],, AC_MSG_ERROR("liblzo2 not found"))
+
+AC_SUBST(KODI_SRC_DIR)
+AC_SUBST(STATIC_FLAG)
+AC_SUBST(EXTRA_DEFINES)
+
+AC_OUTPUT(Makefile)
diff --git a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp
new file mode 100644
index 0000000..5bdfacd
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "GIFDecoder.h"
+
+#include "GifHelper.h"
+
+#include <cstring>
+
+// returns true for gif files, otherwise returns false
+bool GIFDecoder::CanDecode(const std::string &filename)
+{
+ return std::string::npos != filename.rfind(".gif",filename.length() - 4, 4);
+}
+
+bool GIFDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
+{
+ int n = 0;
+ bool result = false;
+
+ GifHelper *gifImage = new GifHelper();
+ if (gifImage->LoadGif(filename.c_str()))
+ {
+ auto extractedFrames = gifImage->GetFrames();
+ n = extractedFrames.size();
+ if (n > 0)
+ {
+ unsigned int height = gifImage->GetHeight();
+ unsigned int width = gifImage->GetWidth();
+ unsigned int pitch = gifImage->GetPitch();
+ unsigned int frameSize = pitch * height;
+ for (unsigned int i = 0; i < extractedFrames.size(); i++)
+ {
+ DecodedFrame frame;
+
+ frame.rgbaImage.pixels = (char *)new char[frameSize];
+ memcpy(frame.rgbaImage.pixels, extractedFrames[i]->m_pImage, frameSize);
+ frame.rgbaImage.height = height;
+ frame.rgbaImage.width = width;
+ frame.rgbaImage.bbp = 32;
+ frame.rgbaImage.pitch = pitch;
+ frame.delay = extractedFrames[i]->m_delay;
+ frame.decoder = this;
+
+ frames.frameList.push_back(frame);
+ }
+ }
+ result = true;
+ }
+ delete gifImage;
+ return result;
+}
+
+void GIFDecoder::FreeDecodedFrame(DecodedFrame &frame)
+{
+ delete [] frame.rgbaImage.pixels;
+}
+
+void GIFDecoder::FillSupportedExtensions()
+{
+ m_supportedExtensions.emplace_back(".gif");
+}
diff --git a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h
new file mode 100644
index 0000000..8f0b42d
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "IDecoder.h"
+
+class GIFDecoder : public IDecoder
+{
+ public:
+ ~GIFDecoder() override = default;
+ bool CanDecode(const std::string &filename) override;
+ bool LoadFile(const std::string &filename, DecodedFrames &frames) override;
+ void FreeDecodedFrame(DecodedFrame &frame) override;
+ const char* GetImageFormatName() override { return "GIF"; }
+ const char* GetDecoderName() override { return "libgif"; }
+ protected:
+ void FillSupportedExtensions() override;
+};
diff --git a/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp b/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp
new file mode 100644
index 0000000..41ca270
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "GifHelper.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+
+#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
+#define GIF_MAX_MEMORY 82944000U // about 79 MB, which is equivalent to 10 full hd frames.
+
+class Gifreader
+{
+public:
+ unsigned char* buffer = nullptr;
+ unsigned int buffSize = 0;
+ unsigned int readPosition = 0;
+
+ Gifreader() = default;
+};
+
+int ReadFromVfs(GifFileType* gif, GifByteType* gifbyte, int len)
+{
+ CFile *gifFile = static_cast<CFile*>(gif->UserData);
+ return gifFile->Read(gifbyte, len);
+}
+
+GifHelper::GifHelper()
+{
+ m_gifFile = new CFile();
+}
+
+GifHelper::~GifHelper()
+{
+ Close(m_gif);
+ Release();
+ delete m_gifFile;
+}
+
+bool GifHelper::Open(GifFileType*& gif, void *dataPtr, InputFunc readFunc)
+{
+ int err = 0;
+#if GIFLIB_MAJOR == 5
+ gif = DGifOpen(dataPtr, readFunc, &err);
+#else
+ gif = DGifOpen(dataPtr, readFunc);
+ if (!gif)
+ err = GifLastError();
+#endif
+
+ if (!gif)
+ {
+ fprintf(stderr, "Gif::Open(): Could not open file %s. Reason: %s\n", m_filename.c_str(), GifErrorString(err));
+ return false;
+ }
+
+ return true;
+}
+
+void GifHelper::Close(GifFileType* gif)
+{
+ int err = 0;
+ int reason = 0;
+#if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1
+ err = DGifCloseFile(gif, &reason);
+#else
+ err = DGifCloseFile(gif);
+#if GIFLIB_MAJOR < 5
+ reason = GifLastError();
+#endif
+ if (err == GIF_ERROR)
+ free(gif);
+#endif
+ if (err == GIF_ERROR)
+ {
+ fprintf(stderr, "GifHelper::Close(): closing file %s failed. Reason: %s\n", m_filename.c_str(), Reason(reason));
+ }
+}
+
+const char* GifHelper::Reason(int reason)
+{
+ const char* err = GifErrorString(reason);
+ if (err)
+ return err;
+
+ return "unknown";
+
+}
+
+void GifHelper::Release()
+{
+ delete[] m_pTemplate;
+ m_pTemplate = nullptr;
+ m_globalPalette.clear();
+ m_frames.clear();
+}
+
+void GifHelper::ConvertColorTable(std::vector<GifColor> &dest, ColorMapObject* src, unsigned int size)
+{
+ for (unsigned int i = 0; i < size; ++i)
+ {
+ GifColor c;
+
+ c.r = src->Colors[i].Red;
+ c.g = src->Colors[i].Green;
+ c.b = src->Colors[i].Blue;
+ c.a = 0xff;
+ dest.push_back(c);
+ }
+}
+
+bool GifHelper::LoadGifMetaData(GifFileType* gif)
+{
+ if (!Slurp(gif))
+ return false;
+
+ m_height = gif->SHeight;
+ m_width = gif->SWidth;
+ if (!m_height || !m_width)
+ {
+ fprintf(stderr, "Gif::LoadGif(): Zero sized image. File %s\n", m_filename.c_str());
+ return false;
+ }
+
+ m_numFrames = gif->ImageCount;
+ if (m_numFrames > 0)
+ {
+ ExtensionBlock* extb = gif->SavedImages[0].ExtensionBlocks;
+ if (extb && extb->Function == APPLICATION_EXT_FUNC_CODE)
+ {
+ // Read number of loops
+ if (++extb && extb->Function == CONTINUE_EXT_FUNC_CODE)
+ {
+ uint8_t low = static_cast<uint8_t>(extb->Bytes[1]);
+ uint8_t high = static_cast<uint8_t>(extb->Bytes[2]);
+ m_loops = UNSIGNED_LITTLE_ENDIAN(low, high);
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Gif::LoadGif(): No images found in file %s\n", m_filename.c_str());
+ return false;
+ }
+
+ m_pitch = m_width * sizeof(GifColor);
+ m_imageSize = m_pitch * m_height;
+ unsigned long memoryUsage = m_numFrames * m_imageSize;
+ if (memoryUsage > GIF_MAX_MEMORY)
+ {
+ // at least 1 image
+ m_numFrames = std::max(1U, GIF_MAX_MEMORY / m_imageSize);
+ fprintf(stderr, "Gif::LoadGif(): Memory consumption too high: %lu bytes. Restricting animation to %u. File %s\n", memoryUsage, m_numFrames, m_filename.c_str());
+ }
+
+ return true;
+}
+
+bool GifHelper::LoadGifMetaData(const char* file)
+{
+ m_gifFile->Close();
+ if (!m_gifFile->Open(file) || !Open(m_gif, m_gifFile, ReadFromVfs))
+ return false;
+
+ return LoadGifMetaData(m_gif);
+}
+
+bool GifHelper::Slurp(GifFileType* gif)
+{
+ if (DGifSlurp(gif) == GIF_ERROR)
+ {
+ int reason = 0;
+#if GIFLIB_MAJOR == 5
+ reason = gif->Error;
+#else
+ reason = GifLastError();
+#endif
+ fprintf(stderr, "Gif::LoadGif(): Could not read file %s. Reason: %s\n", m_filename.c_str(), GifErrorString(reason));
+ return false;
+ }
+
+ return true;
+}
+
+bool GifHelper::LoadGif(const char* file)
+{
+ m_filename = file;
+ if (!LoadGifMetaData(m_filename.c_str()))
+ return false;
+
+ try
+ {
+ InitTemplateAndColormap();
+
+ int extractedFrames = ExtractFrames(m_numFrames);
+ if (extractedFrames < 0)
+ {
+ fprintf(stderr, "Gif::LoadGif(): Could not extract any frame. File %s\n", m_filename.c_str());
+ return false;
+ }
+ else if (extractedFrames < (int)m_numFrames)
+ {
+ fprintf(stderr, "Gif::LoadGif(): Could only extract %d/%d frames. File %s\n", extractedFrames, m_numFrames, m_filename.c_str());
+ m_numFrames = extractedFrames;
+ }
+
+ return true;
+ }
+ catch (std::bad_alloc& ba)
+ {
+ fprintf(stderr, "Gif::Load(): Out of memory while reading file %s - %s\n", m_filename.c_str(), ba.what());
+ Release();
+ return false;
+ }
+}
+
+void GifHelper::InitTemplateAndColormap()
+{
+ m_pTemplate = new unsigned char[m_imageSize];
+ memset(m_pTemplate, 0, m_imageSize);
+
+ if (m_gif->SColorMap)
+ {
+ m_globalPalette.clear();
+ ConvertColorTable(m_globalPalette, m_gif->SColorMap, m_gif->SColorMap->ColorCount);
+ }
+ else
+ m_globalPalette.clear();
+}
+
+bool GifHelper::GcbToFrame(GifFrame &frame, unsigned int imgIdx)
+{
+ int transparent = -1;
+ frame.m_delay = 0;
+ frame.m_disposal = 0;
+
+ if (m_gif->ImageCount > 0)
+ {
+#if GIFLIB_MAJOR == 5
+ GraphicsControlBlock gcb;
+ if (DGifSavedExtensionToGCB(m_gif, imgIdx, &gcb))
+ {
+ // delay in ms
+ frame.m_delay = gcb.DelayTime * 10;
+ frame.m_disposal = gcb.DisposalMode;
+ transparent = gcb.TransparentColor;
+ }
+#else
+ ExtensionBlock* extb = m_gif->SavedImages[imgIdx].ExtensionBlocks;
+ while (extb && extb->Function != GRAPHICS_EXT_FUNC_CODE)
+ extb++;
+
+ if (extb && extb->ByteCount == 4)
+ {
+ uint8_t low = static_cast<uint8_t>(extb->Bytes[1]);
+ uint8_t high = static_cast<uint8_t>(extb->Bytes[2]);
+ frame.m_delay = UNSIGNED_LITTLE_ENDIAN(low, high) * 10;
+ frame.m_disposal = (extb->Bytes[0] >> 2) & 0x07;
+ if (extb->Bytes[0] & 0x01)
+ {
+ transparent = static_cast<uint8_t>(extb->Bytes[3]);
+ }
+ else
+ transparent = -1;
+ }
+#endif
+ }
+
+ if (transparent >= 0 && (unsigned)transparent < frame.m_palette.size())
+ frame.m_palette[transparent].a = 0;
+ return true;
+}
+
+int GifHelper::ExtractFrames(unsigned int count)
+{
+ if (!m_gif)
+ return -1;
+
+ if (!m_pTemplate)
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): No frame template available\n");
+ return -1;
+ }
+
+ int extracted = 0;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ FramePtr frame(new GifFrame);
+ SavedImage savedImage = m_gif->SavedImages[i];
+ GifImageDesc imageDesc = m_gif->SavedImages[i].ImageDesc;
+ frame->m_height = imageDesc.Height;
+ frame->m_width = imageDesc.Width;
+ frame->m_top = imageDesc.Top;
+ frame->m_left = imageDesc.Left;
+
+ if (frame->m_top + frame->m_height > m_height || frame->m_left + frame->m_width > m_width
+ || !frame->m_width || !frame->m_height
+ || frame->m_width > m_width || frame->m_height > m_height)
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): Illegal frame dimensions: width: %d, height: %d, left: %d, top: %d instead of (%d,%d), skip it\n",
+ frame->m_width, frame->m_height, frame->m_left, frame->m_top, m_width, m_height);
+ continue;
+ }
+
+ if (imageDesc.ColorMap)
+ {
+ frame->m_palette.clear();
+ ConvertColorTable(frame->m_palette, imageDesc.ColorMap, imageDesc.ColorMap->ColorCount);
+ // TODO save a backup of the palette for frames without a table in case there's no global table.
+ }
+ else if (m_gif->SColorMap)
+ {
+ frame->m_palette = m_globalPalette;
+ }
+ else
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): No color map found for frame %d, skip it\n", i);
+ continue;
+ }
+
+ // fill delay, disposal and transparent color into frame
+ if (!GcbToFrame(*frame, i))
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): Corrupted Graphics Control Block for frame %d, skip it\n", i);
+ continue;
+ }
+
+ frame->m_pImage = new unsigned char[m_imageSize];
+ frame->m_imageSize = m_imageSize;
+ memcpy(frame->m_pImage, m_pTemplate, m_imageSize);
+
+ ConstructFrame(*frame, savedImage.RasterBits);
+
+ if (!PrepareTemplate(*frame))
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): Could not prepare template after frame %d, skip it\n", i);
+ continue;
+ }
+
+ extracted++;
+ m_frames.push_back(frame);
+ }
+ return extracted;
+}
+
+void GifHelper::ConstructFrame(GifFrame &frame, const unsigned char* src) const
+{
+ size_t paletteSize = frame.m_palette.size();
+
+ for (unsigned int dest_y = frame.m_top, src_y = 0; src_y < frame.m_height; ++dest_y, ++src_y)
+ {
+ unsigned char *to = frame.m_pImage + (dest_y * m_pitch) + (frame.m_left * sizeof(GifColor));
+
+ const unsigned char *from = src + (src_y * frame.m_width);
+ for (unsigned int src_x = 0; src_x < frame.m_width; ++src_x)
+ {
+ unsigned char index = *from++;
+
+ if (index >= paletteSize)
+ {
+ fprintf(stderr, "Gif::ConstructFrame(): Pixel (%d,%d) has no valid palette entry, skip it\n", src_x, src_y);
+ continue;
+ }
+
+ GifColor col = frame.m_palette[index];
+ if (col.a != 0)
+ memcpy(to, &col, sizeof(GifColor));
+
+ to += 4;
+ }
+ }
+}
+
+bool GifHelper::PrepareTemplate(GifFrame &frame)
+{
+ switch (frame.m_disposal)
+ {
+ /* No disposal specified. */
+ case DISPOSAL_UNSPECIFIED:
+ /* Leave image in place */
+ case DISPOSE_DO_NOT:
+ memcpy(m_pTemplate, frame.m_pImage, m_imageSize);
+ break;
+
+ /*
+ Clear the frame's area to transparency.
+ The disposal names is misleading. Do not restore to the background color because
+ this part of the specification is ignored by all browsers/image viewers.
+ */
+ case DISPOSE_BACKGROUND:
+ {
+ ClearFrameAreaToTransparency(m_pTemplate, frame);
+ break;
+ }
+ /* Restore to previous content */
+ case DISPOSE_PREVIOUS:
+ {
+
+ /*
+ * This disposal method makes no sense for the first frame
+ * Since browsers etc. handle that too, we'll fall back to DISPOSE_DO_NOT
+ */
+ if (m_frames.empty())
+ {
+ frame.m_disposal = DISPOSE_DO_NOT;
+ return PrepareTemplate(frame);
+ }
+
+ bool valid = false;
+
+ for (int i = m_frames.size() - 1; i >= 0; --i)
+ {
+ if (m_frames[i]->m_disposal != DISPOSE_PREVIOUS)
+ {
+ memcpy(m_pTemplate, m_frames[i]->m_pImage, m_imageSize);
+ valid = true;
+ break;
+ }
+ }
+ if (!valid)
+ {
+ fprintf(stderr, "Gif::PrepareTemplate(): Disposal method DISPOSE_PREVIOUS encountered, but could not find a suitable frame.\n");
+ return false;
+ }
+ break;
+ }
+ default:
+ {
+ fprintf(stderr, "Gif::PrepareTemplate(): Unknown disposal method: %d. Using DISPOSAL_UNSPECIFIED, the animation might be wrong now.\n", frame.m_disposal);
+ frame.m_disposal = DISPOSAL_UNSPECIFIED;
+ return PrepareTemplate(frame);
+ }
+ }
+ return true;
+}
+
+void GifHelper::ClearFrameAreaToTransparency(unsigned char* dest, const GifFrame &frame)
+{
+ for (unsigned int dest_y = frame.m_top, src_y = 0; src_y < frame.m_height; ++dest_y, ++src_y)
+ {
+ unsigned char *to = dest + (dest_y * m_pitch) + (frame.m_left * sizeof(GifColor));
+ for (unsigned int src_x = 0; src_x < frame.m_width; ++src_x)
+ {
+ to += 3;
+ *to++ = 0;
+ }
+ }
+}
+
+GifFrame::GifFrame(const GifFrame& src)
+ : m_delay(src.m_delay),
+ m_top(src.m_top),
+ m_left(src.m_left),
+ m_disposal(src.m_disposal),
+ m_height(src.m_height),
+ m_width(src.m_width),
+ m_imageSize(src.m_imageSize)
+{
+ if (src.m_pImage)
+ {
+ m_pImage = new unsigned char[m_imageSize];
+ memcpy(m_pImage, src.m_pImage, m_imageSize);
+ }
+
+ if (src.m_palette.size())
+ {
+ m_palette = src.m_palette;
+ }
+}
+
+GifFrame::~GifFrame()
+{
+ delete[] m_pImage;
+ m_pImage = nullptr;
+}
diff --git a/tools/depends/native/TexturePacker/src/decoder/GifHelper.h b/tools/depends/native/TexturePacker/src/decoder/GifHelper.h
new file mode 100644
index 0000000..1e897a7
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/GifHelper.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <gif_lib.h>
+#ifndef CONTINUE_EXT_FUNC_CODE
+#define CONTINUE_EXT_FUNC_CODE 0
+#endif
+
+#ifndef DISPOSAL_UNSPECIFIED
+#define DISPOSAL_UNSPECIFIED 0
+#endif
+
+#ifndef DISPOSE_DO_NOT
+#define DISPOSE_DO_NOT 1
+#endif
+
+#ifndef DISPOSE_BACKGROUND
+#define DISPOSE_BACKGROUND 2
+#endif
+
+#ifndef DISPOSE_PREVIOUS
+#define DISPOSE_PREVIOUS 3
+#endif
+
+#include <vector>
+#include <string>
+#include <memory>
+#include "SimpleFS.h"
+
+#pragma pack(1)
+struct GifColor
+{
+ uint8_t b, g, r, a;
+};
+#pragma pack()
+
+class CFile;
+
+class GifFrame
+{
+ friend class GifHelper;
+public:
+
+ GifFrame() = default;
+ virtual ~GifFrame();
+
+ unsigned char* m_pImage = nullptr;
+ unsigned int m_delay = 0;
+
+private:
+ GifFrame(const GifFrame& src);
+
+ unsigned int m_top = 0;
+ unsigned int m_left = 0;
+ unsigned int m_disposal = 0;
+ unsigned int m_height = 0;
+ unsigned int m_width = 0;
+ unsigned int m_imageSize = 0;
+ std::vector<GifColor> m_palette;
+};
+
+
+
+class GifHelper
+{
+ friend class GifFrame;
+
+ typedef std::shared_ptr<GifFrame> FramePtr;
+
+public:
+ GifHelper();
+ virtual ~GifHelper();
+
+
+ bool LoadGif(const char* file);
+
+ std::vector<FramePtr>& GetFrames() { return m_frames; }
+ unsigned int GetPitch() const { return m_pitch; }
+ unsigned int GetNumLoops() const { return m_loops; }
+ unsigned int GetWidth() const { return m_width; }
+ unsigned int GetHeight() const { return m_height; }
+
+private:
+ std::vector<FramePtr> m_frames;
+ unsigned int m_imageSize = 0;
+ unsigned int m_pitch = 0;
+ unsigned int m_loops = 0;
+ unsigned int m_numFrames = 0;
+
+ std::string m_filename;
+ GifFileType* m_gif = nullptr;
+ std::vector<GifColor> m_globalPalette;
+ unsigned char* m_pTemplate = nullptr;
+ CFile* m_gifFile;
+
+ unsigned int m_width;
+ unsigned int m_height;
+
+ bool Open(GifFileType *& gif, void * dataPtr, InputFunc readFunc);
+ void Close(GifFileType * gif);
+
+ const char* Reason(int reason);
+
+ bool LoadGifMetaData(const char* file);
+ bool Slurp(GifFileType* gif);
+ void InitTemplateAndColormap();
+ bool LoadGifMetaData(GifFileType* gif);
+ static void ConvertColorTable(std::vector<GifColor> &dest, ColorMapObject* src, unsigned int size);
+ bool GcbToFrame(GifFrame &frame, unsigned int imgIdx);
+ int ExtractFrames(unsigned int count);
+ void ClearFrameAreaToTransparency(unsigned char* dest, const GifFrame &frame);
+ void ConstructFrame(GifFrame &frame, const unsigned char* src) const;
+ bool PrepareTemplate(GifFrame &frame);
+ void Release();
+
+#if GIFLIB_MAJOR != 5
+ /*
+ taken from giflib 5.1.0
+ */
+ const char* GifErrorString(int ErrorCode)
+ {
+ const char *Err;
+
+ switch (ErrorCode) {
+ case E_GIF_ERR_OPEN_FAILED:
+ Err = "Failed to open given file";
+ break;
+ case E_GIF_ERR_WRITE_FAILED:
+ Err = "Failed to write to given file";
+ break;
+ case E_GIF_ERR_HAS_SCRN_DSCR:
+ Err = "Screen descriptor has already been set";
+ break;
+ case E_GIF_ERR_HAS_IMAG_DSCR:
+ Err = "Image descriptor is still active";
+ break;
+ case E_GIF_ERR_NO_COLOR_MAP:
+ Err = "Neither global nor local color map";
+ break;
+ case E_GIF_ERR_DATA_TOO_BIG:
+ Err = "Number of pixels bigger than width * height";
+ break;
+ case E_GIF_ERR_NOT_ENOUGH_MEM:
+ Err = "Failed to allocate required memory";
+ break;
+ case E_GIF_ERR_DISK_IS_FULL:
+ Err = "Write failed (disk full?)";
+ break;
+ case E_GIF_ERR_CLOSE_FAILED:
+ Err = "Failed to close given file";
+ break;
+ case E_GIF_ERR_NOT_WRITEABLE:
+ Err = "Given file was not opened for write";
+ break;
+ case D_GIF_ERR_OPEN_FAILED:
+ Err = "Failed to open given file";
+ break;
+ case D_GIF_ERR_READ_FAILED:
+ Err = "Failed to read from given file";
+ break;
+ case D_GIF_ERR_NOT_GIF_FILE:
+ Err = "Data is not in GIF format";
+ break;
+ case D_GIF_ERR_NO_SCRN_DSCR:
+ Err = "No screen descriptor detected";
+ break;
+ case D_GIF_ERR_NO_IMAG_DSCR:
+ Err = "No Image Descriptor detected";
+ break;
+ case D_GIF_ERR_NO_COLOR_MAP:
+ Err = "Neither global nor local color map";
+ break;
+ case D_GIF_ERR_WRONG_RECORD:
+ Err = "Wrong record type detected";
+ break;
+ case D_GIF_ERR_DATA_TOO_BIG:
+ Err = "Number of pixels bigger than width * height";
+ break;
+ case D_GIF_ERR_NOT_ENOUGH_MEM:
+ Err = "Failed to allocate required memory";
+ break;
+ case D_GIF_ERR_CLOSE_FAILED:
+ Err = "Failed to close given file";
+ break;
+ case D_GIF_ERR_NOT_READABLE:
+ Err = "Given file was not opened for read";
+ break;
+ case D_GIF_ERR_IMAGE_DEFECT:
+ Err = "Image is defective, decoding aborted";
+ break;
+ case D_GIF_ERR_EOF_TOO_SOON:
+ Err = "Image EOF detected before image complete";
+ break;
+ default:
+ Err = NULL;
+ break;
+ }
+ return Err;
+ }
+#endif
+};
diff --git a/tools/depends/native/TexturePacker/src/decoder/IDecoder.h b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
new file mode 100644
index 0000000..673ff1a
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+/* forward declarations */
+
+class DecodedFrame;
+class DecodedFrames;
+
+class IDecoder
+{
+ public:
+ virtual ~IDecoder() = default;
+ virtual bool CanDecode(const std::string &filename) = 0;
+ virtual bool LoadFile(const std::string &filename, DecodedFrames &frames) = 0;
+ virtual void FreeDecodedFrame(DecodedFrame &frame) = 0;
+ virtual const char* GetImageFormatName() = 0;
+ virtual const char* GetDecoderName() = 0;
+
+ const std::vector<std::string>& GetSupportedExtensions()
+ {
+ m_supportedExtensions.clear();
+ FillSupportedExtensions();
+ return m_supportedExtensions;
+ }
+
+ protected:
+ virtual void FillSupportedExtensions() = 0;
+ //fill this with extensions in FillSupportedExtensions like ".png"
+ std::vector<std::string> m_supportedExtensions;
+};
+
+class RGBAImage
+{
+public:
+ RGBAImage() = default;
+
+ char* pixels = nullptr; // image data
+ int width = 0; // width
+ int height = 0; // height
+ int bbp = 0; // bits per pixel
+ int pitch = 0; // rowsize in bytes
+};
+
+class DecodedFrame
+{
+public:
+ DecodedFrame() = default;
+ RGBAImage rgbaImage; /* rgbaimage for this frame */
+ int delay = 0; /* Frame delay in ms */
+ IDecoder* decoder = nullptr; /* Pointer to decoder */
+};
+
+class DecodedFrames
+{
+ public:
+ DecodedFrames() = default;
+ std::vector<DecodedFrame> frameList;
+
+ void clear()
+ {
+ for (auto f : frameList)
+ {
+ if (f.decoder != NULL)
+ {
+ f.decoder->FreeDecodedFrame(f);
+ }
+ else
+ {
+ fprintf(stderr,
+ "ERROR: %s - can not determine decoder type for frame!\n",
+ __FUNCTION__);
+ }
+ }
+ frameList.clear();
+ }
+};
diff --git a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp
new file mode 100644
index 0000000..ce06d28
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "JPGDecoder.h"
+
+#include "SimpleFS.h"
+
+#include <jpeglib.h>
+
+bool JPGDecoder::CanDecode(const std::string &filename)
+{
+ CFile *fp = new CFile();
+ bool ret = false;
+ unsigned char magic[2];
+ if (fp->Open(filename))
+ {
+
+ //JPEG image files begin with FF D8 and end with FF D9.
+ // check for FF D8 big + little endian on start
+ uint64_t readbytes = fp->Read(magic, 2);
+ if (readbytes == 2)
+ {
+ if ((magic[0] == 0xd8 && magic[1] == 0xff) ||
+ (magic[1] == 0xd8 && magic[0] == 0xff))
+ ret = true;
+ }
+
+ if (ret)
+ {
+ ret = false;
+ //check on FF D9 big + little endian on end
+ uint64_t fileSize = fp->GetFileSize();
+ fp->Seek(fileSize - 2);
+ readbytes = fp->Read(magic, 2);
+ if (readbytes == 2)
+ {
+ if ((magic[0] == 0xd9 && magic[1] == 0xff) ||
+ (magic[1] == 0xd9 && magic[0] == 0xff))
+ ret = true;
+ }
+ }
+ }
+ delete fp;
+ return ret;
+}
+
+bool JPGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
+{
+ #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
+ CFile *arq = new CFile();
+ if (!arq->Open(filename))
+ {
+ delete arq;
+ return false;
+ }
+
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ int ImageSize;
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+
+ jpeg_stdio_src(&cinfo, arq->getFP());
+ jpeg_read_header(&cinfo, TRUE);
+ jpeg_start_decompress(&cinfo);
+
+ // Image Size is calculated as (width * height * bytes per pixel = 4
+ ImageSize = cinfo.image_width * cinfo.image_height * 4;
+
+ DecodedFrame frame;
+
+ frame.rgbaImage.pixels = (char *)new char[ImageSize];
+
+ unsigned char *scanlinebuff = new unsigned char[3 * cinfo.image_width];
+ unsigned char *dst = (unsigned char *)frame.rgbaImage.pixels;
+ while (cinfo.output_scanline < cinfo.output_height)
+ {
+ jpeg_read_scanlines(&cinfo,&scanlinebuff,1);
+
+ unsigned char *src2 = scanlinebuff;
+ unsigned char *dst2 = dst;
+ for (unsigned int x = 0; x < cinfo.image_width; x++, src2 += 3)
+ {
+ *dst2++ = src2[2];
+ *dst2++ = src2[1];
+ *dst2++ = src2[0];
+ *dst2++ = 0xff;
+ }
+ dst += cinfo.image_width * 4;
+ }
+ delete [] scanlinebuff;
+
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+
+ frame.rgbaImage.height = cinfo.image_height;
+ frame.rgbaImage.width = cinfo.image_width;
+ frame.rgbaImage.bbp = 32;
+ frame.rgbaImage.pitch = 4 * cinfo.image_width;
+
+ frame.decoder = this;
+
+ frames.frameList.push_back(frame);
+
+ delete arq;
+ return true;
+}
+
+void JPGDecoder::FreeDecodedFrame(DecodedFrame &frame)
+{
+ delete [] frame.rgbaImage.pixels;
+}
+
+void JPGDecoder::FillSupportedExtensions()
+{
+ m_supportedExtensions.emplace_back(".jpg");
+ m_supportedExtensions.emplace_back(".jpeg");
+}
diff --git a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h
new file mode 100644
index 0000000..bbf23ba
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "IDecoder.h"
+
+class JPGDecoder : public IDecoder
+{
+ public:
+ ~JPGDecoder() override = default;
+ bool CanDecode(const std::string &filename) override;
+ bool LoadFile(const std::string &filename, DecodedFrames &frames) override;
+ void FreeDecodedFrame(DecodedFrame &frame) override;
+ const char* GetImageFormatName() override { return "JPG"; }
+ const char* GetDecoderName() override { return "libjpeg"; }
+ protected:
+ void FillSupportedExtensions() override;
+};
diff --git a/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp
new file mode 100644
index 0000000..f327400
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "PNGDecoder.h"
+
+#include "SimpleFS.h"
+
+#include <png.h>
+
+#ifndef png_jmpbuf
+# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#endif
+
+/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp()
+ * returns zero if the image is a PNG and nonzero if it isn't a PNG.
+ *
+ * The function check_if_png() shown here, but not used, returns nonzero (true)
+ * if the file can be opened and is a PNG, 0 (false) otherwise.
+ *
+ * If this call is successful, and you are going to keep the file open,
+ * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
+ * you have created the png_ptr, so that libpng knows your application
+ * has read that many bytes from the start of the file. Make sure you
+ * don't call png_set_sig_bytes() with more than 8 bytes read or give it
+ * an incorrect number of bytes read, or you will either have read too
+ * many bytes (your fault), or you are telling libpng to read the wrong
+ * number of magic bytes (also your fault).
+ *
+ * Many applications already read the first 2 or 4 bytes from the start
+ * of the image to determine the file type, so it would be easiest just
+ * to pass the bytes to png_sig_cmp() or even skip that if you know
+ * you have a PNG file, and call png_set_sig_bytes().
+ */
+bool PNGDecoder::CanDecode(const std::string &filename)
+{
+ #define PNG_BYTES_TO_CHECK 4
+ CFile fp;
+ char buf[PNG_BYTES_TO_CHECK];
+
+ /* Open the prospective PNG file. */
+ if (!fp.Open(filename))
+ return false;
+
+ /* Read in some of the signature bytes */
+ if (fp.Read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK)
+ {
+ fprintf(stderr, "error reading header ...\n");
+ return false;
+ }
+ fp.Close();
+
+ /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
+ Return nonzero (true) if they match */
+ return(!png_sig_cmp((png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
+}
+
+bool PNGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
+{
+ png_byte header[8];
+
+ CFile fp;
+ if (!fp.Open(filename))
+ {
+ perror(filename.c_str());
+ return false;
+ }
+
+ // read the header
+ fp.Read(header, 8);
+
+ if (png_sig_cmp(header, 0, 8))
+ {
+ fprintf(stderr, "error: %s is not a PNG.\n", filename.c_str());
+ return false;
+ }
+
+ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ {
+ fprintf(stderr, "error: png_create_read_struct returned 0.\n");
+ return false;
+ }
+
+ // create png info struct
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ fprintf(stderr, "error: png_create_info_struct returned 0.\n");
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ return false;
+ }
+
+ // create png info struct
+ png_infop end_info = png_create_info_struct(png_ptr);
+ if (!end_info)
+ {
+ fprintf(stderr, "error: png_create_info_struct returned 0.\n");
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
+ return false;
+ }
+
+ // the code in this if statement gets called if libpng encounters an error
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ fprintf(stderr, "error from libpng\n");
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ return false;
+ }
+
+ // init png reading
+ png_init_io(png_ptr, fp.getFP());
+
+ // let libpng know you already read the first 8 bytes
+ png_set_sig_bytes(png_ptr, 8);
+
+ // read all the info up to the image data
+ png_read_info(png_ptr, info_ptr);
+
+ // variables to pass to get info
+ int bit_depth, color_type;
+ png_uint_32 temp_width, temp_height;
+
+ // get info about png
+ png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type,
+ NULL, NULL, NULL);
+
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ {
+ png_set_tRNS_to_alpha(png_ptr);
+ }
+
+ //set it to 32bit pixeldepth
+ png_color_8 sig_bit;
+ sig_bit.red = 32;
+ sig_bit.green = 32;
+ sig_bit.blue = 32;
+ // if the image has an alpha channel then
+ sig_bit.alpha = 32;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+
+ /* Add filler (or alpha) byte (before/after each RGB triplet) */
+ png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_bgr(png_ptr);
+
+ // convert indexed color to rgb
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png_ptr);
+
+ /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
+ //png_set_swap_alpha(png_ptr);
+
+ //libsquish only eats 32bit RGBA, must convert grayscale into this format
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ png_set_expand_gray_1_2_4_to_8(png_ptr);
+ png_set_gray_to_rgb(png_ptr);
+ }
+
+ // Update the png info struct.
+ png_read_update_info(png_ptr, info_ptr);
+
+ // Row size in bytes.
+ int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+ // glTexImage2d requires rows to be 4-byte aligned
+ // rowbytes += 3 - ((rowbytes-1) % 4);
+
+ // Allocate the image_data as a big block, to be given to opengl
+ png_byte * image_data;
+ image_data = (png_byte*)new png_byte[rowbytes * temp_height * sizeof(png_byte)+15];
+ if (image_data == NULL)
+ {
+ fprintf(stderr, "error: could not allocate memory for PNG image data\n");
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ return false;
+ }
+
+ // row_pointers is for pointing to image_data for reading the png with libpng
+ png_bytep * row_pointers = (png_bytep*) new png_bytep[temp_height * sizeof(png_bytep)];
+ if (row_pointers == NULL)
+ {
+ fprintf(stderr, "error: could not allocate memory for PNG row pointers\n");
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ delete [] image_data;
+ return false;
+ }
+
+ // set the individual row_pointers to point at the correct offsets of image_data
+ for (unsigned int i = 0; i < temp_height; i++)
+ {
+ row_pointers[i] = image_data + i * rowbytes;
+ }
+
+ // read the png into image_data through row_pointers
+ png_read_image(png_ptr, row_pointers);
+
+ DecodedFrame frame;
+
+ frame.rgbaImage.pixels = (char *)image_data;
+ frame.rgbaImage.height = temp_height;
+ frame.rgbaImage.width = temp_width;
+ frame.rgbaImage.bbp = 32;
+ frame.rgbaImage.pitch = 4 * temp_width;
+
+ frame.decoder = this;
+
+ frames.frameList.push_back(frame);
+ // clean up
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ delete [] row_pointers;
+ return true;
+}
+
+void PNGDecoder::FreeDecodedFrame(DecodedFrame &frame)
+{
+ delete [] frame.rgbaImage.pixels;
+}
+
+void PNGDecoder::FillSupportedExtensions()
+{
+ m_supportedExtensions.emplace_back(".png");
+}
diff --git a/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h
new file mode 100644
index 0000000..c7dba76
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "IDecoder.h"
+
+class PNGDecoder : public IDecoder
+{
+ public:
+ ~PNGDecoder() override = default;
+ bool CanDecode(const std::string &filename) override;
+ bool LoadFile(const std::string &filename, DecodedFrames &frames) override;
+ void FreeDecodedFrame(DecodedFrame &frame) override;
+ const char* GetImageFormatName() override { return "PNG"; }
+ const char* GetDecoderName() override { return "libpng"; }
+ protected:
+ void FillSupportedExtensions() override;
+};
diff --git a/tools/depends/native/TexturePacker/src/md5.cpp b/tools/depends/native/TexturePacker/src/md5.cpp
new file mode 100644
index 0000000..b9788dd
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/md5.cpp
@@ -0,0 +1,231 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h' header
+ * definitions; now uses stuff from dpkg's config.h.
+ * - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#include "md5.h"
+
+
+#ifdef WORDS_BIGENDIAN
+void
+byteSwap(uint32_t *buf, unsigned words)
+{
+ uint8_t *p = (uint8_t*)buf;
+
+ do {
+ *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
+ ((unsigned)p[1] << 8 | p[0]);
+ p += 4;
+ } while (--words);
+}
+#else
+#define byteSwap(buf,words)
+#endif
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+ (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void
+MD5Transform(uint32_t buf[4], uint32_t const in[16])
+{
+ uint32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bytes[0] = 0;
+ ctx->bytes[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, const uint8_t *buf, unsigned len)
+{
+ uint32_t t;
+
+ /* Update byte count */
+
+ t = ctx->bytes[0];
+ if ((ctx->bytes[0] = t + len) < t)
+ ctx->bytes[1]++; /* Carry from low to high */
+
+ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
+ if (t > len) {
+ memcpy((uint8_t*)ctx->in + 64 - t, buf, len);
+ return;
+ }
+ /* First chunk is an odd size */
+ memcpy((uint8_t*)ctx->in + 64 - t, buf, t);
+ byteSwap(ctx->in, 16);
+ MD5Transform(ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+
+ /* Process data in 64-byte chunks */
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteSwap(ctx->in, 16);
+ MD5Transform(ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(uint8_t digest[16], struct MD5Context *ctx)
+{
+ int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
+ uint8_t *p = (uint8_t*)ctx->in + count;
+
+ /* Set the first char of padding to 0x80. There is always room. */
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 56 bytes (-8..55) */
+ count = 56 - 1 - count;
+
+ if (count < 0) { /* Padding forces an extra block */
+ memset(p, 0, count + 8);
+ byteSwap(ctx->in, 16);
+ MD5Transform(ctx->buf, ctx->in);
+ p = (uint8_t*)ctx->in;
+ count = 56;
+ }
+ memset(p, 0, count);
+ byteSwap(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ctx->in[14] = ctx->bytes[0] << 3;
+ ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+ MD5Transform(ctx->buf, ctx->in);
+
+ byteSwap(ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+}
+
diff --git a/tools/depends/native/TexturePacker/src/md5.h b/tools/depends/native/TexturePacker/src/md5.h
new file mode 100644
index 0000000..76475bc
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/md5.h
@@ -0,0 +1,38 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h' header
+ * definitions; now uses stuff from dpkg's config.h.
+ * - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <cstring> /* for memcpy() */
+
+struct MD5Context
+{
+ uint32_t buf[4];
+ uint32_t bytes[2];
+ uint32_t in[16];
+};
+
+void MD5Init(struct MD5Context *ctx);
+void MD5Update(struct MD5Context *ctx, const uint8_t *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
+
diff --git a/tools/depends/native/Toolchain-Native.cmake.in b/tools/depends/native/Toolchain-Native.cmake.in
new file mode 100644
index 0000000..c5f5643
--- /dev/null
+++ b/tools/depends/native/Toolchain-Native.cmake.in
@@ -0,0 +1,79 @@
+set(NATIVEPREFIX "@prefix@/@tool_dir@")
+
+set(TARBALL_DIR "@use_tarballs@")
+
+set(OS "@build_os@")
+set(CMAKE_SYSTEM_PROCESSOR @host_cpu@)
+set(CPU "@use_buildcpu@")
+
+if(OS STREQUAL linux)
+ set(CMAKE_SYSTEM_NAME Linux)
+elseif(OS STREQUAL osx)
+ set(CMAKE_SYSTEM_NAME Darwin)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
+ if(CPU STREQUAL "arm")
+ set(CPU arm64)
+ endif()
+ if(CPU STREQUAL arm64)
+ set(CMAKE_OSX_DEPLOYMENT_TARGET 11.0)
+ else()
+ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.13)
+ endif()
+
+ set(CMAKE_OSX_SYSROOT "@host_sysroot@")
+endif()
+set(CMAKE_SYSTEM_VERSION 1)
+
+# specify the cross compiler
+set(CMAKE_C_COMPILER @CC_FOR_BUILD@)
+set(CMAKE_CXX_COMPILER @CXX_FOR_BUILD@)
+set(CMAKE_AR @AR_FOR_BUILD@ CACHE FILEPATH "Archiver")
+SET(CMAKE_AS @AS_FOR_BUILD@ CACHE FILEPATH "Assembler")
+set(CMAKE_LINKER @LD_FOR_BUILD@ CACHE FILEPATH "Linker")
+set(CMAKE_NM @NM_FOR_BUILD@ CACHE FILEPATH "Nm")
+set(CMAKE_STRIP @STRIP_FOR_BUILD@ CACHE PATH "strip binary" FORCE)
+set(CMAKE_OBJDUMP @OBJDUMP_FOR_BUILD@ CACHE FILEPATH "Objdump")
+set(CMAKE_RANLIB @RANLIB_FOR_BUILD@ CACHE FILEPATH "Ranlib")
+
+if(NOT "@use_ccache@" STREQUAL "")
+ set(CMAKE_CXX_COMPILER_LAUNCHER @CCACHE@)
+ set(CMAKE_C_COMPILER_LAUNCHER @CCACHE@)
+endif()
+
+set(CMAKE_C_FLAGS "@host_includes@ -I@prefix@/@tool_dir@/include")
+set(CMAKE_CXX_FLAGS "@host_cxxflags@ @host_includes@ -I@prefix@/@tool_dir@/include")
+set(CMAKE_EXE_LINKER_FLAGS "@host_includes@ -L@prefix@/@tool_dir@/lib")
+
+# where is the target environment
+set(CMAKE_FIND_ROOT_PATH @prefix@/@tool_dir@)
+set(CMAKE_LIBRARY_PATH @prefix@/@tool_dir@/lib)
+if(NOT "@use_toolchain@" STREQUAL "")
+ list(APPEND CMAKE_FIND_ROOT_PATH @use_toolchain@ @use_toolchain@/@use_host@ @use_toolchain@/@use_host@/sysroot @use_toolchain@/@use_host@/sysroot/usr @use_toolchain@/@use_host@/libc @use_toolchain@/lib/@use_host@/sysroot @use_toolchain@/usr @use_toolchain@/sysroot/usr)
+ set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH}:@use_toolchain@/usr/lib/@use_host@:@use_toolchain@/lib/@use_host@")
+endif()
+if(NOT "@host_sysroot@" STREQUAL "")
+ list(APPEND CMAKE_FIND_ROOT_PATH @host_sysroot@ @host_sysroot@/usr)
+endif()
+
+# search for programs in the build host directories
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+# for libraries and headers in the target directories
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_FRAMEWORK LAST)
+
+# common autoconf build tools
+find_program(AUTOCONF autoconf HINTS "${NATIVEPREFIX}/bin" REQUIRED)
+find_program(ACLOCAL aclocal HINTS "${NATIVEPREFIX}/bin" REQUIRED)
+find_program(AUTOHEADER autoheader HINTS "${NATIVEPREFIX}/bin" REQUIRED)
+find_program(AUTOMAKE automake HINTS "${NATIVEPREFIX}/bin" REQUIRED)
+find_program(AUTOM4TE autom4te HINTS "${NATIVEPREFIX}/bin" REQUIRED)
+find_program(AUTOPOINT autopoint HINTS "${NATIVEPREFIX}/bin" REQUIRED)
+find_program(AUTORECONF autoreconf HINTS "${NATIVEPREFIX}/bin" REQUIRED)
+find_program(LIBTOOL libtool HINTS "${NATIVEPREFIX}/bin" REQUIRED)
+find_program(LIBTOOLIZE libtoolize HINTS "${NATIVEPREFIX}/bin" REQUIRED)
+
+set(ENV{ACLOCAL_PATH} "${NATIVEPREFIX}/share/aclocal")
+set(ENV{PATH} "${NATIVEPREFIX}/bin:$ENV{PATH}")
diff --git a/tools/depends/native/autoconf-archive/Makefile b/tools/depends/native/autoconf-archive/Makefile
new file mode 100644
index 0000000..c1e599d
--- /dev/null
+++ b/tools/depends/native/autoconf-archive/Makefile
@@ -0,0 +1,39 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=autoconf-archive
+VERSION=2021.02.19
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=a968c355c3cf66d74dc5b452141afbdf763e84a6c43b12c25da9a08482910d6d57ba3952aaf270d8cd5fd8b9d2dadf2d7d943ae2e1b067d68b71d2738d881aa0
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+LIBDYLIB=$(PLATFORM)/bin/autoconf
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+
+$(LIBDYLIB): $(PLATFORM)
+ cd $(PLATFORM); $(CONFIGURE)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/autoconf/Makefile b/tools/depends/native/autoconf/Makefile
new file mode 100644
index 0000000..d0f08d8
--- /dev/null
+++ b/tools/depends/native/autoconf/Makefile
@@ -0,0 +1,40 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=autoconf
+VERSION=2.71
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=73d32b4adcbe24e3bafa9f43f59ed3b6efbd3de0f194e5ec90375f35da1199c583f5d3e89139b7edbad35171403709270e339ffa56a2ecb9b3123e9285021ff0
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+LIBDYLIB=$(PLATFORM)/bin/autoconf
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+
+$(LIBDYLIB): $(PLATFORM)
+ cd $(PLATFORM); $(CONFIGURE)
+ $(MAKE) -C $(PLATFORM) install
+# patch autoreconf to not use gtkdocize. Details: https://savannah.gnu.org/support/?110503
+ cd $(NATIVEPREFIX); sed -ie 's|$uses_gtkdoc = 1 if \$$macro eq "GTK_DOC_CHECK";|$uses_gtkdoc = 0; # if \$$macro eq "GTK_DOC_CHECK";|' bin/autoreconf
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/automake/01-fix-help2man-error.patch b/tools/depends/native/automake/01-fix-help2man-error.patch
new file mode 100644
index 0000000..e05e429
--- /dev/null
+++ b/tools/depends/native/automake/01-fix-help2man-error.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -703,7 +703,7 @@
+ update_mans = \
+ $(AM_V_GEN): \
+ && $(MKDIR_P) doc \
+- && ./pre-inst-env $(PERL) $(srcdir)/doc/help2man --output=$@
++ && ./pre-inst-env $(PERL) $(srcdir)/doc/help2man --output=$@ --no-discard-stderr
+
+ checklinkx = $(top_srcdir)/contrib/checklinkx
+ # that 4-second sleep seems to be what gnu.org likes.
diff --git a/tools/depends/native/automake/Makefile b/tools/depends/native/automake/Makefile
new file mode 100644
index 0000000..5e33556
--- /dev/null
+++ b/tools/depends/native/automake/Makefile
@@ -0,0 +1,39 @@
+include ../../Makefile.include
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile 01-fix-help2man-error.patch ../../download-files.include
+
+# lib name, version
+LIBNAME=automake
+VERSION=1.16.5
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=3084ae543aa3fb5a05104ffb2e66cfa9a53080f2343c44809707fd648516869511500dba50dae67ff10f92a1bf3b5a92b2a0fa01cda30adb69b9da03994d9d88
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(NATIVEPREFIX)
+
+LIBDYLIB=$(PLATFORM)/bin/automake
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); patch -p1 -i ../01-fix-help2man-error.patch
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/cmake/Makefile b/tools/depends/native/cmake/Makefile
new file mode 100644
index 0000000..1a4dc3e
--- /dev/null
+++ b/tools/depends/native/cmake/Makefile
@@ -0,0 +1,50 @@
+include ../../Makefile.include
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+APPNAME=cmake
+VERSION=3.21.3
+SOURCE=$(APPNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=0571b78443906c5ad51fb0fafbd32d565caf628cc150b1190802cb819e8497c108ea6b7ecaa03133df2dbbceb730696d24b4df38468c92088c769ce4076d9e9f
+include ../../download-files.include
+
+# configuration settings
+
+SETENV=CC="$(CC_FOR_BUILD)" CXX="$(CXX_FOR_BUILD)" LD=$(LD_FOR_BUILD) CFLAGS="$(NATIVE_CFLAGS)" \
+ CXXFLAGS="$(NATIVE_CXXFLAGS)" LDFLAGS="$(NATIVE_LDFLAGS)"
+
+ifeq ($(NATIVE_OS), osx)
+ SETENV+=SDKROOT=$(shell xcrun --show-sdk-path)
+endif
+
+CONFIGURE=./bootstrap --prefix=$(NATIVEPREFIX) --system-curl
+ifeq ($(USE_CCACHE), yes)
+ CONFIGURE+=--enable-ccache
+endif
+
+APP=$(PLATFORM)/bin/$(APPNAME)
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(SETENV) $(CONFIGURE)
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+ touch $@
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+
diff --git a/tools/depends/native/config.site.native.in b/tools/depends/native/config.site.native.in
new file mode 100644
index 0000000..35171a7
--- /dev/null
+++ b/tools/depends/native/config.site.native.in
@@ -0,0 +1,26 @@
+LD="${LD:-@LD_FOR_BUILD@}"
+CC="${CC:-@CCACHE@ @CC_FOR_BUILD@}"
+CXX="${CXX:-@CCACHE@ @CXX_FOR_BUILD@}"
+AR="${AR:-@AR_FOR_BUILD@}"
+RANLIB="${RANLIB:-@RANLIB_FOR_BUILD@}"
+AS="${AS:-@AS_FOR_BUILD@}"
+NM="${NM:-@NM_FOR_BUILD@}"
+STRIP="${STRIP:-@STRIP_FOR_BUILD@}"
+READELF="${READELF:-@READELF_FOR_BUILD@}"
+OBJDUMP="${OBJDUMP:-@OBJDUMP_FOR_BUILD@}"
+
+CFLAGS="@host_includes@ -I@prefix@/@tool_dir@/include $CFLAGS"
+LDFLAGS="@host_includes@ -L@prefix@/@tool_dir@/lib $LDFLAGS"
+CPPFLAGS="@host_includes@ -I@prefix@/@tool_dir@/include $CPPFLAGS"
+CXXFLAGS="@host_includes@ -I@prefix@/@tool_dir@/include $CXXFLAGS"
+
+PKG_CONFIG=@prefix@/@tool_dir@/bin/pkg-config
+export PKG_CONFIG_LIBDIR=@prefix@/@tool_dir@/lib/pkgconfig
+
+PATH=@prefix@/@tool_dir@/bin:$PATH
+if test -n "@use_build_toolchain@"; then
+ PATH=@use_build_toolchain@/usr/bin:@use_build_toolchain@/bin:$PATH
+fi
+
+LD_LIBRARY_PATH=@prefix@/@tool_dir@/lib:$LD_LIBRARY_PATH
+NASM=@prefix@/@tool_dir@/bin/nasm
diff --git a/tools/depends/native/dpkg/01-no-gnu-patch.patch b/tools/depends/native/dpkg/01-no-gnu-patch.patch
new file mode 100644
index 0000000..7536983
--- /dev/null
+++ b/tools/depends/native/dpkg/01-no-gnu-patch.patch
@@ -0,0 +1,10 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -74,7 +74,6 @@
+ DPKG_C_C99
+ AC_PROG_CXX
+ DPKG_CXX_CXX11
+-DPKG_PROG_PATCH
+ AC_CHECK_PROGS([DOXYGEN], [doxygen])
+ AC_CHECK_PROG([HAVE_DOT], [dot], [YES], [NO])
+ DPKG_PROG_PO4A
diff --git a/tools/depends/native/dpkg/02-perl-min-version.patch b/tools/depends/native/dpkg/02-perl-min-version.patch
new file mode 100644
index 0000000..4fb60ef
--- /dev/null
+++ b/tools/depends/native/dpkg/02-perl-min-version.patch
@@ -0,0 +1,11 @@
+--- a/m4/dpkg-progs.m4
++++ b/m4/dpkg-progs.m4
+@@ -7,7 +7,7 @@
+ # Locate perl interpreter in the path
+ AC_DEFUN([DPKG_PROG_PERL], [
+ AC_ARG_VAR([PERL], [Perl interpreter])dnl
+- m4_define([_PERL_MIN_VERSION], [5.20.2])
++ m4_define([_PERL_MIN_VERSION], [5.18.2])
+ AC_SUBST([PERL_MIN_VERSION], [_PERL_MIN_VERSION])
+ AC_CACHE_CHECK([for perl >= _PERL_MIN_VERSION], [ac_cv_path_PERL], [
+ AC_PATH_PROGS_FEATURE_CHECK([PERL], [perl], [
diff --git a/tools/depends/native/dpkg/03-lzma-compression.patch b/tools/depends/native/dpkg/03-lzma-compression.patch
new file mode 100644
index 0000000..c9bf535
--- /dev/null
+++ b/tools/depends/native/dpkg/03-lzma-compression.patch
@@ -0,0 +1,11 @@
+--- a/dpkg-deb/main.c
++++ b/dpkg-deb/main.c
+@@ -195,7 +195,7 @@
+ if (compress_params.type == COMPRESSOR_TYPE_UNKNOWN)
+ badusage(_("unknown compression type '%s'!"), value);
+ if (compress_params.type == COMPRESSOR_TYPE_LZMA)
+- badusage(_("obsolete compression type '%s'; use xz instead"), value);
++ warning(_("obsolete compression type '%s'; use xz instead"), value);
+ if (compress_params.type == COMPRESSOR_TYPE_BZIP2)
+ badusage(_("obsolete compression type '%s'; use xz or gzip instead"), value);
+ }
diff --git a/tools/depends/native/dpkg/Makefile b/tools/depends/native/dpkg/Makefile
new file mode 100644
index 0000000..08b94ca
--- /dev/null
+++ b/tools/depends/native/dpkg/Makefile
@@ -0,0 +1,45 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile 01-no-gnu-patch.patch 02-perl-min-version.patch 03-lzma-compression.patch ../../download-files.include
+
+# lib name, version
+LIBNAME=dpkg
+VERSION=1.19.7
+SOURCE=$(LIBNAME)_$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=9ca441dc265baf5359c71617aef1c57504a7097c26ea57108b88dadc511bfa9918fcc765d8c67cec9def9916c5df92d6cabe508446dbc7223a29b45260445e81
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX) --enable-static --disable-shared --disable-devel-docs \
+ --disable-linker-optimizations --disable-nls --disable-dselect --disable-start-stop-daemon \
+ ac_cv_header_libintl_h=no
+
+LIBDYLIB=$(PLATFORM)/dpkg-deb/dpkg-deb
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); patch -p1 -i ../01-no-gnu-patch.patch
+ cd $(PLATFORM); patch -p1 -i ../02-perl-min-version.patch
+ cd $(PLATFORM); patch -p1 -i ../03-lzma-compression.patch
+ cd $(PLATFORM); $(AUTORECONF) -vif
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM)/dpkg-deb install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/expat/EXPAT-VERSION b/tools/depends/native/expat/EXPAT-VERSION
new file mode 100644
index 0000000..ea1b164
--- /dev/null
+++ b/tools/depends/native/expat/EXPAT-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=expat
+VERSION=2.4.9
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=8508379b4915d84d50f3638678a90792179c98247d1cb5e6e6387d117af4dc148ac7031c1debea8b96e7b710ef436cf0dd5da91f3d22b8186a00cfafe1201169
diff --git a/tools/depends/native/expat/Makefile b/tools/depends/native/expat/Makefile
new file mode 100644
index 0000000..0a0b484
--- /dev/null
+++ b/tools/depends/native/expat/Makefile
@@ -0,0 +1,31 @@
+include ../../Makefile.include EXPAT-VERSION ../../download-files.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS=../../Makefile.include Makefile EXPAT-VERSION ../../download-files.include
+
+# configuration settings
+CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) ./conftools; CFLAGS="-fPIC" ./configure --prefix=$(PREFIX) --disable-shared
+
+LIBDYLIB=$(PLATFORM)/lib/.libs/lib$(LIBNAME).a
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/flatbuffers/Makefile b/tools/depends/native/flatbuffers/Makefile
new file mode 100644
index 0000000..6911d4c
--- /dev/null
+++ b/tools/depends/native/flatbuffers/Makefile
@@ -0,0 +1,68 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS =../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=flatbuffers
+VERSION=2.0.0
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=26a06b572c0e4c9685743bd2d2162ac7dcd74b9324624cc3f3ef5b154c0cee7c52a04b77cdc184245d2d6ae38dfdcc4fd66001c318aa8ca001d2bf1d85d66a89
+include ../../download-files.include
+
+APP=$(PLATFORM)/build-cmake/flatc
+
+# BUILD Notes
+# When we go c++17, flatbuffers has FLATBUFFERS_BUILD_CPP17 to enable
+# If we bump cmake min req to 3.16, enable FLATBUFFERS_ENABLE_PCH
+
+ifeq ($(USE_CCACHE), yes)
+ LAUNCHER=-DCMAKE_CXX_COMPILER_LAUNCHER=$(CCACHE)
+endif
+
+# Only this package uses CMake for build on native at the moment,
+# so there is no separate toolchain file. Still we have to unset
+# the CMAKE_TOOLCHAIN_FILE, which is part of $(CMAKE) and set to
+# the target toolchain file.
+CMAKE_OPTIONS := -DCMAKE_TOOLCHAIN_FILE= \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DFLATBUFFERS_CODE_COVERAGE=OFF \
+ -DFLATBUFFERS_BUILD_TESTS=OFF \
+ -DFLATBUFFERS_INSTALL=ON \
+ -DFLATBUFFERS_BUILD_FLATLIB=OFF \
+ -DFLATBUFFERS_BUILD_FLATC=ON \
+ -DFLATBUFFERS_BUILD_FLATHASH=OFF \
+ -DFLATBUFFERS_BUILD_GRPCTEST=OFF \
+ -DFLATBUFFERS_BUILD_SHAREDLIB=OFF \
+ -DCMAKE_C_COMPILER="$(CC_BINARY_FOR_BUILD)" \
+ -DCMAKE_CXX_COMPILER="$(CXX_BINARY_FOR_BUILD)" \
+ $(LAUNCHER) \
+ -DCMAKE_C_FLAGS="$(NATIVE_CFLAGS)" \
+ -DCMAKE_CXX_FLAGS="$(NATIVE_CXXFLAGS)" \
+ -DCMAKE_EXE_LINKER_FLAGS="$(NATIVE_LDFLAGS)" \
+ $(CMAKE_OPTIONS)
+BUILDDIR = $(PLATFORM)/build-cmake # 'build' conflicts with file BUILD on case-insensitive FS
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ mkdir -p $(BUILDDIR)
+ cd $(BUILDDIR); $(CMAKE) $(CMAKE_OPTIONS) ..
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(BUILDDIR)
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(BUILDDIR) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(BUILDDIR) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean:
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/gas-preprocessor/Makefile b/tools/depends/native/gas-preprocessor/Makefile
new file mode 100644
index 0000000..d257890
--- /dev/null
+++ b/tools/depends/native/gas-preprocessor/Makefile
@@ -0,0 +1,13 @@
+include ../../Makefile.include
+
+GASBIN=$(NATIVEPREFIX)/bin/gas-preprocessor.pl
+
+all: $(GASBIN)
+
+$(GASBIN):
+ mkdir -p $(NATIVEPREFIX)/bin
+ cp gas-preprocessor.pl $(GASBIN)
+
+clean:
+distclean::
+ rm -f $(GASBIN)
diff --git a/tools/depends/native/gas-preprocessor/README b/tools/depends/native/gas-preprocessor/README
new file mode 100644
index 0000000..2c8ab2b
--- /dev/null
+++ b/tools/depends/native/gas-preprocessor/README
@@ -0,0 +1,13 @@
+To configure Libav for iOS:
+
+./configure --enable-cross-compile --arch=arm --target-os=darwin --cc='clang -arch armv7' --sysroot=$(xcrun --sdk iphoneos --show-sdk-path) --cpu=cortex-a8 --enable-pic
+
+If deploying to all generations, it's recommended to do separate out-of-tree
+builds for each architecture, then lipo together the resulting libs. For
+instance, assuming separate builds in armv6 and armv7:
+
+lipo -create -arch armv6 armv6/libavcodec/libavcodec.a -arch armv7 armv7/libavcodec/libavcodec.a -output universal/libavcodec.a
+
+and similar for each library. Then in XCode, make sure to build for both armv6
+and armv7. If you only care about one generation (since the armv6 devices are
+too slow for instance), then lipo is unnecessary of course.
diff --git a/tools/depends/native/gas-preprocessor/VERSION b/tools/depends/native/gas-preprocessor/VERSION
new file mode 100644
index 0000000..90992e4
--- /dev/null
+++ b/tools/depends/native/gas-preprocessor/VERSION
@@ -0,0 +1,4 @@
+LIBNAME=gas-preprocessor
+BASE_URL=https://github.com/libav/gas-preprocessor
+COMMIT=d09971fad329d32df19f5bbafe88cf2f0ed04ed7
+COMMIT_DATE=2019/10/04
diff --git a/tools/depends/native/gas-preprocessor/gas-preprocessor.pl b/tools/depends/native/gas-preprocessor/gas-preprocessor.pl
new file mode 100755
index 0000000..9cc8b2c
--- /dev/null
+++ b/tools/depends/native/gas-preprocessor/gas-preprocessor.pl
@@ -0,0 +1,1213 @@
+#!/usr/bin/env perl
+# by David Conrad
+# This code is licensed under GPLv2 or later; go to gnu.org to read it
+# (not that it much matters for an asm preprocessor)
+# usage: set your assembler to be something like "perl gas-preprocessor.pl gcc"
+use strict;
+
+# Apple's gas is ancient and doesn't support modern preprocessing features like
+# .rept and has ugly macro syntax, among other things. Thus, this script
+# implements the subset of the gas preprocessor used by x264 and ffmpeg
+# that isn't supported by Apple's gas.
+
+my %canonical_arch = ("aarch64" => "aarch64", "arm64" => "aarch64",
+ "arm" => "arm",
+ "powerpc" => "powerpc", "ppc" => "powerpc");
+
+my %comments = ("aarch64" => '//',
+ "arm" => '@',
+ "powerpc" => '#');
+
+my @gcc_cmd;
+my @preprocess_c_cmd;
+
+my $comm;
+my $arch;
+my $as_type = "apple-gas";
+
+my $fix_unreq = $^O eq "darwin";
+my $force_thumb = 0;
+my $verbose = 0;
+
+my $arm_cond_codes = "eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo";
+
+my $usage_str = "
+$0\n
+Gas-preprocessor.pl converts assembler files using modern GNU as syntax for
+Apple's ancient gas version or clang's incompatible integrated assembler. The
+conversion is regularly tested for Libav, x264 and vlc. Other projects might
+use different features which are not correctly handled.
+Options for this program needs to be separated with ' -- ' from the assembler
+command. Following options are currently supported:
+ -help - this usage text
+ -arch - target architecture
+ -as-type - one value out of {{,apple-}{gas,clang},armasm}
+ -fix-unreq
+ -no-fix-unreq
+ -force-thumb - assemble as thumb regardless of the input source
+ (note, this is incomplete and only works for sources
+ it explicitly was tested with)
+ -verbose - print executed commands
+";
+
+sub usage() {
+ print $usage_str;
+}
+
+while (@ARGV) {
+ my $opt = shift;
+
+ if ($opt =~ /^-(no-)?fix-unreq$/) {
+ $fix_unreq = $1 ne "no-";
+ } elsif ($opt eq "-force-thumb") {
+ $force_thumb = 1;
+ } elsif ($opt eq "-verbose") {
+ $verbose = 1;
+ } elsif ($opt eq "-arch") {
+ $arch = shift;
+ die "unknown arch: '$arch'\n" if not exists $canonical_arch{$arch};
+ } elsif ($opt eq "-as-type") {
+ $as_type = shift;
+ die "unknown as type: '$as_type'\n" if $as_type !~ /^((apple-)?(gas|clang)|armasm)$/;
+ } elsif ($opt eq "-help") {
+ usage();
+ exit 0;
+ } elsif ($opt eq "--" ) {
+ @gcc_cmd = @ARGV;
+ } elsif ($opt =~ /^-/) {
+ die "option '$opt' is not known. See '$0 -help' for usage information\n";
+ } else {
+ push @gcc_cmd, $opt, @ARGV;
+ }
+ last if (@gcc_cmd);
+}
+
+if (grep /\.c$/, @gcc_cmd) {
+ # C file (inline asm?) - compile
+ @preprocess_c_cmd = (@gcc_cmd, "-S");
+} elsif (grep /\.[sS]$/, @gcc_cmd) {
+ # asm file, just do C preprocessor
+ @preprocess_c_cmd = (@gcc_cmd, "-E");
+} elsif (grep /-(v|h|-version|dumpversion)/, @gcc_cmd) {
+ # pass -v/--version along, used during probing. Matching '-v' might have
+ # uninteded results but it doesn't matter much if gas-preprocessor or
+ # the compiler fails.
+ print STDERR join(" ", @gcc_cmd)."\n" if $verbose;
+ exec(@gcc_cmd);
+} else {
+ die "Unrecognized input filetype";
+}
+if ($as_type eq "armasm") {
+
+ $preprocess_c_cmd[0] = "cpp";
+ push(@preprocess_c_cmd, "-undef");
+ # Normally a preprocessor for windows would predefine _WIN32,
+ # but we're using any generic system-agnostic preprocessor "cpp"
+ # with -undef (to avoid getting predefined variables from the host
+ # system in cross compilation cases), so manually define it here.
+ push(@preprocess_c_cmd, "-D_WIN32");
+
+ @preprocess_c_cmd = grep ! /^-nologo$/, @preprocess_c_cmd;
+ # Remove -ignore XX parameter pairs from preprocess_c_cmd
+ my $index = 1;
+ while ($index < $#preprocess_c_cmd) {
+ if ($preprocess_c_cmd[$index] eq "-ignore" and $index + 1 < $#preprocess_c_cmd) {
+ splice(@preprocess_c_cmd, $index, 2);
+ next;
+ }
+ $index++;
+ }
+ if (grep /^-MM$/, @preprocess_c_cmd) {
+ print STDERR join(" ", @preprocess_c_cmd)."\n" if $verbose;
+ system(@preprocess_c_cmd) == 0 or die "Error running preprocessor";
+ exit 0;
+ }
+}
+
+# if compiling, avoid creating an output file named '-.o'
+if ((grep /^-c$/, @gcc_cmd) && !(grep /^-o/, @gcc_cmd)) {
+ foreach my $i (@gcc_cmd) {
+ if ($i =~ /\.[csS]$/) {
+ my $outputfile = $i;
+ $outputfile =~ s/\.[csS]$/.o/;
+ push(@gcc_cmd, "-o");
+ push(@gcc_cmd, $outputfile);
+ last;
+ }
+ }
+}
+# replace only the '-o' argument with '-', avoids rewriting the make dependency
+# target specified with -MT to '-'
+my $index = 1;
+while ($index < $#preprocess_c_cmd) {
+ if ($preprocess_c_cmd[$index] eq "-o") {
+ $index++;
+ $preprocess_c_cmd[$index] = "-";
+ }
+ $index++;
+}
+
+my $tempfile;
+if ($as_type ne "armasm") {
+ @gcc_cmd = map { /\.[csS]$/ ? qw(-x assembler -) : $_ } @gcc_cmd;
+} else {
+ @preprocess_c_cmd = grep ! /^-c$/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-m/, @preprocess_c_cmd;
+
+ @preprocess_c_cmd = grep ! /^-G/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-W/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-Z/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-fp/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-EHsc$/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-O/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-oldit/, @preprocess_c_cmd;
+
+ @gcc_cmd = grep ! /^-G/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-W/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-Z/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-fp/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-EHsc$/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-O/, @gcc_cmd;
+
+ my @outfiles = grep /\.(o|obj)$/, @gcc_cmd;
+ $tempfile = $outfiles[0].".asm";
+
+ # Remove most parameters from gcc_cmd, which actually is the armasm command,
+ # which doesn't support any of the common compiler/preprocessor options.
+ @gcc_cmd = grep ! /^-D/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-U/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-m/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-M/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-c$/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-I/, @gcc_cmd;
+ @gcc_cmd = map { /\.S$/ ? $tempfile : $_ } @gcc_cmd;
+}
+
+# detect architecture from gcc binary name
+if (!$arch) {
+ if ($gcc_cmd[0] =~ /(arm64|aarch64|arm|powerpc|ppc)/) {
+ $arch = $1;
+ } else {
+ # look for -arch flag
+ foreach my $i (1 .. $#gcc_cmd-1) {
+ if ($gcc_cmd[$i] eq "-arch" and
+ $gcc_cmd[$i+1] =~ /(arm64|aarch64|arm|powerpc|ppc)/) {
+ $arch = $1;
+ }
+ }
+ }
+}
+
+# assume we're not cross-compiling if no -arch or the binary doesn't have the arch name
+$arch = qx/arch/ if (!$arch);
+
+die "Unknown target architecture '$arch'" if not exists $canonical_arch{$arch};
+
+$arch = $canonical_arch{$arch};
+$comm = $comments{$arch};
+my $inputcomm = $comm;
+$comm = ";" if $as_type =~ /armasm/;
+
+my %ppc_spr = (ctr => 9,
+ vrsave => 256);
+
+print STDERR join(" ", @preprocess_c_cmd)."\n" if $verbose;
+open(INPUT, "-|", @preprocess_c_cmd) || die "Error running preprocessor";
+
+if ($ENV{GASPP_DEBUG}) {
+ open(ASMFILE, ">&STDOUT");
+} else {
+ if ($as_type ne "armasm") {
+ print STDERR join(" ", @gcc_cmd)."\n" if $verbose;
+ open(ASMFILE, "|-", @gcc_cmd) or die "Error running assembler";
+ } else {
+ open(ASMFILE, ">", $tempfile);
+ }
+}
+
+my $current_macro = '';
+my $macro_level = 0;
+my $rept_level = 0;
+my %macro_lines;
+my %macro_args;
+my %macro_args_default;
+my $macro_count = 0;
+my $altmacro = 0;
+my $in_irp = 0;
+
+my $num_repts;
+my @rept_lines;
+
+my @irp_args;
+my $irp_param;
+
+my @ifstack;
+
+my %symbols;
+
+my @sections;
+
+my %literal_labels; # for ldr <reg>, =<expr>
+my $literal_num = 0;
+my $literal_expr = ".word";
+$literal_expr = ".quad" if $arch eq "aarch64";
+
+my $thumb = 0;
+
+my %thumb_labels;
+my %call_targets;
+my %import_symbols;
+
+my %neon_alias_reg;
+my %neon_alias_type;
+
+my $temp_label_next = 0;
+my %last_temp_labels;
+my %next_temp_labels;
+
+my %labels_seen;
+
+my %aarch64_req_alias;
+
+if ($force_thumb) {
+ parse_line(".thumb\n");
+}
+
+# pass 1: parse .macro
+# note that the handling of arguments is probably overly permissive vs. gas
+# but it should be the same for valid cases
+while (<INPUT>) {
+ # remove lines starting with '#', preprocessing is done, '#' at start of
+ # the line indicates a comment for all supported archs (aarch64, arm, ppc
+ # and x86). Also strips line number comments but since they are off anyway
+ # it is no loss.
+ s/^\s*#.*$//;
+ # remove all comments (to avoid interfering with evaluating directives)
+ s/(?<!\\)$inputcomm.*//x;
+ # Strip out windows linefeeds
+ s/\r$//;
+
+ foreach my $subline (split(";", $_)) {
+ # Add newlines at the end of lines that don't already have one
+ chomp $subline;
+ $subline .= "\n";
+ parse_line($subline);
+ }
+}
+
+sub eval_expr {
+ my $expr = $_[0];
+ while ($expr =~ /([A-Za-z._][A-Za-z0-9._]*)/g) {
+ my $sym = $1;
+ $expr =~ s/$sym/($symbols{$sym})/ if defined $symbols{$sym};
+ }
+ eval $expr;
+}
+
+sub handle_if {
+ my $line = $_[0];
+ # handle .if directives; apple's assembler doesn't support important non-basic ones
+ # evaluating them is also needed to handle recursive macros
+ if ($line =~ /\.if(n?)([a-z]*)\s+(.*)/) {
+ my $result = $1 eq "n";
+ my $type = $2;
+ my $expr = $3;
+
+ if ($type eq "b") {
+ $expr =~ s/\s//g;
+ $result ^= $expr eq "";
+ } elsif ($type eq "c") {
+ if ($expr =~ /(.*)\s*,\s*(.*)/) {
+ $result ^= $1 eq $2;
+ } else {
+ die "argument to .ifc not recognized";
+ }
+ } elsif ($type eq "") {
+ $result ^= eval_expr($expr) != 0;
+ } elsif ($type eq "eq") {
+ $result = eval_expr($expr) == 0;
+ } elsif ($type eq "lt") {
+ $result = eval_expr($expr) < 0;
+ } else {
+ chomp($line);
+ die "unhandled .if varient. \"$line\"";
+ }
+ push (@ifstack, $result);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+sub parse_if_line {
+ my $line = $_[0];
+
+ # evaluate .if blocks
+ if (scalar(@ifstack)) {
+ # Don't evaluate any new if statements if we're within
+ # a repetition or macro - they will be evaluated once
+ # the repetition is unrolled or the macro is expanded.
+ if (scalar(@rept_lines) == 0 and $macro_level == 0) {
+ if ($line =~ /\.endif/) {
+ pop(@ifstack);
+ return 1;
+ } elsif ($line =~ /\.elseif\s+(.*)/) {
+ if ($ifstack[-1] == 0) {
+ $ifstack[-1] = !!eval_expr($1);
+ } elsif ($ifstack[-1] > 0) {
+ $ifstack[-1] = -$ifstack[-1];
+ }
+ return 1;
+ } elsif ($line =~ /\.else/) {
+ $ifstack[-1] = !$ifstack[-1];
+ return 1;
+ } elsif (handle_if($line)) {
+ return 1;
+ }
+ }
+
+ # discard lines in false .if blocks
+ foreach my $i (0 .. $#ifstack) {
+ if ($ifstack[$i] <= 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+sub parse_line {
+ my $line = $_[0];
+
+ return if (parse_if_line($line));
+
+ if (scalar(@rept_lines) == 0) {
+ if ($line =~ /\.macro/) {
+ $macro_level++;
+ if ($macro_level > 1 && !$current_macro) {
+ die "nested macros but we don't have master macro";
+ }
+ } elsif ($line =~ /\.endm/) {
+ $macro_level--;
+ if ($macro_level < 0) {
+ die "unmatched .endm";
+ } elsif ($macro_level == 0) {
+ $current_macro = '';
+ return;
+ }
+ }
+ }
+
+ if ($macro_level == 0) {
+ if ($line =~ /\.(rept|irp)/) {
+ $rept_level++;
+ } elsif ($line =~ /.endr/) {
+ $rept_level--;
+ }
+ }
+
+ if ($macro_level > 1) {
+ push(@{$macro_lines{$current_macro}}, $line);
+ } elsif (scalar(@rept_lines) and $rept_level >= 1) {
+ push(@rept_lines, $line);
+ } elsif ($macro_level == 0) {
+ expand_macros($line);
+ } else {
+ if ($line =~ /\.macro\s+([\d\w\.]+)\s*,?\s*(.*)/) {
+ $current_macro = $1;
+
+ # commas in the argument list are optional, so only use whitespace as the separator
+ my $arglist = $2;
+ $arglist =~ s/,/ /g;
+
+ my @args = split(/\s+/, $arglist);
+ foreach my $i (0 .. $#args) {
+ my @argpair = split(/=/, $args[$i]);
+ $macro_args{$current_macro}[$i] = $argpair[0];
+ $argpair[0] =~ s/:vararg$//;
+ $macro_args_default{$current_macro}{$argpair[0]} = $argpair[1];
+ }
+ # ensure %macro_lines has the macro name added as a key
+ $macro_lines{$current_macro} = [];
+
+ } elsif ($current_macro) {
+ push(@{$macro_lines{$current_macro}}, $line);
+ } else {
+ die "macro level without a macro name";
+ }
+ }
+}
+
+sub handle_set {
+ my $line = $_[0];
+ if ($line =~ /\.(?:set|equ)\s+(\S*)\s*,\s*(.*)/) {
+ $symbols{$1} = eval_expr($2);
+ return 1;
+ }
+ return 0;
+}
+
+sub expand_macros {
+ my $line = $_[0];
+
+ # handle .if directives; apple's assembler doesn't support important non-basic ones
+ # evaluating them is also needed to handle recursive macros
+ if (handle_if($line)) {
+ return;
+ }
+
+ if (/\.purgem\s+([\d\w\.]+)/) {
+ delete $macro_lines{$1};
+ delete $macro_args{$1};
+ delete $macro_args_default{$1};
+ return;
+ }
+
+ if ($line =~ /\.altmacro/) {
+ $altmacro = 1;
+ return;
+ }
+
+ if ($line =~ /\.noaltmacro/) {
+ $altmacro = 0;
+ return;
+ }
+
+ $line =~ s/\%([^,]*)/eval_expr($1)/eg if $altmacro;
+
+ # Strip out the .set lines from the armasm output
+ return if (handle_set($line) and $as_type eq "armasm");
+
+ if ($line =~ /\.rept\s+(.*)/) {
+ $num_repts = $1;
+ @rept_lines = ("\n");
+
+ # handle the possibility of repeating another directive on the same line
+ # .endr on the same line is not valid, I don't know if a non-directive is
+ if ($num_repts =~ s/(\.\w+.*)//) {
+ push(@rept_lines, "$1\n");
+ }
+ $num_repts = eval_expr($num_repts);
+ } elsif ($line =~ /\.irp\s+([\d\w\.]+)\s*(.*)/) {
+ $in_irp = 1;
+ $num_repts = 1;
+ @rept_lines = ("\n");
+ $irp_param = $1;
+
+ # only use whitespace as the separator
+ my $irp_arglist = $2;
+ $irp_arglist =~ s/,/ /g;
+ $irp_arglist =~ s/^\s+//;
+ @irp_args = split(/\s+/, $irp_arglist);
+ } elsif ($line =~ /\.irpc\s+([\d\w\.]+)\s*(.*)/) {
+ $in_irp = 1;
+ $num_repts = 1;
+ @rept_lines = ("\n");
+ $irp_param = $1;
+
+ my $irp_arglist = $2;
+ $irp_arglist =~ s/,/ /g;
+ $irp_arglist =~ s/^\s+//;
+ @irp_args = split(//, $irp_arglist);
+ } elsif ($line =~ /\.endr/) {
+ my @prev_rept_lines = @rept_lines;
+ my $prev_in_irp = $in_irp;
+ my @prev_irp_args = @irp_args;
+ my $prev_irp_param = $irp_param;
+ my $prev_num_repts = $num_repts;
+ @rept_lines = ();
+ $in_irp = 0;
+ @irp_args = '';
+
+ if ($prev_in_irp != 0) {
+ foreach my $i (@prev_irp_args) {
+ foreach my $origline (@prev_rept_lines) {
+ my $line = $origline;
+ $line =~ s/\\$prev_irp_param/$i/g;
+ $line =~ s/\\\(\)//g; # remove \()
+ parse_line($line);
+ }
+ }
+ } else {
+ for (1 .. $prev_num_repts) {
+ foreach my $origline (@prev_rept_lines) {
+ my $line = $origline;
+ parse_line($line);
+ }
+ }
+ }
+ } elsif ($line =~ /(\S+:|)\s*([\w\d\.]+)\s*(.*)/ && exists $macro_lines{$2}) {
+ handle_serialized_line($1);
+ my $macro = $2;
+
+ # commas are optional here too, but are syntactically important because
+ # parameters can be blank
+ my @arglist = split(/,/, $3);
+ my @args;
+ my @args_seperator;
+
+ my $comma_sep_required = 0;
+ foreach (@arglist) {
+ # allow arithmetic/shift operators in macro arguments
+ $_ =~ s/\s*(\+|-|\*|\/|<<|>>|<|>)\s*/$1/g;
+
+ my @whitespace_split = split(/\s+/, $_);
+ if (!@whitespace_split) {
+ push(@args, '');
+ push(@args_seperator, '');
+ } else {
+ foreach (@whitespace_split) {
+ #print ("arglist = \"$_\"\n");
+ if (length($_)) {
+ push(@args, $_);
+ my $sep = $comma_sep_required ? "," : " ";
+ push(@args_seperator, $sep);
+ #print ("sep = \"$sep\", arg = \"$_\"\n");
+ $comma_sep_required = 0;
+ }
+ }
+ }
+
+ $comma_sep_required = 1;
+ }
+
+ my %replacements;
+ if ($macro_args_default{$macro}){
+ %replacements = %{$macro_args_default{$macro}};
+ }
+
+ # construct hashtable of text to replace
+ foreach my $i (0 .. $#args) {
+ my $argname = $macro_args{$macro}[$i];
+ my @macro_args = @{ $macro_args{$macro} };
+ if ($args[$i] =~ m/=/) {
+ # arg=val references the argument name
+ # XXX: I'm not sure what the expected behaviour if a lot of
+ # these are mixed with unnamed args
+ my @named_arg = split(/=/, $args[$i]);
+ $replacements{$named_arg[0]} = $named_arg[1];
+ } elsif ($i > $#{$macro_args{$macro}}) {
+ # more args given than the macro has named args
+ # XXX: is vararg allowed on arguments before the last?
+ $argname = $macro_args{$macro}[-1];
+ if ($argname =~ s/:vararg$//) {
+ #print "macro = $macro, args[$i] = $args[$i], args_seperator=@args_seperator, argname = $argname, arglist[$i] = $arglist[$i], arglist = @arglist, args=@args, macro_args=@macro_args\n";
+ #$replacements{$argname} .= ", $args[$i]";
+ $replacements{$argname} .= "$args_seperator[$i] $args[$i]";
+ } else {
+ die "Too many arguments to macro $macro";
+ }
+ } else {
+ $argname =~ s/:vararg$//;
+ $replacements{$argname} = $args[$i];
+ }
+ }
+
+ my $count = $macro_count++;
+
+ # apply replacements as regex
+ foreach (@{$macro_lines{$macro}}) {
+ my $macro_line = $_;
+ # do replacements by longest first, this avoids wrong replacement
+ # when argument names are subsets of each other
+ foreach (reverse sort {length $a <=> length $b} keys %replacements) {
+ $macro_line =~ s/\\$_/$replacements{$_}/g;
+ }
+ if ($altmacro) {
+ foreach (reverse sort {length $a <=> length $b} keys %replacements) {
+ $macro_line =~ s/\b$_\b/$replacements{$_}/g;
+ }
+ }
+ $macro_line =~ s/\\\@/$count/g;
+ $macro_line =~ s/\\\(\)//g; # remove \()
+ parse_line($macro_line);
+ }
+ } else {
+ handle_serialized_line($line);
+ }
+}
+
+sub is_arm_register {
+ my $name = $_[0];
+ if ($name eq "lr" or
+ $name eq "ip" or
+ $name =~ /^[rav]\d+$/) {
+ return 1;
+ }
+ return 0;
+}
+
+sub is_aarch64_register {
+ my $name = $_[0];
+ if ($name =~ /^[xw]\d+$/) {
+ return 1;
+ }
+ return 0;
+}
+
+sub handle_local_label {
+ my $line = $_[0];
+ my $num = $_[1];
+ my $dir = $_[2];
+ my $target = "$num$dir";
+ if ($dir eq "b") {
+ $line =~ s/\b$target\b/$last_temp_labels{$num}/g;
+ } else {
+ my $name = "temp_label_$temp_label_next";
+ $temp_label_next++;
+ push(@{$next_temp_labels{$num}}, $name);
+ $line =~ s/\b$target\b/$name/g;
+ }
+ return $line;
+}
+
+sub handle_serialized_line {
+ my $line = $_[0];
+
+ # handle .previous (only with regard to .section not .subsection)
+ if ($line =~ /\.(section|text|const_data)/) {
+ push(@sections, $line);
+ } elsif ($line =~ /\.previous/) {
+ if (!$sections[-2]) {
+ die ".previous without a previous section";
+ }
+ $line = $sections[-2];
+ push(@sections, $line);
+ }
+
+ $thumb = 1 if $line =~ /\.code\s+16|\.thumb/;
+ $thumb = 0 if $line =~ /\.code\s+32|\.arm/;
+
+ # handle ldr <reg>, =<expr>
+ if ($line =~ /(.*)\s*ldr([\w\s\d]+)\s*,\s*=(.*)/ and $as_type ne "armasm") {
+ my $label = $literal_labels{$3};
+ if (!$label) {
+ $label = "Literal_$literal_num";
+ $literal_num++;
+ $literal_labels{$3} = $label;
+ }
+ $line = "$1 ldr$2, $label\n";
+ } elsif ($line =~ /\.ltorg/ and $as_type ne "armasm") {
+ $line .= ".align 2\n";
+ foreach my $literal (keys %literal_labels) {
+ $line .= "$literal_labels{$literal}:\n $literal_expr $literal\n";
+ }
+ %literal_labels = ();
+ }
+
+ # handle GNU as pc-relative relocations for adrp/add
+ if ($line =~ /(.*)\s*adrp([\w\s\d]+)\s*,\s*#?:pg_hi21:([^\s]+)/ and $as_type =~ /^apple-/) {
+ $line = "$1 adrp$2, ${3}\@PAGE\n";
+ } elsif ($line =~ /(.*)\s*add([\w\s\d]+)\s*,([\w\s\d]+)\s*,\s*#?:lo12:([^\s]+)/ and $as_type =~ /^apple-/) {
+ $line = "$1 add$2, $3, ${4}\@PAGEOFF\n";
+ }
+
+ # thumb add with large immediate needs explicit add.w
+ if ($thumb and $line =~ /add\s+.*#([^@]+)/) {
+ $line =~ s/add/add.w/ if eval_expr($1) > 255;
+ }
+
+ # mach-o local symbol names start with L (no dot)
+ $line =~ s/(?<!\w)\.(L\w+)/$1/g;
+
+ # recycle the '.func' directive for '.thumb_func'
+ if ($thumb and $as_type =~ /^apple-/) {
+ $line =~ s/\.func/.thumb_func/x;
+ }
+
+ if ($thumb and $line =~ /^\s*(\w+)\s*:/) {
+ $thumb_labels{$1}++;
+ }
+
+ if ($as_type =~ /^apple-/ and
+ $line =~ /^\s*((\w+\s*:\s*)?bl?x?(..)?(?:\.w)?|\.global)\s+(\w+)/) {
+ my $cond = $3;
+ my $label = $4;
+ # Don't interpret e.g. bic as b<cc> with ic as conditional code
+ if ($cond =~ /^(|$arm_cond_codes)$/) {
+ if (exists $thumb_labels{$label}) {
+ print ASMFILE ".thumb_func $label\n";
+ } else {
+ $call_targets{$label}++;
+ }
+ }
+ }
+
+ # @l -> lo16() @ha -> ha16()
+ $line =~ s/,\s+([^,]+)\@l\b/, lo16($1)/g;
+ $line =~ s/,\s+([^,]+)\@ha\b/, ha16($1)/g;
+
+ # move to/from SPR
+ if ($line =~ /(\s+)(m[ft])([a-z]+)\s+(\w+)/ and exists $ppc_spr{$3}) {
+ if ($2 eq 'mt') {
+ $line = "$1${2}spr $ppc_spr{$3}, $4\n";
+ } else {
+ $line = "$1${2}spr $4, $ppc_spr{$3}\n";
+ }
+ }
+
+ if ($line =~ /\.unreq\s+(.*)/) {
+ if (defined $neon_alias_reg{$1}) {
+ delete $neon_alias_reg{$1};
+ delete $neon_alias_type{$1};
+ return;
+ } elsif (defined $aarch64_req_alias{$1}) {
+ delete $aarch64_req_alias{$1};
+ return;
+ }
+ }
+ # old gas versions store upper and lower case names on .req,
+ # but they remove only one on .unreq
+ if ($fix_unreq) {
+ if ($line =~ /\.unreq\s+(.*)/) {
+ $line = ".unreq " . lc($1) . "\n";
+ $line .= ".unreq " . uc($1) . "\n";
+ }
+ }
+
+ if ($line =~ /(\w+)\s+\.(dn|qn)\s+(\w+)(?:\.(\w+))?(\[\d+\])?/) {
+ $neon_alias_reg{$1} = "$3$5";
+ $neon_alias_type{$1} = $4;
+ return;
+ }
+ if (scalar keys %neon_alias_reg > 0 && $line =~ /^\s+v\w+/) {
+ # This line seems to possibly have a neon instruction
+ foreach (keys %neon_alias_reg) {
+ my $alias = $_;
+ # Require the register alias to match as an invididual word, not as a substring
+ # of a larger word-token.
+ if ($line =~ /\b$alias\b/) {
+ $line =~ s/\b$alias\b/$neon_alias_reg{$alias}/g;
+ # Add the type suffix. If multiple aliases match on the same line,
+ # only do this replacement the first time (a vfoo.bar string won't match v\w+).
+ $line =~ s/^(\s+)(v\w+)(\s+)/$1$2.$neon_alias_type{$alias}$3/;
+ }
+ }
+ }
+
+ if ($arch eq "aarch64" or $as_type eq "armasm") {
+ # clang's integrated aarch64 assembler in Xcode 5 does not support .req/.unreq
+ if ($line =~ /\b(\w+)\s+\.req\s+(\w+)\b/) {
+ $aarch64_req_alias{$1} = $2;
+ return;
+ }
+ foreach (keys %aarch64_req_alias) {
+ my $alias = $_;
+ # recursively resolve aliases
+ my $resolved = $aarch64_req_alias{$alias};
+ while (defined $aarch64_req_alias{$resolved}) {
+ $resolved = $aarch64_req_alias{$resolved};
+ }
+ $line =~ s/\b$alias\b/$resolved/g;
+ }
+ }
+ if ($arch eq "aarch64") {
+ # fix missing aarch64 instructions in Xcode 5.1 (beta3)
+ # mov with vector arguments is not supported, use alias orr instead
+ if ($line =~ /^(\d+:)?\s*mov\s+(v\d[\.{}\[\]\w]+),\s*(v\d[\.{}\[\]\w]+)\b\s*$/) {
+ $line = "$1 orr $2, $3, $3\n";
+ }
+ # movi 16, 32 bit shifted variant, shift is optional
+ if ($line =~ /^(\d+:)?\s*movi\s+(v[0-3]?\d\.(?:2|4|8)[hsHS])\s*,\s*(#\w+)\b\s*$/) {
+ $line = "$1 movi $2, $3, lsl #0\n";
+ }
+ # Xcode 5 misses the alias uxtl. Replace it with the more general ushll.
+ # Clang 3.4 misses the alias sxtl too. Replace it with the more general sshll.
+ # armasm64 also misses these instructions.
+ if ($line =~ /^(\d+:)?\s*(s|u)xtl(2)?\s+(v[0-3]?\d\.[248][hsdHSD])\s*,\s*(v[0-3]?\d\.(?:2|4|8|16)[bhsBHS])\b\s*$/) {
+ $line = "$1 $2shll$3 $4, $5, #0\n";
+ }
+ # clang 3.4 and armasm64 do not automatically use shifted immediates in add/sub
+ if (($as_type eq "clang" or $as_type eq "armasm") and
+ $line =~ /^(\d+:)?(\s*(?:add|sub)s?) ([^#l]+)#([\d\+\-\*\/ <>]+)\s*$/) {
+ my $imm = eval $4;
+ if ($imm > 4095 and not ($imm & 4095)) {
+ $line = "$1 $2 $3#" . ($imm >> 12) . ", lsl #12\n";
+ }
+ }
+ if ($ENV{GASPP_FIX_XCODE5}) {
+ if ($line =~ /^\s*bsl\b/) {
+ $line =~ s/\b(bsl)(\s+v[0-3]?\d\.(\w+))\b/$1.$3$2/;
+ $line =~ s/\b(v[0-3]?\d)\.$3\b/$1/g;
+ }
+ if ($line =~ /^\s*saddl2?\b/) {
+ $line =~ s/\b(saddl2?)(\s+v[0-3]?\d\.(\w+))\b/$1.$3$2/;
+ $line =~ s/\b(v[0-3]?\d)\.\w+\b/$1/g;
+ }
+ if ($line =~ /^\s*dup\b.*\]$/) {
+ $line =~ s/\bdup(\s+v[0-3]?\d)\.(\w+)\b/dup.$2$1/g;
+ $line =~ s/\b(v[0-3]?\d)\.[bhsdBHSD](\[\d\])$/$1$2/g;
+ }
+ }
+ }
+
+ if ($as_type eq "armasm") {
+ # Also replace variables set by .set
+ foreach (keys %symbols) {
+ my $sym = $_;
+ $line =~ s/\b$sym\b/$symbols{$sym}/g;
+ }
+
+ # Handle function declarations and keep track of the declared labels
+ if ($line =~ s/^\s*\.func\s+(\w+)/$1 PROC/) {
+ $labels_seen{$1} = 1;
+ }
+
+ if ($line =~ s/^\s*(\d+)://) {
+ # Convert local labels into unique labels. armasm (at least in
+ # RVCT) has something similar, but still different enough.
+ # By converting to unique labels we avoid any possible
+ # incompatibilities.
+
+ my $num = $1;
+ foreach (@{$next_temp_labels{$num}}) {
+ $line = "$_\n" . $line;
+ }
+ @next_temp_labels{$num} = ();
+ my $name = "temp_label_$temp_label_next";
+ $temp_label_next++;
+ # The matching regexp above removes the label from the start of
+ # the line (which might contain an instruction as well), readd
+ # it on a separate line above it.
+ $line = "$name:\n" . $line;
+ $last_temp_labels{$num} = $name;
+ }
+
+ if ($line =~ s/^\s*(\w+):/$1/) {
+ # Skip labels that have already been declared with a PROC,
+ # labels must not be declared multiple times.
+ return if (defined $labels_seen{$1});
+ $labels_seen{$1} = 1;
+ } elsif ($line !~ /(\w+) PROC/) {
+ # If not a label, make sure the line starts with whitespace,
+ # otherwise ms armasm interprets it incorrectly.
+ $line =~ s/^[\.\w]/\t$&/;
+ }
+
+
+ # Check branch instructions
+ if ($line =~ /(?:^|\n)\s*(\w+\s*:\s*)?(bl?x?\.?([^\s]{2})?(\.w)?)\s+(\w+)/) {
+ my $instr = $2;
+ my $cond = $3;
+ my $width = $4;
+ my $target = $5;
+ # Don't interpret e.g. bic as b<cc> with ic as conditional code
+ if ($cond !~ /^(|$arm_cond_codes)$/) {
+ # Not actually a branch
+ } elsif ($target =~ /^(\d+)([bf])$/) {
+ # The target is a local label
+ $line = handle_local_label($line, $1, $2);
+ $line =~ s/\b$instr\b/$&.w/ if $width eq "" and $arch eq "arm";
+ } elsif (($arch eq "arm" and !is_arm_register($target)) or
+ ($arch eq "aarch64" and !is_aarch64_register($target))) {
+ $call_targets{$target}++;
+ }
+ } elsif ($line =~ /(?:^|\n)\s*(\w+\s*:\s*)?(cbn?z|adr|tbz)\s+(\w+)\s*,(\s*#\d+\s*,)?\s*(\w+)/) {
+ my $instr = $2;
+ my $reg = $3;
+ my $bit = $4;
+ my $target = $5;
+ if ($target =~ /^(\d+)([bf])$/) {
+ # The target is a local label
+ $line = handle_local_label($line, $1, $2);
+ } else {
+ $call_targets{$target}++;
+ }
+ # Convert tbz with a wX register into an xX register,
+ # due to armasm64 bugs/limitations.
+ if ($instr eq "tbz" and $reg =~ /w\d+/) {
+ my $xreg = $reg;
+ $xreg =~ s/w/x/;
+ $line =~ s/\b$reg\b/$xreg/;
+ }
+ } elsif ($line =~ /^\s*.h?word.*\b\d+[bf]\b/) {
+ while ($line =~ /\b(\d+)([bf])\b/g) {
+ $line = handle_local_label($line, $1, $2);
+ }
+ }
+
+ # ALIGN in armasm syntax is the actual number of bytes
+ if ($line =~ /\.(?:p2)?align\s+(\d+)/) {
+ my $align = 1 << $1;
+ $line =~ s/\.(?:p2)?align\s+(\d+)/ALIGN $align/;
+ }
+ # Convert gas style [r0, :128] into armasm [r0@128] alignment specification
+ $line =~ s/\[([^\[,]+),?\s*:(\d+)\]/[$1\@$2]/g;
+
+ # armasm treats logical values {TRUE} and {FALSE} separately from
+ # numeric values - logical operators and values can't be intermixed
+ # with numerical values. Evaluate !<number> and (a <> b) into numbers,
+ # let the assembler evaluate the rest of the expressions. This current
+ # only works for cases when ! and <> are used with actual constant numbers,
+ # we don't evaluate subexpressions here.
+
+ # Evaluate !<number>
+ while ($line =~ /!\s*(\d+)/g) {
+ my $val = ($1 != 0) ? 0 : 1;
+ $line =~ s/!(\d+)/$val/;
+ }
+ # Evaluate (a > b)
+ while ($line =~ /\(\s*(\d+)\s*([<>])\s*(\d+)\s*\)/) {
+ my $val;
+ if ($2 eq "<") {
+ $val = ($1 < $3) ? 1 : 0;
+ } else {
+ $val = ($1 > $3) ? 1 : 0;
+ }
+ $line =~ s/\(\s*(\d+)\s*([<>])\s*(\d+)\s*\)/$val/;
+ }
+
+ if ($arch eq "arm") {
+ # Change a movw... #:lower16: into a mov32 pseudoinstruction
+ $line =~ s/^(\s*)movw(\s+\w+\s*,\s*)\#:lower16:(.*)$/$1mov32$2$3/;
+ # and remove the following, matching movt completely
+ $line =~ s/^\s*movt\s+\w+\s*,\s*\#:upper16:.*$//;
+
+ if ($line =~ /^\s*mov32\s+\w+,\s*([a-zA-Z]\w*)/) {
+ $import_symbols{$1}++;
+ }
+
+ # Misc bugs/deficiencies:
+ # armasm seems unable to parse e.g. "vmov s0, s1" without a type
+ # qualifier, thus add .f32.
+ $line =~ s/^(\s+(?:vmov|vadd))(\s+s\d+\s*,\s*s\d+)/$1.f32$2/;
+ } elsif ($arch eq "aarch64") {
+ # Convert ext into ext8; armasm64 seems to require it named as ext8.
+ $line =~ s/^(\s+)ext(\s+)/$1ext8$2/;
+
+ # Pick up targets from ldr x0, =sym+offset
+ if ($line =~ /^\s*ldr\s+(\w+)\s*,\s*=([a-zA-Z]\w*)(.*)$/) {
+ my $reg = $1;
+ my $sym = $2;
+ my $offset = eval_expr($3);
+ if ($offset < 0 and $ENV{GASPP_ARMASM64_SKIP_NEG_OFFSET}) {
+ # armasm64 in VS < 15.6 is buggy with ldr x0, =sym+offset where the
+ # offset is a negative value; it does write a negative
+ # offset into the literal pool as it should, but the
+ # negative offset only covers the lower 32 bit of the 64
+ # bit literal/relocation.
+ # Thus remove the offset and apply it manually with a sub
+ # afterwards.
+ $offset = -$offset;
+ $line = "\tldr $reg, =$sym\n\tsub $reg, $reg, #$offset\n";
+ }
+ $import_symbols{$sym}++;
+ }
+
+ # armasm64 (currently) doesn't support offsets on adrp targets,
+ # even though the COFF format relocations (and the linker)
+ # supports it. Therefore strip out the offsets from adrp and
+ # add :lo12: (in case future armasm64 would start handling it)
+ # and add an extra explicit add instruction for the offset.
+ if ($line =~ s/(adrp\s+\w+\s*,\s*(\w+))([\d\+\-\*\/\(\) <>]+)?/\1/) {
+ $import_symbols{$2}++;
+ }
+ if ($line =~ s/(add\s+(\w+)\s*,\s*\w+\s*,\s*):lo12:(\w+)([\d\+\-\*\/\(\) <>]+)?/\1\3/) {
+ my $reg = $2;
+ my $sym = $3;
+ my $offset = eval_expr($4);
+ $line .= "\tadd $reg, $reg, #$offset\n" if $offset > 0;
+ $import_symbols{$sym}++;
+ }
+
+ # Convert e.g. "add x0, x0, w0, uxtw" into "add x0, x0, w0, uxtw #0",
+ # or "ldr x0, [x0, w0, uxtw]" into "ldr x0, [x0, w0, uxtw #0]".
+ $line =~ s/(uxt[whb]|sxt[whb])(\s*\]?\s*)$/\1 #0\2/i;
+
+ # Convert "mov x0, v0.d[0]" into "umov x0, v0.d[0]"
+ $line =~ s/\bmov\s+[xw]\d+\s*,\s*v\d+\.[ds]/u$&/i;
+
+ # Convert "ccmp w0, #0, #0, ne" into "ccmpne w0, #0, #0",
+ # and "csel w0, w0, w0, ne" into "cselne w0, w0, w0".
+ $line =~ s/(ccmp|csel)\s+([xw]\w+)\s*,\s*([xw#]\w+)\s*,\s*([xw#]\w+)\s*,\s*($arm_cond_codes)/\1\5 \2, \3, \4/;
+
+ # Convert "cinc w0, w0, ne" into "cincne w0, w0".
+ $line =~ s/(cinc)\s+([xw]\w+)\s*,\s*([xw]\w+)\s*,\s*($arm_cond_codes)/\1\4 \2, \3/;
+
+ # Convert "cset w0, lo" into "csetlo w0"
+ $line =~ s/(cset)\s+([xw]\w+)\s*,\s*($arm_cond_codes)/\1\3 \2/;
+
+ if ($ENV{GASPP_ARMASM64_SKIP_PRFUM}) {
+ # Strip out prfum; armasm64 (VS < 15.5) fails to assemble any
+ # variant/combination of prfum tested so far, but since it is
+ # a prefetch instruction it can be skipped without changing
+ # results.
+ $line =~ s/prfum.*\]//;
+ }
+
+ # Convert "ldrb w0, [x0, #-1]" into "ldurb w0, [x0, #-1]".
+ # Don't do this for forms with writeback though.
+ if ($line =~ /(ld|st)(r[bh]?)\s+(\w+)\s*,\s*\[\s*(\w+)\s*,\s*#([^\]]+)\s*\][^!]/) {
+ my $instr = $1;
+ my $suffix = $2;
+ my $target = $3;
+ my $base = $4;
+ my $offset = eval_expr($5);
+ if ($offset < 0) {
+ $line =~ s/$instr$suffix/${instr}u$suffix/;
+ }
+ }
+
+ if ($ENV{GASPP_ARMASM64_INVERT_SCALE}) {
+ # Instructions like fcvtzs and scvtf store the scale value
+ # inverted in the opcode (stored as 64 - scale), but armasm64
+ # in VS < 15.5 stores it as-is. Thus convert from
+ # "fcvtzs w0, s0, #8" into "fcvtzs w0, s0, #56".
+ if ($line =~ /(?:fcvtzs|scvtf)\s+(\w+)\s*,\s*(\w+)\s*,\s*#(\d+)/) {
+ my $scale = $3;
+ my $inverted_scale = 64 - $3;
+ $line =~ s/#$scale/#$inverted_scale/;
+ }
+ }
+
+ # Convert "ld1 {v0.4h-v3.4h}" into "ld1 {v0.4h,v1.4h,v2.4h,v3.4h}"
+ if ($line =~ /(?:ld|st)\d\s+({\s*v(\d+)\.(\d[bhsdBHSD])\s*-\s*v(\d+)\.(\d[bhsdBHSD])\s*})/) {
+ my $regspec = $1;
+ my $reg1 = $2;
+ my $layout1 = $3;
+ my $reg2 = $4;
+ my $layout2 = $5;
+ if ($layout1 eq $layout2) {
+ my $new_regspec = "{";
+ foreach my $i ($reg1 .. $reg2) {
+ $new_regspec .= "," if ($i > $reg1);
+ $new_regspec .= "v$i.$layout1";
+ }
+ $new_regspec .= "}";
+ $line =~ s/$regspec/$new_regspec/;
+ }
+ }
+ }
+ # armasm is unable to parse &0x - add spacing
+ $line =~ s/&0x/& 0x/g;
+ }
+
+ if ($force_thumb) {
+ # Convert register post indexing to a separate add instruction.
+ # This converts e.g. "ldr r0, [r1], r2" into "ldr r0, [r1]",
+ # "add r1, r1, r2".
+ $line =~ s/((?:ldr|str)[bh]?)\s+(\w+),\s*\[(\w+)\],\s*(\w+)/$1 $2, [$3]\n\tadd $3, $3, $4/g;
+
+ # Convert "mov pc, lr" into "bx lr", since the former only works
+ # for switching from arm to thumb (and only in armv7), but not
+ # from thumb to arm.
+ $line =~ s/mov\s*pc\s*,\s*lr/bx lr/g;
+
+ # Convert stmdb/ldmia/stmfd/ldmfd/ldm with only one register into a plain str/ldr with post-increment/decrement.
+ # Wide thumb2 encoding requires at least two registers in register list while all other encodings support one register too.
+ $line =~ s/stm(?:db|fd)\s+sp!\s*,\s*\{([^,-]+)\}/str $1, [sp, #-4]!/g;
+ $line =~ s/ldm(?:ia|fd)?\s+sp!\s*,\s*\{([^,-]+)\}/ldr $1, [sp], #4/g;
+
+ # Convert muls into mul+cmp
+ $line =~ s/muls\s+(\w+),\s*(\w+)\,\s*(\w+)/mul $1, $2, $3\n\tcmp $1, #0/g;
+
+ # Convert "and r0, sp, #xx" into "mov r0, sp", "and r0, r0, #xx"
+ $line =~ s/and\s+(\w+),\s*(sp|r13)\,\s*#(\w+)/mov $1, $2\n\tand $1, $1, #$3/g;
+
+ # Convert "ldr r0, [r0, r1, lsl #6]" where the shift is >3 (which
+ # can't be handled in thumb) into "add r0, r0, r1, lsl #6",
+ # "ldr r0, [r0]", for the special case where the same address is
+ # used as base and target for the ldr.
+ if ($line =~ /(ldr[bh]?)\s+(\w+),\s*\[\2,\s*(\w+),\s*lsl\s*#(\w+)\]/ and $4 > 3) {
+ $line =~ s/(ldr[bh]?)\s+(\w+),\s*\[\2,\s*(\w+),\s*lsl\s*#(\w+)\]/add $2, $2, $3, lsl #$4\n\t$1 $2, [$2]/;
+ }
+
+ $line =~ s/\.arm/.thumb/x;
+ }
+
+ # comment out unsupported directives
+ $line =~ s/\.type/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+ $line =~ s/\.func/$comm$&/x if $as_type =~ /^(apple-|clang)/;
+ $line =~ s/\.endfunc/$comm$&/x if $as_type =~ /^(apple-|clang)/;
+ $line =~ s/\.endfunc/ENDP/x if $as_type =~ /armasm/;
+ $line =~ s/\.ltorg/$comm$&/x if $as_type =~ /^(apple-|clang)/;
+ $line =~ s/\.ltorg/LTORG/x if $as_type eq "armasm";
+ $line =~ s/\.size/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+ $line =~ s/\.fpu/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+ $line =~ s/\.arch/$comm$&/x if $as_type =~ /^(apple-|clang|armasm)/;
+ $line =~ s/\.object_arch/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+ $line =~ s/.section\s+.note.GNU-stack.*/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+
+ $line =~ s/\.syntax/$comm$&/x if $as_type =~ /armasm/;
+
+ $line =~ s/\.hword/.short/x;
+
+ if ($as_type =~ /^apple-/) {
+ # the syntax for these is a little different
+ $line =~ s/\.global/.globl/x;
+ # also catch .section .rodata since the equivalent to .const_data is .section __DATA,__const
+ $line =~ s/(.*)\.rodata/.const_data/x;
+ $line =~ s/\.int/.long/x;
+ $line =~ s/\.float/.single/x;
+ }
+ if ($as_type eq "apple-gas") {
+ $line =~ s/vmrs\s+APSR_nzcv/fmrx r15/x;
+ }
+ if ($as_type eq "armasm") {
+ $line =~ s/\.global/EXPORT/x;
+ $line =~ s/\.extern/IMPORT/x;
+ $line =~ s/\.int/dcd/x;
+ $line =~ s/\.long/dcd/x;
+ $line =~ s/\.float/dcfs/x;
+ $line =~ s/\.word/dcd/x;
+ $line =~ s/\.short/dcw/x;
+ $line =~ s/\.byte/dcb/x;
+ $line =~ s/\.quad/dcq/x;
+ $line =~ s/\.ascii/dcb/x;
+ $line =~ s/\.asciz(.*)$/dcb\1,0/x;
+ $line =~ s/\.thumb/THUMB/x;
+ $line =~ s/\.arm/ARM/x;
+ # The alignment in AREA is the power of two, just as .align in gas
+ $line =~ s/\.text/AREA |.text|, CODE, READONLY, ALIGN=4, CODEALIGN/;
+ $line =~ s/(\s*)(.*)\.ro?data/$1AREA |.rdata|, DATA, READONLY, ALIGN=5/;
+ $line =~ s/\.data/AREA |.data|, DATA, ALIGN=5/;
+ }
+ if ($as_type eq "armasm" and $arch eq "arm") {
+ $line =~ s/fmxr/vmsr/;
+ $line =~ s/fmrx/vmrs/;
+ $line =~ s/fadds/vadd.f32/;
+ # Armasm in VS 2019 16.3 errors out on "it" instructions. But
+ # armasm implicitly adds the necessary it instructions anyway, so we
+ # can just filter them out.
+ $line =~ s/^\s*it[te]*\s+/$comm$&/;
+ }
+ if ($as_type eq "armasm" and $arch eq "aarch64") {
+ # Convert "b.eq" into "beq"
+ $line =~ s/\bb\.($arm_cond_codes)\b/b\1/;
+ }
+
+ # catch unknown section names that aren't mach-o style (with a comma)
+ if ($as_type =~ /apple-/ and $line =~ /.section ([^,]*)$/) {
+ die ".section $1 unsupported; figure out the mach-o section name and add it";
+ }
+
+ print ASMFILE $line;
+}
+
+if ($as_type ne "armasm") {
+ print ASMFILE ".text\n";
+ print ASMFILE ".align 2\n";
+ foreach my $literal (keys %literal_labels) {
+ print ASMFILE "$literal_labels{$literal}:\n $literal_expr $literal\n";
+ }
+
+ map print(ASMFILE ".thumb_func $_\n"),
+ grep exists $thumb_labels{$_}, keys %call_targets;
+} else {
+ map print(ASMFILE "\tIMPORT $_\n"),
+ grep ! exists $labels_seen{$_}, (keys %call_targets, keys %import_symbols);
+
+ print ASMFILE "\tEND\n";
+}
+
+close(INPUT) or exit 1;
+close(ASMFILE) or exit 1;
+if ($as_type eq "armasm" and ! defined $ENV{GASPP_DEBUG}) {
+ print STDERR join(" ", @gcc_cmd)."\n" if $verbose;
+ system(@gcc_cmd) == 0 or die "Error running assembler";
+}
+
+END {
+ unlink($tempfile) if defined $tempfile;
+}
+#exit 1
diff --git a/tools/depends/native/gettext/01-gettext-tools-stpncpy.patch b/tools/depends/native/gettext/01-gettext-tools-stpncpy.patch
new file mode 100644
index 0000000..a7541bf
--- /dev/null
+++ b/tools/depends/native/gettext/01-gettext-tools-stpncpy.patch
@@ -0,0 +1,11 @@
+--- a/gettext-tools/gnulib-lib/stpncpy.c
++++ b/gettext-tools/gnulib-lib/stpncpy.c
+@@ -24,7 +24,7 @@
+ /* Specification. */
+ #include <string.h>
+
+-#ifndef weak_alias
++#ifndef HAVE_STPNCPY
+ # define __stpncpy stpncpy
+ #endif
+
diff --git a/tools/depends/native/gettext/02-disable-test-doc.patch b/tools/depends/native/gettext/02-disable-test-doc.patch
new file mode 100644
index 0000000..1e539d1
--- /dev/null
+++ b/tools/depends/native/gettext/02-disable-test-doc.patch
@@ -0,0 +1,11 @@
+--- a/gettext-tools/Makefile.in
++++ b/gettext-tools/Makefile.in
+@@ -2198,7 +2198,7 @@
+ top_srcdir = @top_srcdir@
+ AUTOMAKE_OPTIONS = 1.5 gnu no-dependencies
+ ACLOCAL_AMFLAGS = -I m4 -I ../gettext-runtime/m4 -I ../m4 -I gnulib-m4 -I libgrep/gnulib-m4 -I libgettextpo/gnulib-m4
+-SUBDIRS = intl gnulib-lib libgrep src libgettextpo po its projects styles emacs misc man m4 tests system-tests gnulib-tests examples doc
++SUBDIRS = intl gnulib-lib libgrep src libgettextpo po its projects styles emacs misc man m4
+
+ # Allow users to use "gnulib-tool --update".
+
diff --git a/tools/depends/native/gettext/Makefile b/tools/depends/native/gettext/Makefile
new file mode 100644
index 0000000..f78acea
--- /dev/null
+++ b/tools/depends/native/gettext/Makefile
@@ -0,0 +1,62 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile 01-gettext-tools-stpncpy.patch 02-disable-test-doc.patch ../../download-files.include
+
+# lib name, version
+LIBNAME=gettext
+VERSION=0.21
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=f7e2968651879f8444d43a176a149db9f9411f4a03132a7f3b37c2ed97e3978ae6888169c995c1953cb78943b6e3573811abcbb8661b6631edbbe067b2699ddf
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX) \
+ --disable-csharp --disable-native-java --disable-java --without-emacs \
+ --disable-libasprintf --disable-openmp \
+ --with-included-gettext \
+ --with-included-glib \
+ --with-included-libcroco \
+ --with-included-libxml \
+ --without-git --without-cvs \
+ --disable-shared --disable-curses --disable-acl --disable-c++ --disable-nls
+
+ifeq ($(NATIVE_OS), osx)
+ # As per homebrew - https://github.com/Homebrew/homebrew-core/blob/f6df737d9479dd215185000a3dbd641185eafec2/Formula/g/gettext.rb#L52C1-L55
+ # Sonoma iconv() has a regression w.r.t. transliteration, which happens to
+ # break gettext's configure check. Force it.
+ # Reported to Apple as FB13163914
+ CONFIGURE+= am_cv_func_iconv_works=y
+endif
+
+LIBDYLIB=$(PLATFORM)/gettext-tools/src/.libs/libgettextsrc.a
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); sed -ie '/gets is a security hole/d' gettext-tools/gnulib-lib/stdio.in.h
+ cd $(PLATFORM); sed -ie '/gets is a security hole/d' gettext-tools/libgettextpo/stdio.in.h
+ cd $(PLATFORM); sed -ie '/gets is a security hole/d' gettext-runtime/gnulib-lib/stdio.in.h
+ cd $(PLATFORM); patch -p1 -i ../01-gettext-tools-stpncpy.patch
+ cd $(PLATFORM); patch -p1 -i ../02-disable-test-doc.patch
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)/libtextstyle
+ $(MAKE) -C $(PLATFORM)/gettext-tools
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -j1 -C $(PLATFORM)/gettext-tools install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+
diff --git a/tools/depends/native/giflib/01-static-lib.patch b/tools/depends/native/giflib/01-static-lib.patch
new file mode 100644
index 0000000..a5b0ebc
--- /dev/null
+++ b/tools/depends/native/giflib/01-static-lib.patch
@@ -0,0 +1,12 @@
+--- a/Makefile
++++ b/Makefile
+@@ -99,9 +99,6 @@
+ install-lib:
+ $(INSTALL) -d "$(DESTDIR)$(LIBDIR)"
+ $(INSTALL) -m 644 libgif.a "$(DESTDIR)$(LIBDIR)/libgif.a"
+- $(INSTALL) -m 755 libgif.so "$(DESTDIR)$(LIBDIR)/libgif.so.$(LIBVER)"
+- ln -sf libgif.so.$(LIBVER) "$(DESTDIR)$(LIBDIR)/libgif.so.$(LIBMAJOR)"
+- ln -sf libgif.so.$(LIBMAJOR) "$(DESTDIR)$(LIBDIR)/libgif.so"
+ install-man:
+ $(INSTALL) -d "$(DESTDIR)$(MANDIR)/man1"
+ $(INSTALL) -m 644 doc/*.1 "$(DESTDIR)$(MANDIR)/man1"
diff --git a/tools/depends/native/giflib/Makefile b/tools/depends/native/giflib/Makefile
new file mode 100644
index 0000000..a5df837
--- /dev/null
+++ b/tools/depends/native/giflib/Makefile
@@ -0,0 +1,40 @@
+include ../../Makefile.include
+DEPS = ../../Makefile.include Makefile 01-static-lib.patch ../../download-files.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+
+# lib name, version
+LIBNAME=giflib
+VERSION=5.2.1
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=4550e53c21cb1191a4581e363fc9d0610da53f7898ca8320f0d3ef6711e76bdda2609c2df15dc94c45e28bff8de441f1227ec2da7ea827cb3c0405af4faa4736
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+LIBDYLIB=$(PLATFORM)/libgif.a
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM); mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); patch -p1 -i ../01-static-lib.patch
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM) libgif.a CFLAGS="$(NATIVE_CFLAGS)" LDFLAGS="$(NATIVE_LDFLAGS)"
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install-include PREFIX="$(PREFIX)"
+ $(MAKE) -C $(PLATFORM) install-lib PREFIX="$(PREFIX)"
+ touch $@
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -r .installed-$(PLATFORM)
+ rm -rf $(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/heimdal/01-disable-libedit.patch b/tools/depends/native/heimdal/01-disable-libedit.patch
new file mode 100644
index 0000000..0e17025
--- /dev/null
+++ b/tools/depends/native/heimdal/01-disable-libedit.patch
@@ -0,0 +1,11 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -309,8 +309,6 @@
+ #endif
+ ],-ledit,,, READLINE,, [readline.h readline/readline.h editline/readline.h])
+
+-AC_CONFIG_SUBDIRS([lib/libedit])
+-
+ KRB_C_BIGENDIAN
+ AC_C_INLINE
+
diff --git a/tools/depends/native/heimdal/02-autoconf-2.70-configure.patch b/tools/depends/native/heimdal/02-autoconf-2.70-configure.patch
new file mode 100644
index 0000000..7275504
--- /dev/null
+++ b/tools/depends/native/heimdal/02-autoconf-2.70-configure.patch
@@ -0,0 +1,11 @@
+--- a/cf/check-var.m4
++++ b/cf/check-var.m4
+@@ -20,7 +20,7 @@
+ if test "$ac_foo" = yes; then
+ AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]$1), 1,
+ [Define if you have the `]$1[' variable.])
+- m4_ifval([$2], AC_CHECK_DECLS([$1],[],[],[$2]))
++ m4_ifval([$2], [AC_CHECK_DECLS([$1],[],[],[$2])])
+ fi
+ ])
+
diff --git a/tools/depends/native/heimdal/Makefile b/tools/depends/native/heimdal/Makefile
new file mode 100644
index 0000000..29d2a79
--- /dev/null
+++ b/tools/depends/native/heimdal/Makefile
@@ -0,0 +1,43 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile 01-disable-libedit.patch 02-autoconf-2.70-configure.patch ../../download-files.include
+
+# lib name, version
+LIBNAME=heimdal
+VERSION=7.7.0
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=6660939b5a36ce36310721a08a089fb671d1e3d2e8ac74ea4775bfa5f8f772d32de805551456200fe96cc486c092c44beb84f5dd877008bc305490ee971bbf99
+include ../../download-files.include
+
+APP=$(PLATFORM)/lib/asn1/asn1_compile
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM); mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); patch -p1 -i ../01-disable-libedit.patch
+ cd $(PLATFORM); patch -p1 -i ../02-autoconf-2.70-configure.patch
+ cd $(PLATFORM); $(AUTORECONF) -vif
+ cd $(PLATFORM); ./configure --prefix=$(PREFIX) --disable-shared
+
+$(APP): $(PLATFORM)
+ make -C $(PLATFORM)/include
+ make -C $(PLATFORM)/lib/roken
+ make -C $(PLATFORM)/lib/vers
+ make -C $(PLATFORM)/lib/com_err
+ make -C $(PLATFORM)/lib/asn1
+
+.installed-$(PLATFORM): $(APP)
+ install $(PLATFORM)/lib/asn1/asn1_compile $(PLATFORM)/lib/com_err/compile_et $(PREFIX)/bin
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/ldid/01-disable-openssl-plist.patch b/tools/depends/native/ldid/01-disable-openssl-plist.patch
new file mode 100644
index 0000000..d25b2a0
--- /dev/null
+++ b/tools/depends/native/ldid/01-disable-openssl-plist.patch
@@ -0,0 +1,21 @@
+--- a/Makefile
++++ b/Makefile
+@@ -1,13 +1,14 @@
+ DESTDIR ?= /
+ PREFIX ?= /usr/local
+-OPENSSL_LDFLAGS := $(shell pkg-config --libs-only-L openssl)
+-OPENSSL_CFLAGS := $(shell pkg-config --cflags openssl)
+-CFLAGS += $(OPENSSL_CFLAGS) -O2
+-LDFLAGS ?= $(LDID_LIBS) $(OPENSSL_LDFLAGS)
++#OPENSSL_LDFLAGS := $(shell pkg-config --libs-only-L openssl)
++#OPENSSL_CFLAGS := $(shell pkg-config --cflags openssl)
++#CFLAGS += $(OPENSSL_CFLAGS) -O2 -DLDID_NOSMIME=1 -DLDID_NOPLIST=1
++CFLAGS += -O2 -DLDID_NOSMIME=1 -DLDID_NOPLIST=1
++#LDFLAGS ?= $(LDID_LIBS) $(OPENSSL_LDFLAGS)
+
+ .PHONY: all clean
+ LDID_OBJS = ldid.cpp.o lookup2.c.o
+-LDID_LIBS = -lplist -lcrypto
++#LDID_LIBS = -lplist -lcrypto
+
+ all: ldid
diff --git a/tools/depends/native/ldid/Makefile b/tools/depends/native/ldid/Makefile
new file mode 100644
index 0000000..04a209d
--- /dev/null
+++ b/tools/depends/native/ldid/Makefile
@@ -0,0 +1,37 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile 01-disable-openssl-plist.patch ../../download-files.include
+
+# lib name, version
+LIBNAME=ldid
+VERSION=2.1.2-b462a92
+# tarball source: https://github.com/sbingner/ldid/commit/b462a92349c57f38f2a6844adabee940afe01ca6
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=9582d747f55e8fd1d54c20b6a3f0825d2ab0cfaffeb6992e53b39343b3aa3936f31e6353d59518f294ecc154adf687fd2dee0405d9b2e594cc16b19409f3c0f4
+include ../../download-files.include
+
+LIBDYLIB=$(PLATFORM)/ldid
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); patch -p1 -i ../01-disable-openssl-plist.patch
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ cp $(PLATFORM)/ldid $(NATIVEPREFIX)/bin
+ touch $@
+
+clean:
+ rm -r $(PLATFORM)
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/libffi/Makefile b/tools/depends/native/libffi/Makefile
new file mode 100644
index 0000000..499dfda
--- /dev/null
+++ b/tools/depends/native/libffi/Makefile
@@ -0,0 +1,43 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=libffi
+VERSION=3.2.1
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=980ca30a8d76f963fca722432b1fe5af77d7a4e4d2eac5144fbc5374d4c596609a293440573f4294207e1bdd9fda80ad1e1cafb2ffb543df5a275bc3bd546483
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE= CFLAGS="-fPIC" ./configure --prefix=$(NATIVEPREFIX) --disable-shared --disable-builddir
+
+
+LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME).a
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM); mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -j 1 -C $(PLATFORM)
+ touch $@
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ mkdir -p $(NATIVEPREFIX)/include/ffi
+ cp $(NATIVEPREFIX)/lib/$(SOURCE)/include/* $(NATIVEPREFIX)/include/ffi/
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/libjpeg-turbo/01-disable-executables.patch b/tools/depends/native/libjpeg-turbo/01-disable-executables.patch
new file mode 100644
index 0000000..8a672b2
--- /dev/null
+++ b/tools/depends/native/libjpeg-turbo/01-disable-executables.patch
@@ -0,0 +1,118 @@
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -211,6 +211,9 @@
+ boolean_number(WITH_TURBOJPEG)
+ option(WITH_FUZZ "Build fuzz targets" FALSE)
+
++option(ENABLE_TESTS "Enable testing targets" FALSE)
++boolean_number(ENABLE_TESTS)
++
+ macro(report_option var desc)
+ if(${var})
+ message(STATUS "${desc} enabled (${var} = ${${var}})")
+@@ -634,6 +637,7 @@
+ LINK_FLAGS "${TJMAPFLAG}${TJMAPFILE}")
+ endif()
+
++if(ENABLE_TESTS)
+ add_executable(tjunittest tjunittest.c tjutil.c md5/md5.c md5/md5hl.c)
+ target_link_libraries(tjunittest turbojpeg)
+
+@@ -645,6 +649,7 @@
+
+ add_executable(tjexample tjexample.c)
+ target_link_libraries(tjexample turbojpeg)
++endif()
+ endif()
+
+ if(ENABLE_STATIC)
+@@ -656,7 +661,7 @@
+ if(NOT MSVC)
+ set_target_properties(turbojpeg-static PROPERTIES OUTPUT_NAME turbojpeg)
+ endif()
+-
++if(ENABLE_TESTS)
+ add_executable(tjunittest-static tjunittest.c tjutil.c md5/md5.c
+ md5/md5hl.c)
+ target_link_libraries(tjunittest-static turbojpeg-static)
+@@ -666,6 +671,7 @@
+ if(UNIX)
+ target_link_libraries(tjbench-static m)
+ endif()
++endif()
+ endif()
+ endif()
+
+@@ -680,6 +686,7 @@
+ set(DJPEG_BMP_SOURCES wrbmp.c wrtarga.c)
+ endif()
+
++if(ENABLE_TESTS)
+ if(ENABLE_STATIC)
+ add_executable(cjpeg-static cjpeg.c cdjpeg.c rdgif.c rdppm.c rdswitch.c
+ ${CJPEG_BMP_SOURCES})
+@@ -699,11 +706,12 @@
+ add_executable(rdjpgcom rdjpgcom.c)
+
+ add_executable(wrjpgcom wrjpgcom.c)
+-
++endif()
+
+ ###############################################################################
+ # TESTS
+ ###############################################################################
++if(ENABLE_TESTS)
+
+ if(WITH_FUZZ)
+ add_subdirectory(fuzz)
+@@ -1419,7 +1427,7 @@
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest)
+ endif()
+ endif()
+-
++endif()
+
+ ###############################################################################
+ # INSTALLATION
+@@ -1434,8 +1442,10 @@
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
++if(ENABLE_TESTS)
+ install(TARGETS tjbench
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
++endif()
+ if(NOT CMAKE_VERSION VERSION_LESS "3.1" AND MSVC AND
+ CMAKE_C_LINKER_SUPPORTS_PDB)
+ install(FILES "$<TARGET_PDB_FILE:turbojpeg>"
+@@ -1452,8 +1462,10 @@
+ else()
+ set(DIR ${CMAKE_CURRENT_BINARY_DIR})
+ endif()
++ if(ENABLE_TESTS)
+ install(PROGRAMS ${DIR}/tjbench-static${EXE}
+ DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME tjbench${EXE})
++ endif()
+ endif()
+ endif()
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/turbojpeg.h
+@@ -1464,6 +1476,7 @@
+ install(TARGETS jpeg-static EXPORT ${CMAKE_PROJECT_NAME}Targets
+ INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
++if(ENABLE_TESTS)
+ if(NOT ENABLE_SHARED)
+ if(MSVC_IDE OR XCODE)
+ set(DIR "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}")
+@@ -1478,8 +1491,11 @@
+ DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME jpegtran${EXE})
+ endif()
+ endif()
++endif()
+
++if(ENABLE_TESTS)
+ install(TARGETS rdjpgcom wrjpgcom RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
++endif()
+
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/README.ijg
+ ${CMAKE_CURRENT_SOURCE_DIR}/README.md ${CMAKE_CURRENT_SOURCE_DIR}/example.txt
diff --git a/tools/depends/native/libjpeg-turbo/LIBJPEG-TURBO-VERSION b/tools/depends/native/libjpeg-turbo/LIBJPEG-TURBO-VERSION
new file mode 100644
index 0000000..61eb008
--- /dev/null
+++ b/tools/depends/native/libjpeg-turbo/LIBJPEG-TURBO-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=libjpeg-turbo
+VERSION=2.1.4
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=d3e92d614168355827e0ed884ff847cc7df8f6f1fb7b673c6c99afdf61fdfc0372afe5d30fdbf5e743335e2a7a27ca9f510c67d213e5cb2315a8d946e9414575
diff --git a/tools/depends/native/libjpeg-turbo/Makefile b/tools/depends/native/libjpeg-turbo/Makefile
new file mode 100644
index 0000000..990c2ba
--- /dev/null
+++ b/tools/depends/native/libjpeg-turbo/Makefile
@@ -0,0 +1,38 @@
+include ../../Makefile.include LIBJPEG-TURBO-VERSION ../../download-files.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include LIBJPEG-TURBO-VERSION Makefile ../../download-files.include \
+ 01-disable-executables.patch
+
+CMAKE_OPTIONS := -DCMAKE_TOOLCHAIN_FILE= \
+ -DCMAKE_ASM_NASM_COMPILER:FILEPATH=$(NATIVEPREFIX)/bin/nasm \
+ -DENABLE_SHARED:BOOL=OFF \
+ -DWITH_JPEG8:BOOL=ON \
+ -DCMAKE_C_COMPILER="$(CC_BINARY_FOR_BUILD)" \
+ -DCMAKE_C_FLAGS="$(NATIVE_CFLAGS)" \
+ -DCMAKE_EXE_LINKER_FLAGS="$(NATIVE_LDFLAGS)" \
+ -DCMAKE_INSTALL_LIBDIR:STRING=lib
+
+LIBDYLIB=$(PLATFORM)/build/libjpeg.a
+
+all: .installed-$(PLATFORM)
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); patch -p1 -i ../01-disable-executables.patch
+ cd $(PLATFORM); $(CMAKE) -B build $(CMAKE_OPTIONS)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)/build
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM)/build install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/liblzo2/Makefile b/tools/depends/native/liblzo2/Makefile
new file mode 100644
index 0000000..e6ca6e4
--- /dev/null
+++ b/tools/depends/native/liblzo2/Makefile
@@ -0,0 +1,41 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=lzo
+VERSION=2.10
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=a3dae5e4a6b93b1f5bf7435e8ab114a9be57252e9efc5dd444947d7a2d031b0819f34bcaeb35f60b5629a01b1238d738735a64db8f672be9690d3c80094511a4
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) autoconf/; \
+ ./configure --prefix=$(PREFIX) --enable-shared
+
+LIBDYLIB=$(PLATFORM)/src/.libs/lib$(LIBNAME)2.a
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+
diff --git a/tools/depends/native/libpng/Makefile b/tools/depends/native/libpng/Makefile
new file mode 100644
index 0000000..6059b69
--- /dev/null
+++ b/tools/depends/native/libpng/Makefile
@@ -0,0 +1,41 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=libpng
+VERSION=1.6.37
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=2ce2b855af307ca92a6e053f521f5d262c36eb836b4810cb53c809aa3ea2dcc08f834aee0ffd66137768a54397e28e92804534a74abb6fc9f6f3127f14c9c338
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \
+ ./configure --prefix=$(PREFIX)
+
+LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME)16.a
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+ touch $@
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/libtool/Makefile b/tools/depends/native/libtool/Makefile
new file mode 100644
index 0000000..ebbfdaf
--- /dev/null
+++ b/tools/depends/native/libtool/Makefile
@@ -0,0 +1,41 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=libtool
+VERSION=2.4.6
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=3233d81cb2739a54b840a0a82064eebbfaa4fb442fb993a35d6bd41d8395c51f038c90ae048b9252f172d0a5bbfb4b36e2b13d4477001f9ff7d4124237819a18
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX) \
+ --disable-shared --disable-ltdl-install
+
+LIBDYLIB=$(PLATFORM)/libtool
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+ touch $@
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/m4/Makefile b/tools/depends/native/m4/Makefile
new file mode 100644
index 0000000..016f098
--- /dev/null
+++ b/tools/depends/native/m4/Makefile
@@ -0,0 +1,38 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=m4
+VERSION=1.4.19
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=47f595845c89709727bda0b3fc78e3188ef78ec818965b395532e7041cabe9e49677ee4aca3d042930095a7f8df81de3da1026b23b6897be471f6cf13ddd512b
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+LIBDYLIB=$(PLATFORM)/src/$(LIBNAME)
+
+all: .installed-$(PLATFORM)
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/meson/Makefile b/tools/depends/native/meson/Makefile
new file mode 100644
index 0000000..553d4a3
--- /dev/null
+++ b/tools/depends/native/meson/Makefile
@@ -0,0 +1,35 @@
+include ../../Makefile.include
+PLATFORM=$(NATIVEPLATFORM)
+DEPS =../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=meson
+VERSION=0.59.2
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=126ac3a6c6b9e1fba1b3ac163f02d1eb0b61fedb312bcfe4996f6150522688d424f47283070c95101cc456afe9ea5cb462fb38f368d0c732952ffb8c600fda00
+include ../../download-files.include
+
+LIBDYLIB=$(PLATFORM)/build
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(NATIVEPREFIX)/bin/python3 setup.py config
+
+$(LIBDYLIB): $(PLATFORM)
+ cd $(PLATFORM); $(NATIVEPREFIX)/bin/python3 setup.py build
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ cd $(PLATFORM); $(NATIVEPREFIX)/bin/python3 setup.py install --prefix="$(NATIVEPREFIX)"
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/nasm/Makefile b/tools/depends/native/nasm/Makefile
new file mode 100644
index 0000000..c3b77e3
--- /dev/null
+++ b/tools/depends/native/nasm/Makefile
@@ -0,0 +1,39 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+APPNAME=nasm
+VERSION=2.15.05
+SOURCE=$(APPNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=512f90a2584f1c5811429274b97c64a2cedf37b9fdeffb1bcd0ea64afd9ecc19a2d7877ca8f1e05393aa324153fc9f39ea51dacbf8d25a7d5a2d7728c925dba7
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+APP=$(PLATFORM)/$(APPNAME)
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+
diff --git a/tools/depends/native/ninja/Makefile b/tools/depends/native/ninja/Makefile
new file mode 100644
index 0000000..f54cf8d
--- /dev/null
+++ b/tools/depends/native/ninja/Makefile
@@ -0,0 +1,33 @@
+include ../../Makefile.include
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=ninja
+VERSION=1.10.2
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=895412ae1cbc83c656e92f282602a29300e08274e9dea0da4464202ae556e7a1ab03bec057f23da4756bbd91bd2d744cd7a64b336740fd2782bb4db5c3b7b496
+include ../../download-files.include
+
+LIBDYLIB=$(PLATFORM)/ninja
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+
+$(LIBDYLIB): $(PLATFORM)
+ cd $(PLATFORM); CXX="$(CXX_FOR_BUILD)" AR="$(AR_FOR_BUILD)" CFLAGS="$(NATIVE_CFLAGS)" LDFLAGS="$(NATIVE_LDFLAGS)" $(NATIVEPREFIX)/bin/python3 configure.py --bootstrap
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ install $(PLATFORM)/ninja $(NATIVEPREFIX)/bin
+ touch $@
+
+clean:
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/openssl/Makefile b/tools/depends/native/openssl/Makefile
new file mode 100644
index 0000000..189acf0
--- /dev/null
+++ b/tools/depends/native/openssl/Makefile
@@ -0,0 +1,54 @@
+include ../../Makefile.include
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=openssl
+VERSION=1.1.1k
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=73cd042d4056585e5a9dd7ab68e7c7310a3a4c783eafa07ab0b560e7462b924e4376436a6d38a155c687f6942a881cfc0c1b9394afcde1d8c46bf396e7d51121
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=MACHINE=$(PLATFORM) ./config no-shared zlib no-asm --prefix=$(NATIVEPREFIX) --with-zlib-include=$(NATIVEPREFIX)/include --with-zlib-lib=$(NATIVEPREFIX)/lib
+
+ifeq ($(NATIVE_OS), osx)
+ ifeq ($(BUILD_CPU), x86_64)
+ CONFIGURE=./Configure darwin64-$(BUILD_CPU)-cc zlib no-asm no-shared --prefix=$(NATIVEPREFIX)
+ else
+ CONFIGURE=./Configure darwin64-arm64-cc zlib no-asm no-shared --prefix=$(NATIVEPREFIX)
+ endif
+endif
+
+CFLAGS=$(NATIVE_CFLAGS)
+LDFLAGS=$(NATIVE_LDFLAGS)
+CXXFLAGS=$(NATIVE_CXXFLAGS)
+CPPFLAGS=$(NATIVE_CPPFLAGS)
+
+export CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
+
+LIBDYLIB=$(PLATFORM)/libssl.a
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM); mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+ touch $@
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install_sw
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/pcre/Makefile b/tools/depends/native/pcre/Makefile
new file mode 100644
index 0000000..d50252f
--- /dev/null
+++ b/tools/depends/native/pcre/Makefile
@@ -0,0 +1,44 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=pcre
+VERSION=8.45
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.bz2
+SHA512=91bff52eed4a2dfc3f3bfdc9c672b88e7e2ffcf3c4b121540af8a4ae8c1ce05178430aa6b8000658b9bb7b4252239357250890e20ceb84b79cdfcde05154061a
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX) --disable-cpp \
+ --disable-shared --disable-stack-for-recursion \
+ --enable-pcre8 --disable-pcre16 --disable-pcre32 \
+ --enable-jit --enable-utf --enable-unicode-properties
+
+
+LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME).so
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $(LIBDYLIB)
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/perlmodule-parseyapp/Makefile b/tools/depends/native/perlmodule-parseyapp/Makefile
new file mode 100644
index 0000000..85dec65
--- /dev/null
+++ b/tools/depends/native/perlmodule-parseyapp/Makefile
@@ -0,0 +1,43 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=Parse-Yapp
+VERSION=1.21
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=dbf6182d4813ff7e355ea1713c748bfdf8290040a93f123acec645c7a1733fe457ab6e0ab51c4ec83cf82bc43d7fb35cbf89875df7b5c2ffc9635e85458cfeee
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+# clear env vars in case already active on system
+export PERL_MB_OPT=
+export PERL_MM_OPT=
+
+LIBDYLIB=$(PLATFORM)/bin/autoconf
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+
+$(LIBDYLIB): $(PLATFORM)
+ cd $(PLATFORM); perl Makefile.PL PREFIX=$(NATIVEPREFIX)
+ cd $(PLATFORM); $(MAKE)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ cd $(PLATFORM); $(MAKE) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/pkg-config/Makefile b/tools/depends/native/pkg-config/Makefile
new file mode 100644
index 0000000..1ba81b7
--- /dev/null
+++ b/tools/depends/native/pkg-config/Makefile
@@ -0,0 +1,45 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+# lib name, version
+LIBNAME=pkg-config
+VERSION=0.29.2
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=4861ec6428fead416f5cbbbb0bbad10b9152967e481d4b0ff2eb396a9f297f552984c9bb72f6864a37dcd8fca1d9ccceda3ef18d8f121938dbe4fdf2b870fe75
+include ../../download-files.include
+
+PC_PATH=$(PREFIX)/lib/pkgconfig:$(PREFIX)/share/pkgconfig
+ifeq ($(CROSS_COMPILING),no)
+PC_PATH:=$(PC_PATH):/usr/lib/pkgconfig:/usr/lib/$(HOST)/pkgconfig:/usr/share/pkgconfig
+endif
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX) --enable-indirect-deps --with-pc-path=$(PC_PATH) --with-internal-glib
+LIBDYLIB=$(PLATFORM)/pkg-config
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+ cd $(PLATFORM); sed -ie "s|LN = ln|LN = ln -f|" Makefile
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/pugixml/Makefile b/tools/depends/native/pugixml/Makefile
new file mode 100644
index 0000000..03ef707
--- /dev/null
+++ b/tools/depends/native/pugixml/Makefile
@@ -0,0 +1,43 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS =../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=pugixml
+VERSION=1.10
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=bfc80661005d0a0fb82ca6d5299e5efdd1bb468e11ee52d7ee9367e15776d28efb60266ce03842715cd43aae023afc2b369797bb3cbecd6d6a65c3ae3903e469
+include ../../download-files.include
+
+LIBDYLIB=$(PLATFORM)/build/libpugixml.a
+
+CMAKE_OPTIONS := -DCMAKE_INSTALL_LIBDIR=lib \
+ -DCMAKE_INSTALL_PREFIX=$(NATIVEPREFIX) \
+ $(CMAKE_OPTIONS)
+
+BUILDDIR = $(PLATFORM)/build
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ mkdir -p $(BUILDDIR)
+ cd $(BUILDDIR); $(NATIVEPREFIX)/bin/cmake $(CMAKE_OPTIONS) ..
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(BUILDDIR)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(BUILDDIR) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(BUILDDIR) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean:
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/python3/01-distutil-flags.patch b/tools/depends/native/python3/01-distutil-flags.patch
new file mode 100644
index 0000000..28cd2f9
--- /dev/null
+++ b/tools/depends/native/python3/01-distutil-flags.patch
@@ -0,0 +1,12 @@
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -214,6 +214,9 @@
+ (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \
+ get_config_vars('CC', 'CXX', 'CFLAGS',
+ 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
++ # get_config_vars returns host vars. clear cflags, ldshared for crosscompile use
++ cflags = ""
++ ldshared = cc + " -shared"
+
+ if 'CC' in os.environ:
+ newcc = os.environ['CC']
diff --git a/tools/depends/native/python3/Makefile b/tools/depends/native/python3/Makefile
new file mode 100644
index 0000000..74ebe06
--- /dev/null
+++ b/tools/depends/native/python3/Makefile
@@ -0,0 +1,46 @@
+include ../../Makefile.include PYTHON3-VERSION ../../download-files.include
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile PYTHON3-VERSION ../../download-files.include \
+ 01-distutil-flags.patch
+
+CONFIGURE=./configure --prefix=$(NATIVEPREFIX) \
+ --disable-shared \
+ --disable-framework \
+ --without-pymalloc \
+ --with-system-ffi
+
+NATIVE_SITEPACKAGES=$(NATIVEPREFIX)/lib/python$(PYTHON_VERSION)/site-packages
+
+ifeq ($(OS),linux)
+ CONFIGURE += --with-system-expat
+endif
+
+LIBDYLIB=$(PLATFORM)/python
+ifeq ($(NATIVE_OS), osx)
+ # Case insensitive FS will add .exe to buildexe regardless of --with-suffix=no
+ LIBDYLIB=$(PLATFORM)/python.exe
+endif
+
+all: .installed-$(PLATFORM)
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ cd $(PLATFORM); $(MAKE)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ cd $(PLATFORM); patch -p1 -i ../01-distutil-flags.patch
+ cd $(PLATFORM); $(MAKE) install
+# Sed patch setuptools that is installed via ensurepip as we cant patch the source
+ cd $(NATIVE_SITEPACKAGES); sed -ie "s|cflags = cflags + ' ' + os.environ\['CFLAGS'\]|cflags = os.environ\['CFLAGS'\]|" setuptools/_distutils/sysconfig.py
+ touch $(LIBDYLIB)
+ touch $@
+
+clean:
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/python3/PYTHON3-VERSION b/tools/depends/native/python3/PYTHON3-VERSION
new file mode 100644
index 0000000..290e333
--- /dev/null
+++ b/tools/depends/native/python3/PYTHON3-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=Python
+VERSION=3.11.2
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=5684ec7eae2dce26facc54d448ccdb6901bbfa1cab03abbe8fd34e4268a2b701daa13df15903349492447035be78380d473389e8703b4e910a65b088d2462e8b
diff --git a/tools/depends/native/swig/Makefile b/tools/depends/native/swig/Makefile
new file mode 100644
index 0000000..045cbcc
--- /dev/null
+++ b/tools/depends/native/swig/Makefile
@@ -0,0 +1,41 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=swig
+VERSION=4.0.2
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=05e7da70ce6d9a733b96c0bcfa3c1b82765bd859f48c74759bbf4bb1467acb1809caa310cba5e2b3280cd704fca249eaa0624821dffae1d2a75097c7f55d14ed
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX) --without-alllang --without-x --disable-ccache
+
+LIBDYLIB=$(PLATFORM)/swig
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+
diff --git a/tools/depends/native/tar/Makefile b/tools/depends/native/tar/Makefile
new file mode 100644
index 0000000..a3624ff
--- /dev/null
+++ b/tools/depends/native/tar/Makefile
@@ -0,0 +1,45 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile ../../download-files.include
+
+# app name, version
+APPNAME=tar
+VERSION=1.34
+SOURCE=$(APPNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=5e77c4a7b49983ad7d15238c2bce28be7a8aa437b4b1815fc00abd13096da308b6bba196cc6e3ed79d85e62823d520ae0d8fcda2d93873842cf84dc3369fc902
+include ../../download-files.include
+
+export PATH:=$(PREFIX)/bin:$(PATH)
+CONFIGURE=./configure --prefix=$(PREFIX) \
+ --program-transform-name=s/tar/gtar/ \
+ --disable-dependency-tracking \
+ $(PLATFORM_CONFIGURE)
+
+APP=$(PLATFORM)/src/tar
+APPBIN=$(PREFIX)/bin/tar
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(AUTORECONF)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(PLATFORM) install
+ rm -f $(PREFIX)/bin/tar $(PREFIX)/bin/gnutar
+ cd $(PREFIX)/bin; ln -s gtar tar; ln -s gtar gnutar
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/wayland-scanner/Makefile b/tools/depends/native/wayland-scanner/Makefile
new file mode 100644
index 0000000..ea46e21
--- /dev/null
+++ b/tools/depends/native/wayland-scanner/Makefile
@@ -0,0 +1,39 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS =../../Makefile.include Makefile ../../download-files.include
+
+APPNAME=wayland-scanner
+PROJECTNAME=wayland
+VERSION=1.17.0
+SOURCE=$(PROJECTNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=c5051aab5ff078b368c196ecfedb33ccd961265bb914845d7ed81de361bb86ae18299575baa6c4eceb0d82cf8b495e8293f31b51d1cbc05d84af0a199ab3f946
+include ../../download-files.include
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX) --disable-libraries --disable-documentation --disable-dtd-validation
+
+APP=$(PLATFORM)/wayland-scanner
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/waylandpp-scanner/Makefile b/tools/depends/native/waylandpp-scanner/Makefile
new file mode 100644
index 0000000..571412e
--- /dev/null
+++ b/tools/depends/native/waylandpp-scanner/Makefile
@@ -0,0 +1,47 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS =../../Makefile.include Makefile ../../download-files.include
+
+# lib name, version
+LIBNAME=waylandpp
+VERSION=0.2.8
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=bf1b8a9e69b87547fc65989b9eaff88a442d8b2f01f5446cef960000b093390b1e557536837fbf38bb6d9a4f93e3985ea34c3253f94925b0f571b4606c980832
+include ../../download-files.include
+
+APP=$(PLATFORM)/wayland-scanner++
+
+CMAKE_OPTIONS := -DBUILD_DOCUMENTATION=OFF \
+ -DBUILD_LIBRARIES=OFF \
+ -DBUILD_EXAMPLES=OFF \
+ -DBUILD_SCANNER=ON \
+ -DCMAKE_INSTALL_LIBDIR=lib \
+ -DCMAKE_INSTALL_PREFIX=$(NATIVEPREFIX) \
+ $(CMAKE_OPTIONS)
+
+BUILDDIR = $(PLATFORM)/build
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ mkdir -p $(BUILDDIR)
+ cd $(BUILDDIR); $(NATIVEPREFIX)/bin/cmake $(CMAKE_OPTIONS) ..
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(BUILDDIR)
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(BUILDDIR) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(BUILDDIR) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean:
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/xz/Makefile b/tools/depends/native/xz/Makefile
new file mode 100644
index 0000000..8986c49
--- /dev/null
+++ b/tools/depends/native/xz/Makefile
@@ -0,0 +1,30 @@
+include ../../Makefile.include XZ-VERSION ../../download-files.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile XZ-VERSION ../../download-files.include
+
+export LIBTOOL=builds/unix/libtool
+export PATH:=$(PREFIX)/bin:$(PATH)
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+APP=$(PLATFORM)/src/xz/xz
+
+all: .installed-$(PLATFORM)
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/xz/XZ-VERSION b/tools/depends/native/xz/XZ-VERSION
new file mode 100644
index 0000000..288df10
--- /dev/null
+++ b/tools/depends/native/xz/XZ-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=xz
+VERSION=5.2.6
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=5c69a492227c0ff72836d7a87e6372dc2e62bedfffb33f057263e28a6341825cef67834a863ed6ac02c5368c86da89f8affbe767f8bb914064cfa478f653e935
diff --git a/tools/depends/native/zlib/Makefile b/tools/depends/native/zlib/Makefile
new file mode 100644
index 0000000..863ac4b
--- /dev/null
+++ b/tools/depends/native/zlib/Makefile
@@ -0,0 +1,40 @@
+include ../../Makefile.include
+PREFIX=$(NATIVEPREFIX)
+PLATFORM=$(NATIVEPLATFORM)
+DEPS = ../../Makefile.include Makefile visibility.patch ../../download-files.include
+
+# lib name, version
+LIBNAME=zlib
+VERSION=1.2.11
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=73fd3fff4adeccd4894084c15ddac89890cd10ef105dd5e1835e1e9bbb6a49ff229713bd197d203edfa17c2727700fce65a2a235f07568212d820dca88b528ae
+include ../../download-files.include
+# configuration settings
+CONFIGURE= CC="$(CC_FOR_BUILD)" CFLAGS="$(NATIVE_CFLAGS)" ./configure --prefix=$(PREFIX)
+
+LIBDYLIB=$(PLATFORM)/$(LIBNAME).a
+
+all: .installed-$(PLATFORM)
+
+
+$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE)
+ rm -rf $(PLATFORM); mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); patch -p1 -i ../visibility.patch
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+ touch $@
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/zlib/visibility.patch b/tools/depends/native/zlib/visibility.patch
new file mode 100644
index 0000000..3257f7f
--- /dev/null
+++ b/tools/depends/native/zlib/visibility.patch
@@ -0,0 +1,15 @@
+--- a/zconf.h.in
++++ b/zconf.h.in
+@@ -374,7 +374,11 @@
+ #endif
+
+ #ifndef ZEXTERN
+-# define ZEXTERN extern
++# ifdef HAVE_HIDDEN
++# define ZEXTERN extern __attribute__((visibility ("default")))
++# else
++# define ZEXTERN extern
++# endif
+ #endif
+ #ifndef ZEXPORT
+ # define ZEXPORT
diff --git a/tools/depends/pre-depends/autoconf-pre-depends/Makefile b/tools/depends/pre-depends/autoconf-pre-depends/Makefile
new file mode 100644
index 0000000..23feab1
--- /dev/null
+++ b/tools/depends/pre-depends/autoconf-pre-depends/Makefile
@@ -0,0 +1,43 @@
+include ../../Makefile.include.in
+PREFIX=$(CURDIR)/../../pre-build-deps
+PLATFORM=native
+TARBALLS_LOCATION=$(PREFIX)
+RETRIEVE_TOOL=curl
+ARCHIVE_TOOL=tar
+# lib name, version
+LIBNAME=autoconf
+VERSION=2.71
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+
+export PATH:=$(CURDIR)/../../pre-build-deps/bin:$(PATH)
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+LIBDYLIB=$(PLATFORM)/bin/autoconf
+
+all: $(PREFIX)/bin/$(LIBNAME)
+
+$(TARBALLS_LOCATION)/$(ARCHIVE):
+ mkdir -p $(TARBALLS_LOCATION)
+ cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE)
+
+$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+
+$(LIBDYLIB): $(PLATFORM)
+ cd $(PLATFORM); $(CONFIGURE)
+ $(MAKE) -C $(PLATFORM)
+
+$(PREFIX)/bin/$(LIBNAME): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -f .installed-$(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/pre-depends/m4-pre-depends/Makefile b/tools/depends/pre-depends/m4-pre-depends/Makefile
new file mode 100644
index 0000000..fa60e37
--- /dev/null
+++ b/tools/depends/pre-depends/m4-pre-depends/Makefile
@@ -0,0 +1,41 @@
+include ../../Makefile.include.in
+DEPS=Makefile
+PREFIX=$(CURDIR)/../../pre-build-deps
+PLATFORM=native
+TARBALLS_LOCATION=$(PREFIX)
+RETRIEVE_TOOL=curl
+ARCHIVE_TOOL=tar
+# lib name, version
+LIBNAME=m4
+VERSION=1.4.19
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+LIBDYLIB=$(PLATFORM)/src/$(LIBNAME)
+
+all: $(PREFIX)/bin/$(LIBNAME)
+
+$(TARBALLS_LOCATION)/$(ARCHIVE):
+ mkdir -p $(TARBALLS_LOCATION)
+ cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE)
+
+$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+$(PREFIX)/bin/$(LIBNAME): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+
+distclean::
+ rm -rf $(PLATFORM)
diff --git a/tools/depends/target/crossguid/CROSSGUID-VERSION b/tools/depends/target/crossguid/CROSSGUID-VERSION
new file mode 100644
index 0000000..b5e40b8
--- /dev/null
+++ b/tools/depends/target/crossguid/CROSSGUID-VERSION
@@ -0,0 +1,6 @@
+LIBNAME=crossguid
+VERSION=ca1bf4b810e2d188d04cb6286f957008ee1b7681
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=f0a80d8e99b10473bcfdfde3d1c5fd7b766959819f0d1c0595ac84ce46db9007a5fbfde9a55aca60530c46cb7f8ef4c7e472c6191559ded92f868589c141ccaf
+BYPRODUCT=libcrossguid.a
+BYPRODUCT_WIN=crossguid.lib
diff --git a/tools/depends/target/dav1d/DAV1D-VERSION b/tools/depends/target/dav1d/DAV1D-VERSION
new file mode 100644
index 0000000..bb6d404
--- /dev/null
+++ b/tools/depends/target/dav1d/DAV1D-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=dav1d
+VERSION=1.0.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.bz2
+SHA512=86c6481e787fb6b8c28521e1efb1876d1be99f5fa5332cddab1111059b44775e05203cfc5c80a1b404ee00f35a1f5e1099e21b1f0851d77fb0101567e8b1a892
+BYPRODUCT=libdav1d.a
diff --git a/tools/depends/target/expat/EXPAT-VERSION b/tools/depends/target/expat/EXPAT-VERSION
new file mode 100644
index 0000000..fac7be7
--- /dev/null
+++ b/tools/depends/target/expat/EXPAT-VERSION
@@ -0,0 +1,6 @@
+LIBNAME=expat
+VERSION=2.4.9
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=8508379b4915d84d50f3638678a90792179c98247d1cb5e6e6387d117af4dc148ac7031c1debea8b96e7b710ef436cf0dd5da91f3d22b8186a00cfafe1201169
+BYPRODUCT=libexpat.a
diff --git a/tools/depends/target/ffmpeg/FFMPEG-VERSION b/tools/depends/target/ffmpeg/FFMPEG-VERSION
new file mode 100644
index 0000000..2c9eda8
--- /dev/null
+++ b/tools/depends/target/ffmpeg/FFMPEG-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=ffmpeg
+BASE_URL=https://github.com/xbmc/FFmpeg
+VERSION=4.4.1-Nexus-Alpha1
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=8beb04d577b5251e74b0d52f4d130997a8ba94bbd488c7c8309e6b45095c27807e150212888ce3a384b23dff52f8df1a7bde5407bae924ddc363f8125c0616c5
diff --git a/tools/depends/target/flatbuffers/FLATBUFFERS-VERSION b/tools/depends/target/flatbuffers/FLATBUFFERS-VERSION
new file mode 100644
index 0000000..4d05761
--- /dev/null
+++ b/tools/depends/target/flatbuffers/FLATBUFFERS-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=flatbuffers
+VERSION=2.0.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=26a06b572c0e4c9685743bd2d2162ac7dcd74b9324624cc3f3ef5b154c0cee7c52a04b77cdc184245d2d6ae38dfdcc4fd66001c318aa8ca001d2bf1d85d66a89
diff --git a/tools/depends/target/fmt/FMT-VERSION b/tools/depends/target/fmt/FMT-VERSION
new file mode 100644
index 0000000..f887185
--- /dev/null
+++ b/tools/depends/target/fmt/FMT-VERSION
@@ -0,0 +1,6 @@
+LIBNAME=fmt
+VERSION=9.1.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=a18442042722dd48e20714ec034a12fcc0576c9af7be5188586970e2edf47529825bdc99af366b1d5891630c8dbf6f63bfa9f012e77ab3d3ed80d1a118e3b2be
+BYPRODUCT=libfmt.a
+BYPRODUCT_WIN=fmt.lib
diff --git a/tools/depends/target/fontconfig/FONTCONFIG-VERSION b/tools/depends/target/fontconfig/FONTCONFIG-VERSION
new file mode 100644
index 0000000..60e2d31
--- /dev/null
+++ b/tools/depends/target/fontconfig/FONTCONFIG-VERSION
@@ -0,0 +1,7 @@
+LIBNAME=fontconfig
+VERSION=2.14.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=a5257249d031b3cd1a7b1521cd58f48d235a970020da4136a727db5407ec98e74a3776bc467d7e39f30ec664f56ff9fe39068317744a5e737a65109f7a005bfc
+BYPRODUCT=libfontconfig.a
+
+BASE_URL=https://www.freedesktop.org/software/fontconfig/release
diff --git a/tools/depends/target/freetype2-noharfbuzz/FREETYPE2-NOHARFBUZZ-VERSION b/tools/depends/target/freetype2-noharfbuzz/FREETYPE2-NOHARFBUZZ-VERSION
new file mode 100644
index 0000000..eba6f0e
--- /dev/null
+++ b/tools/depends/target/freetype2-noharfbuzz/FREETYPE2-NOHARFBUZZ-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=freetype
+VERSION=2.11.1
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=0848678482fbe20603a866f02da82c91122014d6f815ba4f1d9c03601c32e3ceb781f721c2b4427b6117d7c9742018af8dbb26566faf018595c70b50f8db3f08
+BYPRODUCT=libfreetype.a
diff --git a/tools/depends/target/freetype2/FREETYPE2-VERSION b/tools/depends/target/freetype2/FREETYPE2-VERSION
new file mode 100644
index 0000000..eba6f0e
--- /dev/null
+++ b/tools/depends/target/freetype2/FREETYPE2-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=freetype
+VERSION=2.11.1
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=0848678482fbe20603a866f02da82c91122014d6f815ba4f1d9c03601c32e3ceb781f721c2b4427b6117d7c9742018af8dbb26566faf018595c70b50f8db3f08
+BYPRODUCT=libfreetype.a
diff --git a/tools/depends/target/fribidi/FRIBIDI-VERSION b/tools/depends/target/fribidi/FRIBIDI-VERSION
new file mode 100644
index 0000000..2f1bcbd
--- /dev/null
+++ b/tools/depends/target/fribidi/FRIBIDI-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=fribidi
+VERSION=1.0.11
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.xz
+SHA512=6afde86784de06759f18235ccb44f23261a975f7cce0021b16755065a6a8ed84d7d5fb7fdcaadd691b48011efb4bfc2ee67555e5133a294a418cca1a0c85476c
diff --git a/tools/depends/target/fstrcmp/FSTRCMP-VERSION b/tools/depends/target/fstrcmp/FSTRCMP-VERSION
new file mode 100644
index 0000000..4712cad
--- /dev/null
+++ b/tools/depends/target/fstrcmp/FSTRCMP-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=fstrcmp
+VERSION=0.7.D001
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=aaeb0227afd5ada5955cbe6a565254ff88d2028d677d199c00e03b7cb5de1f2c69b18e6e8b032e452350a8eda7081807b01765adbeb8476eaf803d9de6e5509c
+BYPRODUCT=libfstrcmp.a
diff --git a/tools/depends/target/gtest/GTEST-VERSION b/tools/depends/target/gtest/GTEST-VERSION
new file mode 100644
index 0000000..3e6dd42
--- /dev/null
+++ b/tools/depends/target/gtest/GTEST-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=gtest
+VERSION=1.11.0
+ARCHIVE=googletest-$(VERSION).tar.gz
+SHA512=6fcc7827e4c4d95e3ae643dd65e6c4fc0e3d04e1778b84f6e06e390410fe3d18026c131d828d949d2f20dde6327d30ecee24dcd3ef919e21c91e010d149f3a28
+BYPRODUCT=libgtest.a
diff --git a/tools/depends/target/libandroidjni/LIBANDROIDJNI-VERSION b/tools/depends/target/libandroidjni/LIBANDROIDJNI-VERSION
new file mode 100644
index 0000000..cf6697c
--- /dev/null
+++ b/tools/depends/target/libandroidjni/LIBANDROIDJNI-VERSION
@@ -0,0 +1,6 @@
+LIBNAME=libandroidjni
+VERSION=3a2401853946f5ed9ae91e2163ab213edb8f4b62
+BASE_URL=https://github.com/xbmc/libandroidjni/archive
+ARCHIVE=$(VERSION).tar.gz
+SHA512=074e9d37b8f1574b6b30489cfb5127d11b3ed558d5edb15a8cc40fc0d57d88373a621eeb16fcd6eaa5fc97eb1c7598feeb60f95778989354a35e4efa02014b78
+BYPRODUCT=libandroidjni.a
diff --git a/tools/depends/target/libbluray/LIBBLURAY-VERSION b/tools/depends/target/libbluray/LIBBLURAY-VERSION
new file mode 100644
index 0000000..c34fdc1
--- /dev/null
+++ b/tools/depends/target/libbluray/LIBBLURAY-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=libbluray
+VERSION=1.3.2
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.bz2
+SHA512=6f2d3a984809db33a99d2fe3618370a3fda3ef1c417b725d3c2e1f24ff21495f95a6a5f78b30b2b26bab47865f68dd08c08e8a554809d3a5225956da712dc064
+BYPRODUCT=libbluray.a
diff --git a/tools/depends/target/libdvdcss/LIBDVDCSS-VERSION b/tools/depends/target/libdvdcss/LIBDVDCSS-VERSION
new file mode 100644
index 0000000..4fb78d9
--- /dev/null
+++ b/tools/depends/target/libdvdcss/LIBDVDCSS-VERSION
@@ -0,0 +1,7 @@
+LIBNAME=libdvdcss
+BASE_URL=https://github.com/xbmc/libdvdcss
+VERSION=1.4.3-Next-Nexus-Alpha2-2
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=d3be3bfc13c5ea56d8db745c2aab090c99760684fe4c8f62a13d266feb319e9180ceeecf8116bfd2ed90d9accba2c11dbbf93b61ad00f69a40812ebf4eabcdda
+BYPRODUCT=libdvdcss.a
+BYPRODUCT_WIN=dvdcss.lib
diff --git a/tools/depends/target/libdvdnav/LIBDVDNAV-VERSION b/tools/depends/target/libdvdnav/LIBDVDNAV-VERSION
new file mode 100644
index 0000000..3d6d1ec
--- /dev/null
+++ b/tools/depends/target/libdvdnav/LIBDVDNAV-VERSION
@@ -0,0 +1,7 @@
+LIBNAME=libdvdnav
+BASE_URL=https://github.com/xbmc/libdvdnav
+VERSION=6.1.1-Next-Nexus-Alpha2-2
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=51e6fc033121241354a5f0b3fc9a430577ae3ff6bb7f31445aa548ef4893037fb80eea3b2c6774c81e9ebaf9c45e9b490c98c2c65eb38f9f7daba84b236f7e1d
+BYPRODUCT=libdvdnav.a
+BYPRODUCT_WIN=libdvdnav.lib
diff --git a/tools/depends/target/libdvdread/LIBDVDREAD-VERSION b/tools/depends/target/libdvdread/LIBDVDREAD-VERSION
new file mode 100644
index 0000000..d51b629
--- /dev/null
+++ b/tools/depends/target/libdvdread/LIBDVDREAD-VERSION
@@ -0,0 +1,7 @@
+LIBNAME=libdvdread
+BASE_URL=https://github.com/xbmc/libdvdread
+VERSION=6.1.3-Next-Nexus-Alpha2-2
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=629a41157d07b8ec0ea1fe89ae5ec48f63047472a862782b805c531ae31a0376fc4dc15175f8280c3ef91d7fa977bacebb1b51232640034a34bab2293210fc5e
+BYPRODUCT=libdvdread.a
+BYPRODUCT_WIN=dvdread.lib
diff --git a/tools/depends/target/libffi/LIBFFI-VERSION b/tools/depends/target/libffi/LIBFFI-VERSION
new file mode 100644
index 0000000..9d1e722
--- /dev/null
+++ b/tools/depends/target/libffi/LIBFFI-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=libffi
+VERSION=3.4.2
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=31bad35251bf5c0adb998c88ff065085ca6105cf22071b9bd4b5d5d69db4fadf16cadeec9baca944c4bb97b619b035bb8279de8794b922531fddeb0779eb7fb1
diff --git a/tools/depends/target/libgcrypt/LIBGCRYPT-VERSION b/tools/depends/target/libgcrypt/LIBGCRYPT-VERSION
new file mode 100644
index 0000000..1010baf
--- /dev/null
+++ b/tools/depends/target/libgcrypt/LIBGCRYPT-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=libgcrypt
+VERSION=1.10.1
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.bz2
+SHA512=e5ca7966624fff16c3013795836a2c4377f0193dbb4ac5ad2b79654b1fa8992e17d83816569a402212dc8367a7980d4141f5d6ac282bae6b9f02186365b61f13
+BYPRODUCT=libgcrypt.a
diff --git a/tools/depends/target/libgpg-error/LIBGPG-ERROR-VERSION b/tools/depends/target/libgpg-error/LIBGPG-ERROR-VERSION
new file mode 100644
index 0000000..3456a91
--- /dev/null
+++ b/tools/depends/target/libgpg-error/LIBGPG-ERROR-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=libgpg-error
+VERSION=1.45
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.bz2
+SHA512=882f2dd617e89137d7a9d61b60488dac32321dd4fdb699e9687b6bd9380c056c027da502837f4482289c0fe00e7de01210e804428f05a0843ae2ca23fdcc6457
diff --git a/tools/depends/target/libjpeg-turbo/LIBJPEG-TURBO-VERSION b/tools/depends/target/libjpeg-turbo/LIBJPEG-TURBO-VERSION
new file mode 100644
index 0000000..61eb008
--- /dev/null
+++ b/tools/depends/target/libjpeg-turbo/LIBJPEG-TURBO-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=libjpeg-turbo
+VERSION=2.1.4
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=d3e92d614168355827e0ed884ff847cc7df8f6f1fb7b673c6c99afdf61fdfc0372afe5d30fdbf5e743335e2a7a27ca9f510c67d213e5cb2315a8d946e9414575
diff --git a/tools/depends/target/liblzo2/LIBLZO2-VERSION b/tools/depends/target/liblzo2/LIBLZO2-VERSION
new file mode 100644
index 0000000..05008a9
--- /dev/null
+++ b/tools/depends/target/liblzo2/LIBLZO2-VERSION
@@ -0,0 +1,6 @@
+LIBNAME=lzo
+VERSION=2.10
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.gz
+SHA512=a3dae5e4a6b93b1f5bf7435e8ab114a9be57252e9efc5dd444947d7a2d031b0819f34bcaeb35f60b5629a01b1238d738735a64db8f672be9690d3c80094511a4
+BYPRODUCT=liblzo2.a
diff --git a/tools/depends/target/libmicrohttpd/LIBMICROHTTPD-VERSION b/tools/depends/target/libmicrohttpd/LIBMICROHTTPD-VERSION
new file mode 100644
index 0000000..b6c751d
--- /dev/null
+++ b/tools/depends/target/libmicrohttpd/LIBMICROHTTPD-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=libmicrohttpd
+VERSION=0.9.75
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=4dc62ed191342a61cc2767171bb1ff4050f390db14ef7100299888237b52ea0b04b939c843878fe7f5daec2b35a47b3c1b7e7c11fb32d458184fe6b19986a37c
diff --git a/tools/depends/target/libnfs/LIBNFS-VERSION b/tools/depends/target/libnfs/LIBNFS-VERSION
new file mode 100644
index 0000000..892aa7a
--- /dev/null
+++ b/tools/depends/target/libnfs/LIBNFS-VERSION
@@ -0,0 +1,6 @@
+LIBNAME=libnfs
+VERSION=5.0.2
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=6dcf4ea8a01b35beb53694625d20fbebd858a88725c2742671878ad6fe7877999f93d262fb58a435b00c283c3e6fb6fa7222d04bb4540bf674b7ce196e9424f5
+BYPRODUCT=libnfs.a
+BYPRODUCT_WIN=nfs.lib
diff --git a/tools/depends/target/libpng/LIBPNG-VERSION b/tools/depends/target/libpng/LIBPNG-VERSION
new file mode 100644
index 0000000..c67b9d4
--- /dev/null
+++ b/tools/depends/target/libpng/LIBPNG-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=libpng
+VERSION=1.6.37
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=2ce2b855af307ca92a6e053f521f5d262c36eb836b4810cb53c809aa3ea2dcc08f834aee0ffd66137768a54397e28e92804534a74abb6fc9f6f3127f14c9c338
+BYPRODUCT=libpng.a
diff --git a/tools/depends/target/libxml2/LIBXML2-VERSION b/tools/depends/target/libxml2/LIBXML2-VERSION
new file mode 100644
index 0000000..9a8fbb1
--- /dev/null
+++ b/tools/depends/target/libxml2/LIBXML2-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=libxml2
+VERSION=2.10.1
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=7ae653eef725706c825a8755da14a92124c3f85b38f81fd1148c6e373b149d095eae935a47d874d210dafc7e76f09c019866657b8f9d6a44c666ce741e12f3ce
+BYPRODUCT=libxml2.a
diff --git a/tools/depends/target/libzip/LIBZIP-VERSION b/tools/depends/target/libzip/LIBZIP-VERSION
new file mode 100644
index 0000000..af0835b
--- /dev/null
+++ b/tools/depends/target/libzip/LIBZIP-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=libzip
+VERSION=1.8.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=fe94a26a2797dff7c9b27334f29982f8e523dd5095bf32ebcadc6443726864f0ff7b2e8bf243e52cad8f79297bc7a87d73fdbc35edae4ffc8ab6aa0bcc93b03e
+BYPRODUCT=libzip.a
diff --git a/tools/depends/target/mariadb/MARIADB-VERSION b/tools/depends/target/mariadb/MARIADB-VERSION
new file mode 100644
index 0000000..e05f933
--- /dev/null
+++ b/tools/depends/target/mariadb/MARIADB-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=mariadb
+VERSION=3.3.2
+ARCHIVE=$(LIBNAME)-connector-c-$(VERSION)-src.tar.gz
+SHA512=1f9754112ba02b863435840dab8e0954b98c646e6e6d73bbc2f338cd6493824b0f8973bbf80b129631ccafd684e0579743fe81a0e8f1120ed9f18154d9d446b3
diff --git a/tools/depends/target/nghttp2/NGHTTP2-VERSION b/tools/depends/target/nghttp2/NGHTTP2-VERSION
new file mode 100644
index 0000000..998667c
--- /dev/null
+++ b/tools/depends/target/nghttp2/NGHTTP2-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=nghttp2
+VERSION=1.46.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=fcf3573bcc421705190c7cf0e3230f6f3028b669cb2976d29cfeb73e706deaae91ce60d0a615472e3f296454049ea5798f1e8defdd260a98895e94fea6a7a16b
+BYPRODUCT=libnghttp2.a
diff --git a/tools/depends/target/pcre/PCRE-VERSION b/tools/depends/target/pcre/PCRE-VERSION
new file mode 100644
index 0000000..af533d2
--- /dev/null
+++ b/tools/depends/target/pcre/PCRE-VERSION
@@ -0,0 +1,6 @@
+LIBNAME=pcre
+VERSION=8.45
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.bz2
+SHA512=91bff52eed4a2dfc3f3bfdc9c672b88e7e2ffcf3c4b121540af8a4ae8c1ce05178430aa6b8000658b9bb7b4252239357250890e20ceb84b79cdfcde05154061a
+BYPRODUCT=libpcre.a
+BYPRODUCT_WIN=pcre.lib
diff --git a/tools/depends/target/python3/PYTHON3-VERSION b/tools/depends/target/python3/PYTHON3-VERSION
new file mode 100644
index 0000000..290e333
--- /dev/null
+++ b/tools/depends/target/python3/PYTHON3-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=Python
+VERSION=3.11.2
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=5684ec7eae2dce26facc54d448ccdb6901bbfa1cab03abbe8fd34e4268a2b701daa13df15903349492447035be78380d473389e8703b4e910a65b088d2462e8b
diff --git a/tools/depends/target/pythonmodule-pil/PYTHONMODULE-PIL-VERSION b/tools/depends/target/pythonmodule-pil/PYTHONMODULE-PIL-VERSION
new file mode 100644
index 0000000..9940c86
--- /dev/null
+++ b/tools/depends/target/pythonmodule-pil/PYTHONMODULE-PIL-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=Pillow
+VERSION=8.4.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=d395f69ccb37c52a3b6f45836700ffbc3173afae31848cc61d7b47db88ca1594541023beb9a14fd9067aca664e182c7d6e3300ab3e3095c31afe8dcbc6e08233
diff --git a/tools/depends/target/pythonmodule-pycryptodome/PYTHONMODULE-PYCRYPTODOME-VERSION b/tools/depends/target/pythonmodule-pycryptodome/PYTHONMODULE-PYCRYPTODOME-VERSION
new file mode 100644
index 0000000..236dc94
--- /dev/null
+++ b/tools/depends/target/pythonmodule-pycryptodome/PYTHONMODULE-PYCRYPTODOME-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=pycryptodome
+VERSION=3.12.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=67f2a814d74305614fdf9dfb633c4fd9d80d2064119d0ecab24ae52fd8ce4b6de1a1e82c6ba7bcf22fb7db1a5a850adf078e22317b4c07229cd7cb8cb7f1ffd4
diff --git a/tools/depends/target/pythonmodule-setuptools/PYTHONMODULE-SETUPTOOLS-VERSION b/tools/depends/target/pythonmodule-setuptools/PYTHONMODULE-SETUPTOOLS-VERSION
new file mode 100644
index 0000000..1eca9e1
--- /dev/null
+++ b/tools/depends/target/pythonmodule-setuptools/PYTHONMODULE-SETUPTOOLS-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=setuptools
+VERSION=65.5.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=b3ed6546bfa45c96f9b69fd7f014a87b52e6d8a6591340bf980bd4de98e33dbe0990b089940c348f2ad20a27590b82de84aec44c8ba1dce0510a3835653930d3
diff --git a/tools/depends/target/rapidjson/RAPIDJSON-VERSION b/tools/depends/target/rapidjson/RAPIDJSON-VERSION
new file mode 100644
index 0000000..120e868
--- /dev/null
+++ b/tools/depends/target/rapidjson/RAPIDJSON-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=rapidjson
+VERSION=1.1.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=2e82a4bddcd6c4669541f5945c2d240fb1b4fdd6e239200246d3dd50ce98733f0a4f6d3daa56f865d8c88779c036099c52a9ae85d47ad263686b68a88d832dff
diff --git a/tools/depends/target/samba-gplv3/SAMBA-GPLV3-VERSION b/tools/depends/target/samba-gplv3/SAMBA-GPLV3-VERSION
new file mode 100644
index 0000000..57d2c98
--- /dev/null
+++ b/tools/depends/target/samba-gplv3/SAMBA-GPLV3-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=samba
+VERSION=4.13.17
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=3f47cc588c370510a11a1d5dc1a9f64872d765a2940a0dd39f02718f9a81b134dda9c9cb593f291f2aa1657de65b26458adcda33369c0858e16edf7f088edaf4
diff --git a/tools/depends/target/spdlog/SPDLOG-VERSION b/tools/depends/target/spdlog/SPDLOG-VERSION
new file mode 100644
index 0000000..297caea
--- /dev/null
+++ b/tools/depends/target/spdlog/SPDLOG-VERSION
@@ -0,0 +1,6 @@
+LIBNAME=spdlog
+VERSION=1.10.0
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=e82ec0a0c813ed2f1c8a31a0f21dbb733d0a7bd8d05284feae3bd66040bc53ad47a93b26c3e389c7e5623cfdeba1854d690992c842748e072aab3e6e6ecc5666
+BYPRODUCT=libspdlog.a
+BYPRODUCT_WIN=spdlog.lib
diff --git a/tools/depends/target/sqlite3/SQLITE3-VERSION b/tools/depends/target/sqlite3/SQLITE3-VERSION
new file mode 100644
index 0000000..1bfb2cc
--- /dev/null
+++ b/tools/depends/target/sqlite3/SQLITE3-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=sqlite
+VERSION=3390400
+ARCHIVE=$(LIBNAME)-autoconf-$(VERSION).tar.gz
+SHA512=cc1de214e69ef677cac3f6dd2000ccfcf4b672ab464a115d96f24707009a408630e762c3cda89741b728ab34c4d9f5b8f8b12e9b11448e8364642b4421c3393d
diff --git a/tools/depends/target/taglib/TAGLIB-VERSION b/tools/depends/target/taglib/TAGLIB-VERSION
new file mode 100644
index 0000000..8f980b0
--- /dev/null
+++ b/tools/depends/target/taglib/TAGLIB-VERSION
@@ -0,0 +1,6 @@
+LIBNAME=taglib
+VERSION=1.12
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz
+SHA512=7e369faa5e3c6c6401052b7a19e35b0cf8c1e5ed9597053ac731a7718791d5d4803d1b18a93e903ec8c3fc6cb92e34d9616daa2ae4d326965d4c4d5624dcdaba
+BYPRODUCT=libtag.a
+BYPRODUCT_WIN=tag.lib
diff --git a/tools/depends/target/udfread/UDFREAD-VERSION b/tools/depends/target/udfread/UDFREAD-VERSION
new file mode 100644
index 0000000..64c5a41
--- /dev/null
+++ b/tools/depends/target/udfread/UDFREAD-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=udfread
+VERSION=1.1.2
+ARCHIVE=lib$(LIBNAME)-$(VERSION).tar.gz
+SHA512=3069feb5db40288beb5b112b285186162a704f0fdd3cf67a17fd4eeea015f2cfcfbb455b7aa7c3d79d00fd095a3fd11cffc7b121dce94d99c3b06a509a8977d2
+BYPRODUCT=libudfread.a
diff --git a/tools/depends/target/xz/XZ-VERSION b/tools/depends/target/xz/XZ-VERSION
new file mode 100644
index 0000000..288df10
--- /dev/null
+++ b/tools/depends/target/xz/XZ-VERSION
@@ -0,0 +1,4 @@
+LIBNAME=xz
+VERSION=5.2.6
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=5c69a492227c0ff72836d7a87e6372dc2e62bedfffb33f057263e28a6341825cef67834a863ed6ac02c5368c86da89f8affbe767f8bb914064cfa478f653e935
diff --git a/tools/depends/target/zlib/ZLIB-VERSION b/tools/depends/target/zlib/ZLIB-VERSION
new file mode 100644
index 0000000..c609cbe
--- /dev/null
+++ b/tools/depends/target/zlib/ZLIB-VERSION
@@ -0,0 +1,5 @@
+LIBNAME=zlib
+VERSION=1.2.12
+ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
+SHA512=12940e81e988f7661da52fa20bdc333314ae86a621fdb748804a20840b065a1d6d984430f2d41f3a057de0effc6ff9bcf42f9ee9510b88219085f59cbbd082bd
+BYPRODUCT=libz.a
diff --git a/tools/depends/xbmc-addons.include b/tools/depends/xbmc-addons.include
new file mode 100644
index 0000000..928845b
--- /dev/null
+++ b/tools/depends/xbmc-addons.include
@@ -0,0 +1,133 @@
+ADDON_DEPS_DIR := $(BUILDDIR)/$(PLATFORM)/build/depends
+TOOLCHAIN_FILE = $(ADDON_DEPS_DIR)/share/Toolchain_binaddons.cmake
+ADDON_PROJECT_DIR = $(BUILDDIR)/../../../../cmake/addons
+export PKG_CONFIG_LIBDIR = $(ADDON_DEPS_DIR)/lib/pkgconfig
+
+ifeq ($(CROSS_COMPILING),yes)
+ DEPS = $(TOOLCHAIN_FILE) $(abs_top_srcdir)/target/config-binaddons.site $(abs_top_srcdir)/target/Toolchain_binaddons.cmake $(CONFIG_SUB) $(CONFIG_GUESS)
+ TOOLCHAIN = -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE)
+ ifeq ($(OS),linux)
+ DEPS += linux-system-libs linux-system-x11-libs
+
+ ifeq ($(RENDER_SYSTEM),gl)
+ DEPS += linux-system-gl-libs
+ else
+ DEPS += linux-system-gles-libs
+ endif
+ endif
+endif
+
+ifeq ($(PLATFORM),)
+ PLATFORM = native
+endif
+ifeq ($(CMAKE),)
+ CMAKE = cmake
+endif
+
+CMAKE_EXTRA =
+ifeq (darwin, $(findstring darwin, $(HOST)))
+ INSTALL_PREFIX = ../../../../../addons/
+ CMAKE_EXTRA = -DPACKAGE_ZIP=ON
+endif
+
+ifneq ($(PREFIX),)
+ ifneq (darwin, $(findstring darwin, $(HOST)))
+ INSTALL_PREFIX = $(PREFIX) -DOVERRIDE_PATHS=ON
+ endif
+
+ CMAKE_EXTRA += -DAUTOCONF_FILES="$(CONFIG_SUB) $(CONFIG_GUESS)"
+endif
+
+ifneq ($(TARBALLS_LOCATION),)
+ CMAKE_EXTRA += -DTARBALL_DIR=$(TARBALLS_LOCATION)
+endif
+
+ifneq ($(ADDON_SRC_PREFIX),)
+ CMAKE_EXTRA += -DADDON_SRC_PREFIX=$(ADDON_SRC_PREFIX)
+endif
+
+ifneq ($(ADDONS_DEFINITION_DIR),)
+ CMAKE_EXTRA += -DADDONS_DEFINITION_DIR=$(ADDONS_DEFINITION_DIR)
+endif
+
+ifneq ($(EXTRA_CMAKE_ARGS),)
+ CMAKE_EXTRA += $(EXTRA_CMAKE_ARGS)
+endif
+
+ifeq ($(PACKAGE),1)
+ MAKE_PACKAGE = package-
+endif
+
+all: .installed-$(PLATFORM)
+
+
+clean:
+ rm -f .installed-$(PLATFORM)
+
+distclean:
+ rm -rf $(PLATFORM) .installed-$(PLATFORM) native
+
+.installed-$(PLATFORM): $(DEPS)
+ cd $(ADDON_PROJECT_DIR) && (git clean -xfd || rm -rf CMakeCache.txt CMakeFiles cmake_install.cmake build/*)
+ mkdir -p $(PLATFORM)
+ifeq ($(PREFIX),)
+ @echo
+ @echo "ERROR: please set PREFIX to the xbmc install path e.g. $(MAKE) PREFIX=/usr/local"
+ @exit 1
+endif
+ifeq ($(CROSS_COMPILING),yes)
+ mkdir -p $(PLATFORM)/build/depends/share; \
+ cp -f $(abs_top_srcdir)/target/config-binaddons.site $(PLATFORM)/build/depends/share/config.site
+endif
+ cd $(PLATFORM); \
+ $(CMAKE) -DCMAKE_INSTALL_PREFIX=$(INSTALL_PREFIX) $(CMAKE_EXTRA) \
+ $(TOOLCHAIN) \
+ -DADDONS_TO_BUILD="$(ADDONS)" $(ADDON_PROJECT_DIR) -DBUILD_DIR=$(BUILDDIR)/$(PLATFORM)/build ;\
+ for addon in $$($(MAKE) supported_addons | awk '/^ALL_ADDONS_BUILDING: .*$$/ { first = $$1; $$1 = ""; print $$0 }'); do \
+ $(MAKE) $(MAKE_PACKAGE)$$addon && echo $$addon >> $(ADDON_PROJECT_DIR)/.success || echo $$addon >> $(ADDON_PROJECT_DIR)/.failure ;\
+ done
+ifneq ($(CROSS_COMPILING),yes)
+ @[ -f $(ADDON_PROJECT_DIR)/.failure ] && echo "Following Addons failed to build:" $(shell cat $(ADDON_PROJECT_DIR)/.failure) || :
+ @cd $(PLATFORM); $(MAKE) need-sudo | grep -q TRUE && $(MAKE) sudo-install || :
+endif
+ touch $@
+
+$(TOOLCHAIN_FILE): $(abs_top_srcdir)/target/Toolchain_binaddons.cmake
+ mkdir -p $(ADDON_DEPS_DIR)/share
+ sed "s|@CMAKE_FIND_ROOT_PATH@|$(ADDON_DEPS_DIR)|g" $(abs_top_srcdir)/target/Toolchain_binaddons.cmake > $@
+
+HOST_LIBDIR := $(firstword $(wildcard /usr/lib64 /usr/lib/$(HOST)))
+
+linux-system-libs:
+ mkdir -p $(ADDON_DEPS_DIR)/lib
+ [ -f $(ADDON_DEPS_DIR)/lib/libm.so ] || ln -sf $(HOST_LIBDIR)/libm.so $(ADDON_DEPS_DIR)/lib/
+
+linux-system-x11-libs:
+ mkdir -p $(ADDON_DEPS_DIR)/lib/pkgconfig $(ADDON_DEPS_DIR)/include
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/x11.pc ] || ln -sf $(HOST_LIBDIR)/pkgconfig/x*.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/
+ [ -f $(ADDON_DEPS_DIR)/lib/libX11.so ] || ln -sf $(HOST_LIBDIR)/libX11.so* $(ADDON_DEPS_DIR)/lib/
+ [ -L $(ADDON_DEPS_DIR)/include/X11 ] || ln -sf /usr/include/X11 $(ADDON_DEPS_DIR)/include/X11
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/xproto.pc ] || ln -sf /usr/share/pkgconfig/x*.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/kbproto.pc ] || ln -sf /usr/share/pkgconfig/kbproto.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/kbproto.pc
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/damageproto.pc ] || ln -sf /usr/share/pkgconfig/damageproto.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/damageproto.pc
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/fixesproto.pc ] || ln -sf /usr/share/pkgconfig/fixesproto.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/fixesproto.pc
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/pthread-stubs.pc ] || ln -sf $(HOST_LIBDIR)/pkgconfig/pthread-stubs.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/pthread-stubs.pc
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/ice.pc ] || ln -sf $(HOST_LIBDIR)/pkgconfig/ice.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/ice.pc
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/sm.pc ] || ln -sf $(HOST_LIBDIR)/pkgconfig/sm.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/sm.pc
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/libdrm.pc ] || ln -sf $(HOST_LIBDIR)/pkgconfig/libdrm.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/libdrm.pc
+
+linux-system-gl-libs:
+ mkdir -p $(ADDON_DEPS_DIR)/lib/pkgconfig $(ADDON_DEPS_DIR)/include
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/gl.pc ] || ln -sf $(HOST_LIBDIR)/pkgconfig/gl.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/gl.pc
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/glu.pc ] || ln -sf $(HOST_LIBDIR)/pkgconfig/glu.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/glu.pc
+ [ -f $(ADDON_DEPS_DIR)/lib/libGL.so ] || ln -sf $(HOST_LIBDIR)/libGL.so $(ADDON_DEPS_DIR)/lib/libGL.so
+ [ -L $(ADDON_DEPS_DIR)/include/GL ] || ln -sf /usr/include/GL $(ADDON_DEPS_DIR)/include/GL
+
+linux-system-gles-libs:
+ mkdir -p $(ADDON_DEPS_DIR)/lib/pkgconfig $(ADDON_DEPS_DIR)/include
+ [ -f $(ADDON_DEPS_DIR)/lib/pkgconfig/glesv2.pc ] || ln -sf $(PREFIX)/lib/pkgconfig/glesv2.pc $(ADDON_DEPS_DIR)/lib/pkgconfig/glesv2.pc
+ [ -f $(ADDON_DEPS_DIR)/lib/libGLESv2.so ] || ln -sf $(PREFIX)/lib/libGLESv2.so $(ADDON_DEPS_DIR)/lib/libGLESv2.so
+ [ -L $(ADDON_DEPS_DIR)/include/GLES2 ] || ln -sf $(PREFIX)/include/GLES2 $(ADDON_DEPS_DIR)/include/GLES2
+ [ -L $(ADDON_DEPS_DIR)/include/KHR ] || ln -sf $(PREFIX)/include/KHR $(ADDON_DEPS_DIR)/include/KHR
+ [ -L $(ADDON_DEPS_DIR)/include/EGL ] || ln -sf $(PREFIX)/include/EGL $(ADDON_DEPS_DIR)/include/EGL
+ [ -f $(ADDON_DEPS_DIR)/lib/libEGL.so ] || ln -sf $(PREFIX)/lib/libEGL.so $(ADDON_DEPS_DIR)/lib/libEGL.so
diff --git a/tools/static-analysis/cppcheck/cppcheck-rules.xml b/tools/static-analysis/cppcheck/cppcheck-rules.xml
new file mode 100644
index 0000000..35f1fd1
--- /dev/null
+++ b/tools/static-analysis/cppcheck/cppcheck-rules.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<def>
+ <type-checks>
+ <unusedvar>
+ <suppress>CSingleLock</suppress>
+ <suppress>CSharedLock</suppress>
+ <suppress>CExclusiveLock</suppress>
+ </unusedvar>
+ </type-checks>
+</def>
diff --git a/tools/static-analysis/cppcheck/cppcheck-suppressions.xml b/tools/static-analysis/cppcheck/cppcheck-suppressions.xml
new file mode 100644
index 0000000..251fd80
--- /dev/null
+++ b/tools/static-analysis/cppcheck/cppcheck-suppressions.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<suppressions>
+ <suppress>
+ <id>*</id>
+ <fileName>lib/*</fileName>
+ </suppress>
+ <suppress>
+ <id>*</id>
+ <fileName>build/*</fileName>
+ </suppress>
+ <suppress>
+ <id>*</id>
+ <fileName>tools/*</fileName>
+ </suppress>
+ <suppress>
+ <id>*</id>
+ <fileName>*.c</fileName>
+ </suppress>
+</suppressions>