Browse Source

patch for cpp 17 & of 12

master
cailean 1 month ago
parent
commit
deae808571
  1. 10
      .github/FUNDING.yml
  2. 114
      .github/workflows/linux.yml
  3. 120
      .github/workflows/osx.yml
  4. 134
      .github/workflows/windows.yml
  5. 242
      .gitignore
  6. 18
      LICENSE.md
  7. 496
      README.md
  8. 152
      addon_config.mk
  9. 26
      example_basic/Makefile
  10. 14
      example_basic/README.md
  11. 8
      example_basic/addons.make
  12. 6
      example_basic/addons.make.norpi
  13. 239
      example_basic/bin/data/ofxpimapper.xml
  14. 14
      example_basic/src/main.cpp
  15. 76
      example_basic/src/ofApp.cpp
  16. 50
      example_basic/src/ofApp.h
  17. 10
      example_camera/.gitignore
  18. 26
      example_camera/Makefile
  19. 18
      example_camera/README.md
  20. 10
      example_camera/addons.make
  21. 6
      example_camera/addons.make.norpi
  22. 72
      example_camera/bin/data/defaultSurfaces.xml
  23. 140
      example_camera/bin/data/ofxpimapper.xml
  24. 124
      example_camera/src/CameraSource.cpp
  25. 66
      example_camera/src/CameraSource.h
  26. 48
      example_camera/src/main.cpp
  27. 72
      example_camera/src/ofApp.cpp
  28. 60
      example_camera/src/ofApp.h
  29. 10
      example_fbo-sources/.gitignore
  30. 26
      example_fbo-sources/Makefile
  31. 56
      example_fbo-sources/README.md
  32. 8
      example_fbo-sources/addons.make
  33. 6
      example_fbo-sources/addons.make.norpi
  34. 30
      example_fbo-sources/bin/data/magslideshow_settings.xml
  35. 252
      example_fbo-sources/bin/data/ofxpimapper.xml
  36. 104
      example_fbo-sources/src/BrickSource/BrickSource.cpp
  37. 30
      example_fbo-sources/src/BrickSource/BrickSource.h
  38. 86
      example_fbo-sources/src/CircleSource/CircleSource.cpp
  39. 28
      example_fbo-sources/src/CircleSource/CircleSource.h
  40. 124
      example_fbo-sources/src/QuadSource/QuadSource.cpp
  41. 28
      example_fbo-sources/src/QuadSource/QuadSource.h
  42. 96
      example_fbo-sources/src/ScanLineSource/ScanlineSource.cpp
  43. 28
      example_fbo-sources/src/ScanLineSource/ScanlineSource.h
  44. 402
      example_fbo-sources/src/SlideShowSource/magSlide.cpp
  45. 526
      example_fbo-sources/src/SlideShowSource/magSlide.h
  46. 1058
      example_fbo-sources/src/SlideShowSource/magSlideShowSource.cpp
  47. 334
      example_fbo-sources/src/SlideShowSource/magSlideShowSource.h
  48. 120
      example_fbo-sources/src/SlideShowSource/magSlideTransition.cpp
  49. 258
      example_fbo-sources/src/SlideShowSource/magSlideTransition.h
  50. 152
      example_fbo-sources/src/SlideShowSource/magSlideTransitionFactory.cpp
  51. 82
      example_fbo-sources/src/SlideShowSource/magSlideTransitionFactory.h
  52. 174
      example_fbo-sources/src/SyphonSource/SyphonSource.cpp
  53. 42
      example_fbo-sources/src/SyphonSource/SyphonSource.h
  54. 14
      example_fbo-sources/src/main.cpp
  55. 114
      example_fbo-sources/src/ofApp.cpp
  56. 74
      example_fbo-sources/src/ofApp.h
  57. 12
      example_pocketvj/.gitignore
  58. 26
      example_pocketvj/Makefile
  59. 8
      example_pocketvj/addons.make
  60. 6
      example_pocketvj/addons.make.norpi
  61. 72
      example_pocketvj/bin/data/ofxpimapper.xml
  62. 18
      example_pocketvj/src/main.cpp
  63. 248
      example_pocketvj/src/ofApp.cpp
  64. 42
      example_pocketvj/src/ofApp.h
  65. 26
      example_remote-client/Makefile
  66. 44
      example_remote-client/README.md
  67. 12
      example_remote-client/addons.make
  68. 10
      example_remote-client/addons.make.norpi
  69. 8
      example_remote-client/bin/data/config.json
  70. 72
      example_remote-client/bin/data/ofxpimapper.xml
  71. 98
      example_remote-client/src/TCPClient.cpp
  72. 44
      example_remote-client/src/TCPClient.h
  73. 14
      example_remote-client/src/main.cpp
  74. 218
      example_remote-client/src/ofApp.cpp
  75. 50
      example_remote-client/src/ofApp.h
  76. 26
      example_remote-server/Makefile
  77. 50
      example_remote-server/README.md
  78. 12
      example_remote-server/addons.make
  79. 10
      example_remote-server/addons.make.norpi
  80. 72
      example_remote-server/bin/data/ofxpimapper.xml
  81. 190
      example_remote-server/src/TCPServer.cpp
  82. 46
      example_remote-server/src/TCPServer.h
  83. 14
      example_remote-server/src/main.cpp
  84. 168
      example_remote-server/src/ofApp.cpp
  85. 46
      example_remote-server/src/ofApp.h
  86. 10
      example_simpler/.gitignore
  87. 26
      example_simpler/Makefile
  88. 8
      example_simpler/addons.make
  89. 6
      example_simpler/addons.make.norpi
  90. 162
      example_simpler/bin/data/ofxpimapper.xml
  91. 82
      example_simpler/src/CustomSource.cpp
  92. 26
      example_simpler/src/CustomSource.h
  93. 42
      example_simpler/src/Settings.cpp
  94. 36
      example_simpler/src/Settings.h
  95. 44
      example_simpler/src/main.cpp
  96. 110
      example_simpler/src/ofApp.cpp
  97. 56
      example_simpler/src/ofApp.h
  98. 532
      patches/msys2/makefileCommon/config.addons.mk
  99. 16
      patches/msys2/patch.sh
  100. 2152
      patches/msys2/sound/ofOpenALSoundPlayer.cpp

10
.github/FUNDING.yml

@ -1,5 +1,5 @@
# These are supported funding model platforms
github: [kr15h]
patreon: kriwkrow
custom: ['https://paypal.me/kriwkrow']
# These are supported funding model platforms
github: [kr15h]
patreon: kriwkrow
custom: ['https://paypal.me/kriwkrow']

114
.github/workflows/linux.yml

@ -1,57 +1,57 @@
name: linux
on:
push:
branches:
- master
jobs:
compile:
runs-on: ubuntu-latest
env:
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_linux64gcc6_release.tar.gz
steps:
- name: Fetch ofxPiMapper
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Download openFrameworks and add ofxPiMapper to addons
run: |
mkdir .ofxPiMapper
mv ./* .ofxPiMapper/
wget ${OF_URL} --tries=10 --quiet
echo "Unarchive openFrameworks"
OF_ARCHIVE_NAME=$(basename -- "$OF_URL")
tar -xf ${OF_ARCHIVE_NAME}
rm ${OF_ARCHIVE_NAME}
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .tar.gz)
mv ${OF_EXTRACT_NAME} openFrameworks
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper
- name: Install openFrameworks Dependencies
working-directory: ./openFrameworks/scripts/linux/ubuntu
run: sudo ./install_dependencies.sh -y
- name: Compile openFrameworks
working-directory: ./openFrameworks/scripts/linux
run: ./compileOF.sh
- name: Compile example_basic
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic
run: mv addons.make.norpi addons.make && make
- name: Compile example_camera
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera
run: mv addons.make.norpi addons.make && make
- name: Compile example_fbo-sources
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources
run: mv addons.make.norpi addons.make && make
- name: Compile example_pocketvj
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj
run: mv addons.make.norpi addons.make && make
- name: Install ofxJSON dependency
working-directory: ./openFrameworks/addons/
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1
- name: Compile example_remote-client
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client
run: mv addons.make.norpi addons.make && make
- name: Compile example_remote-server
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server
run: mv addons.make.norpi addons.make && make
- name: Compile example_simpler
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler
run: mv addons.make.norpi addons.make && make
name: linux
on:
push:
branches:
- master
jobs:
compile:
runs-on: ubuntu-latest
env:
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_linux64gcc6_release.tar.gz
steps:
- name: Fetch ofxPiMapper
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Download openFrameworks and add ofxPiMapper to addons
run: |
mkdir .ofxPiMapper
mv ./* .ofxPiMapper/
wget ${OF_URL} --tries=10 --quiet
echo "Unarchive openFrameworks"
OF_ARCHIVE_NAME=$(basename -- "$OF_URL")
tar -xf ${OF_ARCHIVE_NAME}
rm ${OF_ARCHIVE_NAME}
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .tar.gz)
mv ${OF_EXTRACT_NAME} openFrameworks
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper
- name: Install openFrameworks Dependencies
working-directory: ./openFrameworks/scripts/linux/ubuntu
run: sudo ./install_dependencies.sh -y
- name: Compile openFrameworks
working-directory: ./openFrameworks/scripts/linux
run: ./compileOF.sh
- name: Compile example_basic
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic
run: mv addons.make.norpi addons.make && make
- name: Compile example_camera
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera
run: mv addons.make.norpi addons.make && make
- name: Compile example_fbo-sources
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources
run: mv addons.make.norpi addons.make && make
- name: Compile example_pocketvj
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj
run: mv addons.make.norpi addons.make && make
- name: Install ofxJSON dependency
working-directory: ./openFrameworks/addons/
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1
- name: Compile example_remote-client
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client
run: mv addons.make.norpi addons.make && make
- name: Compile example_remote-server
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server
run: mv addons.make.norpi addons.make && make
- name: Compile example_simpler
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler
run: mv addons.make.norpi addons.make && make

120
.github/workflows/osx.yml

@ -1,60 +1,60 @@
name: osx
on:
push:
branches:
- master
jobs:
compile:
runs-on: macos-latest
env:
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_osx_release.zip
steps:
- name: Fetch ofxPiMapper
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Download openFrameworks and add ofxPiMapper to addons
run: |
mkdir .ofxPiMapper
mv ./* .ofxPiMapper/
wget ${OF_URL} --tries=10 --quiet
echo "Unarchive openFrameworks"
OF_ARCHIVE_NAME=$(basename -- "$OF_URL")
unzip ${OF_ARCHIVE_NAME}
rm ${OF_ARCHIVE_NAME}
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .zip)
mv ${OF_EXTRACT_NAME} openFrameworks
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper
- name: Install Dependencies
run: |
set -ev
brew update
brew install gdb
brew install coreutils
- name: Compile openFrameworks
working-directory: ./openFrameworks/scripts/templates/osx
run: make
- name: Compile example_basic
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic
run: mv addons.make.norpi addons.make && make
- name: Compile example_camera
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera
run: mv addons.make.norpi addons.make && make
- name: Compile example_fbo-sources
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources
run: mv addons.make.norpi addons.make && make
- name: Compile example_pocketvj
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj
run: mv addons.make.norpi addons.make && make
- name: Install ofxJSON dependency
working-directory: ./openFrameworks/addons/
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1
- name: Compile example_remote-client
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client
run: mv addons.make.norpi addons.make && make
- name: Compile example_remote-server
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server
run: mv addons.make.norpi addons.make && make
- name: Compile example_simpler
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler
run: mv addons.make.norpi addons.make && make
name: osx
on:
push:
branches:
- master
jobs:
compile:
runs-on: macos-latest
env:
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_osx_release.zip
steps:
- name: Fetch ofxPiMapper
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Download openFrameworks and add ofxPiMapper to addons
run: |
mkdir .ofxPiMapper
mv ./* .ofxPiMapper/
wget ${OF_URL} --tries=10 --quiet
echo "Unarchive openFrameworks"
OF_ARCHIVE_NAME=$(basename -- "$OF_URL")
unzip ${OF_ARCHIVE_NAME}
rm ${OF_ARCHIVE_NAME}
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .zip)
mv ${OF_EXTRACT_NAME} openFrameworks
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper
- name: Install Dependencies
run: |
set -ev
brew update
brew install gdb
brew install coreutils
- name: Compile openFrameworks
working-directory: ./openFrameworks/scripts/templates/osx
run: make
- name: Compile example_basic
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic
run: mv addons.make.norpi addons.make && make
- name: Compile example_camera
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera
run: mv addons.make.norpi addons.make && make
- name: Compile example_fbo-sources
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources
run: mv addons.make.norpi addons.make && make
- name: Compile example_pocketvj
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj
run: mv addons.make.norpi addons.make && make
- name: Install ofxJSON dependency
working-directory: ./openFrameworks/addons/
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1
- name: Compile example_remote-client
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client
run: mv addons.make.norpi addons.make && make
- name: Compile example_remote-server
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server
run: mv addons.make.norpi addons.make && make
- name: Compile example_simpler
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler
run: mv addons.make.norpi addons.make && make

134
.github/workflows/windows.yml

@ -1,67 +1,67 @@
name: windows
on:
push:
branches:
- master
jobs:
compile:
runs-on: windows-latest
env:
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_msys2_mingw64_release.zip
defaults:
run:
shell: msys2 {0}
steps:
- uses: msys2/setup-msys2@v2
with:
update: true
install: unzip git
msystem: MINGW64
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Download openFrameworks and add ofxPiMapper to addons
run: |
mkdir .ofxPiMapper
mv ./* .ofxPiMapper/
wget ${OF_URL} --tries=10 --quiet
echo "Unarchive openFrameworks"
OF_ARCHIVE_NAME=$(basename -- "$OF_URL")
unzip ${OF_ARCHIVE_NAME}
rm ${OF_ARCHIVE_NAME}
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .zip)
mv ${OF_EXTRACT_NAME} openFrameworks
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper
- name: Install openFrameworks Dependencies
working-directory: ./openFrameworks/scripts/msys2
run: ./install_dependencies.sh --noconfirm
- name: Apply patches
working-directory: ./openFrameworks/addons/ofxPiMapper/patches/msys2
run: ./patch.sh
- name: Compile openFrameworks
working-directory: ./openFrameworks/scripts/msys2
run: ./compileOF.sh
- name: Compile example_basic
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic
run: mv addons.make.norpi addons.make && make
- name: Compile example_camera
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera
run: mv addons.make.norpi addons.make && make
- name: Compile example_fbo-sources
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources
run: mv addons.make.norpi addons.make && make
- name: Compile example_pocketvj
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj
run: mv addons.make.norpi addons.make && make
- name: Install ofxJSON dependency
working-directory: ./openFrameworks/addons/
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1
- name: Compile example_remote-client
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client
run: mv addons.make.norpi addons.make && make
- name: Compile example_remote-server
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server
run: mv addons.make.norpi addons.make && make
- name: Compile example_simpler
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler
run: mv addons.make.norpi addons.make && make
name: windows
on:
push:
branches:
- master
jobs:
compile:
runs-on: windows-latest
env:
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_msys2_mingw64_release.zip
defaults:
run:
shell: msys2 {0}
steps:
- uses: msys2/setup-msys2@v2
with:
update: true
install: unzip git
msystem: MINGW64
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Download openFrameworks and add ofxPiMapper to addons
run: |
mkdir .ofxPiMapper
mv ./* .ofxPiMapper/
wget ${OF_URL} --tries=10 --quiet
echo "Unarchive openFrameworks"
OF_ARCHIVE_NAME=$(basename -- "$OF_URL")
unzip ${OF_ARCHIVE_NAME}
rm ${OF_ARCHIVE_NAME}
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .zip)
mv ${OF_EXTRACT_NAME} openFrameworks
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper
- name: Install openFrameworks Dependencies
working-directory: ./openFrameworks/scripts/msys2
run: ./install_dependencies.sh --noconfirm
- name: Apply patches
working-directory: ./openFrameworks/addons/ofxPiMapper/patches/msys2
run: ./patch.sh
- name: Compile openFrameworks
working-directory: ./openFrameworks/scripts/msys2
run: ./compileOF.sh
- name: Compile example_basic
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic
run: mv addons.make.norpi addons.make && make
- name: Compile example_camera
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera
run: mv addons.make.norpi addons.make && make
- name: Compile example_fbo-sources
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources
run: mv addons.make.norpi addons.make && make
- name: Compile example_pocketvj
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj
run: mv addons.make.norpi addons.make && make
- name: Install ofxJSON dependency
working-directory: ./openFrameworks/addons/
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1
- name: Compile example_remote-client
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client
run: mv addons.make.norpi addons.make && make
- name: Compile example_remote-server
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server
run: mv addons.make.norpi addons.make && make
- name: Compile example_simpler
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler
run: mv addons.make.norpi addons.make && make

242
.gitignore

@ -1,121 +1,121 @@
#########################
# general patterns
#########################
docs/html
docs/tagfile.xml
*/bin/*
!*/bin/data/
# for bin folder in root
/bin/*
!/bin/data/
[Bb]uild/
[Oo]bj/
*.o
[Dd]ebug*/
[Rr]elease*/
*.mode*
*.app/
*.pyc
.svn/
#########################
# IDE
#########################
# XCode
*.pbxuser
*.perspective
*.perspectivev3
*.mode1v3
*.mode2v3
#XCode 4
xcuserdata
*.xcworkspace
# Code::Blocks
*.depend
*.layout
*.cbTemp
# Visual Studio
*.sdf
*.opensdf
*.suo
*.pdb
*.ilk
*.aps
ipch/
# Eclipse
.metadata
local.properties
.externalToolBuilders
# Codelite
*.session
*.tags
*.workspace.*
#########################
# operating system
#########################
# Linux
*~
# KDE
.directory
.AppleDouble
# OSX
.DS_Store
*.swp
*~.nib
# Thumbnails
._*
# Windows
# Windows image file caches
Thumbs.db
# Folder config file
Desktop.ini
#Android
.csettings
#########################
# packages
#########################
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases
*.log
*.sql
*.sqlite
example/cmake-build-debug/
example/\.idea/
example/cmake-build-release/
example/example\.xcodeproj/xcshareddata/xcschemes/
.idea/
cmake-build-debug/
CMakeLists\.txt
#########################
# general patterns
#########################
docs/html
docs/tagfile.xml
*/bin/*
!*/bin/data/
# for bin folder in root
/bin/*
!/bin/data/
[Bb]uild/
[Oo]bj/
*.o
[Dd]ebug*/
[Rr]elease*/
*.mode*
*.app/
*.pyc
.svn/
#########################
# IDE
#########################
# XCode
*.pbxuser
*.perspective
*.perspectivev3
*.mode1v3
*.mode2v3
#XCode 4
xcuserdata
*.xcworkspace
# Code::Blocks
*.depend
*.layout
*.cbTemp
# Visual Studio
*.sdf
*.opensdf
*.suo
*.pdb
*.ilk
*.aps
ipch/
# Eclipse
.metadata
local.properties
.externalToolBuilders
# Codelite
*.session
*.tags
*.workspace.*
#########################
# operating system
#########################
# Linux
*~
# KDE
.directory
.AppleDouble
# OSX
.DS_Store
*.swp
*~.nib
# Thumbnails
._*
# Windows
# Windows image file caches
Thumbs.db
# Folder config file
Desktop.ini
#Android
.csettings
#########################
# packages
#########################
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases
*.log
*.sql
*.sqlite
example/cmake-build-debug/
example/\.idea/
example/cmake-build-release/
example/example\.xcodeproj/xcshareddata/xcschemes/
.idea/
cmake-build-debug/
CMakeLists\.txt

18
LICENSE.md

@ -1,9 +1,9 @@
ofxPiMapper is distributed under the [MIT License](https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license). This gives everyone the freedoms to use ofxPiMapper in any context: commercial or non-commercial, public or private, open or closed source.
**Copyright (c) 2014–2021, Krisjanis Rijnieks and contributors**
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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ofxPiMapper is distributed under the [MIT License](https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license). This gives everyone the freedoms to use ofxPiMapper in any context: commercial or non-commercial, public or private, open or closed source.
**Copyright (c) 2014–2021, Krisjanis Rijnieks and contributors**
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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

496
README.md

@ -1,248 +1,248 @@
# ofxPiMapper
[![Ubuntu Workflow Badge](https://github.com/kr15h/ofxPiMapper/workflows/linux/badge.svg)](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Alinux)
[![Windows Workflow Badge](https://github.com/kr15h/ofxPiMapper/workflows/windows/badge.svg)](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Awindows)
[![OSX Workflow Badge](https://github.com/kr15h/ofxPiMapper/workflows/osx/badge.svg)](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Aosx)
Projection mapping addon for openFrameworks that runs on the Raspberry Pi. It has been tested against openFrameworks version (0.11.0).
The project started as master's thesis project by [Krisjanis Rijnieks](https://rijnieks.com) at the [Aalto Media Lab](https://www.aalto.fi/en/aalto-media-lab). Currently being developed during free time. Please [donate](https://ofxpimapper.com/) to create more free time.
Note on build status: GitHub Actions ubuntu-latest, windows-latest and osx-latest images with 64bit environments are used. To be reviewed.
## Disk Image
For those not using openFrameworks, there is a precompiled disk image available via [ofxPiMapper website](https://ofxpimapper.com). It works with Raspberry Pi up until version 3B+ (with the older BCM2837 chip). Given the recent growing interest in the project, some effort is being put into figuring out how to make the disk image to work on Pi 4 and Pi 5 (and Pi 3B+ with the more recent BCM2837B0 chip). Please [donate](https://ofxpimapper.com/) to increase the frequency and duration of these efforts.
> **Warning!** It does not work on the latest generation of Raspberry Pi 3B+ with the BCM2837B0 chip. Make sure the Pi has the older BCM2837 chip when purchasing.
## Introduction
This repository contains the addon for [openFrameworks](https://openframeworks.cc). It is expected to be used as an extension for your custom openFrameworks project where you create a custom [FBO source](example_fbo-sources) that is being animated by an advanced process rather than a plain video.
If you are planning to use videos and images only, consider using the precompiled Raspberry Pi image available from the [ofxPiMapper website](https://ofxpimapper.com). It is based on a recent Raspberry Pi OS disk image and contains compiled installation of openFrameworks along with all the scripts and services that make Pi Mapper start automatically.
## Installation
Clone or download the repository to your openFrameworks addons folder. Make sure that default openFrameworks examples compile and run before trying ofxPiMapper examples. There are a few things that you should do depending on if you are compiling on the Raspberry Pi or not.
- Raspberry Pi
Please install the [ofxOMXPlayer](https://github.com/jvcleave/ofxOMXPlayer) addon before compiling.
- Windows MSYS2
Go to `patches/msys2` directory and run `./patch.sh`
- Other platforms
Please rename the `addons.make.rpi` file to `addons.make`.
To test, use Terminal to change the directory to `example_basic`, compile and run.
```
cd path/to/openFrameworks/addons/ofxPiMapper/example_basic
make
cd bin
./example_basic
```
If you plan to use `example_remote-server` and `example_remote-client`, make sure that you have added [ofxJSON](https://github.com/jeffcrouse/ofxJSON) dependency to your `openFrameworks/addons` folder prior compilation.
## Usage
Currently a keyboard and a mouse has to be used in order to do the mapping with ofxPiMapper.
### Modes
PiMapper has 4 modes:
1. Presentation mode
2. Texture mapping mode
3. Surface editing mode
4. Source assignment mode
You can access these modes by pressing 1, 2, 3 or 4 respectively.
#### Presentation mode
This mode is activated once the application starts up. It does not show anything else except the final projection mapping as it was saved previously.
#### Texture mapping mode
In this mode you can adjust the texture coordinates of the surface you have selected in the surface editing mode.
#### Surface editing mode
Here you can select, move and distort the surfaces you have created.
#### Source assignment mode
After you select a surface in surface editing mode, activate this mode to be able to choose a source for the surface. Afterwards you might want to go to the texture mapping mode to adjust texture coordinates.
### Other shortcuts
These other shortcuts that you can use while using the example app.
Key | Function
:--- | :---
1 | Presentation mode
2 | Texture editing mode
3 | Projection mapping mode, use this to select a surface first
4 | Source selection mode
i | Show info
t | Add triangle surface
q | Add quad surface
g | Add grid warp surface
c | Add circle surface
d | Duplicate selected surface
\+ | Scale surface up
\- | Scale surface down
p | Toggle perspective warping (quad surfaces only)
F | Expand selected surface to fill the screen (quad surfaces only)
] | Add columns to grid surface (grid warp surfaces only)
[ | Remove columns from grid surface (grid warp surfaces only)
} | Add rows to grid surface (grid warp surfaces only)
{ | Remove rows from grid surface (grid warp surfaces only)
. | Select next surface (projection mapping mode only)
, | Select previous surface (projection mapping mode only)
\> | Select next vertex
\< | Select previous vertex
0 | Move selected surface one layer up
9 | Move selected surface one layer down
s | Save composition
l | Hide/show layer panel
z | Undo
rbt | Reboot (Raspberry Pi only)
sdn | Shutdown (Raspberry Pi only)
new | Clear composition (remove all surfaces)
ext | Exit application and return to command line
BACKSPACE ('\' via SSH) | Delete surface.
SPACE | Toggle pause for video sources (texture and projection mapping modes)
TAB | Select next source (no need to use the source selection interface)
Arrow keys | Move selection. If no surface is selected in the projection mapping mode, all surfaces are moved.
\/ | Toggle 1px/10px steps for keyboard moves on Raspberry Pi
## Notes on Video Encoding
Easiest way to achieve success is to use [HandBrake](https://handbrake.fr/) with the following settings. This will produce a `.mkv` file with 16bit FLAC audio with 22.05KHz sampling rate.
```
Preset: Fast 720p30
Summary / Format: MKV File
Video / Framerate: Same as source
Video / Profile: Baseline
Audio / Codec: FLAC 16-bit
Audio / Samplerate: 22.05
```
If you are familiar with [ffmpeg](http://ffmpeg.org/), use the following. It will produce a `.mov` file. PCM audio codec with 22KHz sampling rate is used.
```
ffmpeg -i input-video.mp4 -s 1280x720 -aspect 16:9 \
-c:v libx264 -profile:v baseline \
-c:a pcm_s16le -ar 22000 -ac 2 \
output-video.mov
```
These two settings have shown the best results so far. Audio problems and video playback at the beginning of longer video files was the main issue in most cases. Please open an issue if you have better suggestions.
## Extended Functionality
Examples represent extended functionality of ofxPiMapper. Enter each example separately to find out more.
- [Basic Example](example_basic).
- [FBO Sources Example](example_fbo-sources).
- [Camera Example](example_camera).
- [Remote Control Server](example_remote-server) example.
- [Remote Control Client](example_remote-client) example.
- Readme's for the rest are cooking...
## Problems with Audio
If you are having problems with audio playback, here are two steps for you. Before you do these, make sure audio of your video file works.
### Step 1
Open example openFrameworks application `ofApp.cpp` file in a text editor.
```
cd /home/pi/openFrameworks/addons/ofxPiMapper/example
nano src/ofApp.cpp
```
Make sure that the following line looks as follows.
```
ofx::piMapper::VideoSource::enableAudio = true;
```
Save the file (CTRL + X, Y and ENTER). Recompile and run the example.
```
make && make run
```
### Step 2
If the sound still does not work, try to use `raspi-config`.
```
sudo raspi-config
```
Select "7 Advanced Options" and "A9 Audio" then "0 Auto". You can use one of the force options if you want to be 100% sure.
Open alsamixer.
```
alsamixer
```
Set the volume to a value between 90 to 100 by using the arrow keys. ESC to exit the mixer.
Launch ofxPiMapper example, select a surface and set a video source with audio. Should work.
## Development
Keeping it simple. Developing ofxPiMapper master branch against the latest stable release version of openFrameworks.
## Licence
ofxPiMapper is distributed under the [MIT License](https://en.wikipedia.org/wiki/MIT_License). See the [LICENSE](LICENSE.md) file for further details. Just add my name somewhere along your project [Krisjanis Rijnieks](https://rijnieks.com) whenever possible.
## Supporters
You can become a supporter by donating BitCoins, via PayPal or becoming a Patreon. Please check https://ofxpimapper.com for details. List of supporters below.
- [Marc-André Gasser](https://www.magdesign.ch/)
- Manuel Meißner
## Dependencies
Before moving on, make sure that you have all the dependencies installed.
- ofxGui (available in oF by default)
- ofxXmlSettings (available in oF by default)
- [ofxOMXPlayer](https://github.com/jvcleave/ofxOMXPlayer) (needed only on Raspberry Pi)
To install dependencies, `cd` into `openFrameworks/addons` directory and execute the following:
```bash
git clone https://github.com/jvcleave/ofxOMXPlayer.git
```
The `ofxOMXPlayer` addon recommends you to use its releases. Currently the latest release is `0.9.0-compatible`. To checkout the code of the relase, go to the `ofxOMXPlayer` addon directory and checkout the relase.
```
cd openFrameworks/addons/ofxOMXPlayer
git checkout 0.9.0-compatible
```
You can check the latest releases on the [ofxOMXPlayer GitHub repository](https://github.com/jvcleave/ofxOMXPlayer/releases).
# ofxPiMapper
[![Ubuntu Workflow Badge](https://github.com/kr15h/ofxPiMapper/workflows/linux/badge.svg)](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Alinux)
[![Windows Workflow Badge](https://github.com/kr15h/ofxPiMapper/workflows/windows/badge.svg)](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Awindows)
[![OSX Workflow Badge](https://github.com/kr15h/ofxPiMapper/workflows/osx/badge.svg)](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Aosx)
Projection mapping addon for openFrameworks that runs on the Raspberry Pi. It has been tested against openFrameworks version (0.11.0).
The project started as master's thesis project by [Krisjanis Rijnieks](https://rijnieks.com) at the [Aalto Media Lab](https://www.aalto.fi/en/aalto-media-lab). Currently being developed during free time. Please [donate](https://ofxpimapper.com/) to create more free time.
Note on build status: GitHub Actions ubuntu-latest, windows-latest and osx-latest images with 64bit environments are used. To be reviewed.
## Disk Image
For those not using openFrameworks, there is a precompiled disk image available via [ofxPiMapper website](https://ofxpimapper.com). It works with Raspberry Pi up until version 3B+ (with the older BCM2837 chip). Given the recent growing interest in the project, some effort is being put into figuring out how to make the disk image to work on Pi 4 and Pi 5 (and Pi 3B+ with the more recent BCM2837B0 chip). Please [donate](https://ofxpimapper.com/) to increase the frequency and duration of these efforts.
> **Warning!** It does not work on the latest generation of Raspberry Pi 3B+ with the BCM2837B0 chip. Make sure the Pi has the older BCM2837 chip when purchasing.
## Introduction
This repository contains the addon for [openFrameworks](https://openframeworks.cc). It is expected to be used as an extension for your custom openFrameworks project where you create a custom [FBO source](example_fbo-sources) that is being animated by an advanced process rather than a plain video.
If you are planning to use videos and images only, consider using the precompiled Raspberry Pi image available from the [ofxPiMapper website](https://ofxpimapper.com). It is based on a recent Raspberry Pi OS disk image and contains compiled installation of openFrameworks along with all the scripts and services that make Pi Mapper start automatically.
## Installation
Clone or download the repository to your openFrameworks addons folder. Make sure that default openFrameworks examples compile and run before trying ofxPiMapper examples. There are a few things that you should do depending on if you are compiling on the Raspberry Pi or not.
- Raspberry Pi
Please install the [ofxOMXPlayer](https://github.com/jvcleave/ofxOMXPlayer) addon before compiling.
- Windows MSYS2
Go to `patches/msys2` directory and run `./patch.sh`
- Other platforms
Please rename the `addons.make.rpi` file to `addons.make`.
To test, use Terminal to change the directory to `example_basic`, compile and run.
```
cd path/to/openFrameworks/addons/ofxPiMapper/example_basic
make
cd bin
./example_basic
```
If you plan to use `example_remote-server` and `example_remote-client`, make sure that you have added [ofxJSON](https://github.com/jeffcrouse/ofxJSON) dependency to your `openFrameworks/addons` folder prior compilation.
## Usage
Currently a keyboard and a mouse has to be used in order to do the mapping with ofxPiMapper.
### Modes
PiMapper has 4 modes:
1. Presentation mode
2. Texture mapping mode
3. Surface editing mode
4. Source assignment mode
You can access these modes by pressing 1, 2, 3 or 4 respectively.
#### Presentation mode
This mode is activated once the application starts up. It does not show anything else except the final projection mapping as it was saved previously.
#### Texture mapping mode
In this mode you can adjust the texture coordinates of the surface you have selected in the surface editing mode.
#### Surface editing mode
Here you can select, move and distort the surfaces you have created.
#### Source assignment mode
After you select a surface in surface editing mode, activate this mode to be able to choose a source for the surface. Afterwards you might want to go to the texture mapping mode to adjust texture coordinates.
### Other shortcuts
These other shortcuts that you can use while using the example app.
Key | Function
:--- | :---
1 | Presentation mode
2 | Texture editing mode
3 | Projection mapping mode, use this to select a surface first
4 | Source selection mode
i | Show info
t | Add triangle surface
q | Add quad surface
g | Add grid warp surface
c | Add circle surface
d | Duplicate selected surface
\+ | Scale surface up
\- | Scale surface down
p | Toggle perspective warping (quad surfaces only)
F | Expand selected surface to fill the screen (quad surfaces only)
] | Add columns to grid surface (grid warp surfaces only)
[ | Remove columns from grid surface (grid warp surfaces only)
} | Add rows to grid surface (grid warp surfaces only)
{ | Remove rows from grid surface (grid warp surfaces only)
. | Select next surface (projection mapping mode only)
, | Select previous surface (projection mapping mode only)
\> | Select next vertex
\< | Select previous vertex
0 | Move selected surface one layer up
9 | Move selected surface one layer down
s | Save composition
l | Hide/show layer panel
z | Undo
rbt | Reboot (Raspberry Pi only)
sdn | Shutdown (Raspberry Pi only)
new | Clear composition (remove all surfaces)
ext | Exit application and return to command line
BACKSPACE ('\' via SSH) | Delete surface.
SPACE | Toggle pause for video sources (texture and projection mapping modes)
TAB | Select next source (no need to use the source selection interface)
Arrow keys | Move selection. If no surface is selected in the projection mapping mode, all surfaces are moved.
\/ | Toggle 1px/10px steps for keyboard moves on Raspberry Pi
## Notes on Video Encoding
Easiest way to achieve success is to use [HandBrake](https://handbrake.fr/) with the following settings. This will produce a `.mkv` file with 16bit FLAC audio with 22.05KHz sampling rate.
```
Preset: Fast 720p30
Summary / Format: MKV File
Video / Framerate: Same as source
Video / Profile: Baseline
Audio / Codec: FLAC 16-bit
Audio / Samplerate: 22.05
```
If you are familiar with [ffmpeg](http://ffmpeg.org/), use the following. It will produce a `.mov` file. PCM audio codec with 22KHz sampling rate is used.
```
ffmpeg -i input-video.mp4 -s 1280x720 -aspect 16:9 \
-c:v libx264 -profile:v baseline \
-c:a pcm_s16le -ar 22000 -ac 2 \
output-video.mov
```
These two settings have shown the best results so far. Audio problems and video playback at the beginning of longer video files was the main issue in most cases. Please open an issue if you have better suggestions.
## Extended Functionality
Examples represent extended functionality of ofxPiMapper. Enter each example separately to find out more.
- [Basic Example](example_basic).
- [FBO Sources Example](example_fbo-sources).
- [Camera Example](example_camera).
- [Remote Control Server](example_remote-server) example.
- [Remote Control Client](example_remote-client) example.
- Readme's for the rest are cooking...
## Problems with Audio
If you are having problems with audio playback, here are two steps for you. Before you do these, make sure audio of your video file works.
### Step 1
Open example openFrameworks application `ofApp.cpp` file in a text editor.
```
cd /home/pi/openFrameworks/addons/ofxPiMapper/example
nano src/ofApp.cpp
```
Make sure that the following line looks as follows.
```
ofx::piMapper::VideoSource::enableAudio = true;
```
Save the file (CTRL + X, Y and ENTER). Recompile and run the example.
```
make && make run
```
### Step 2
If the sound still does not work, try to use `raspi-config`.
```
sudo raspi-config
```
Select "7 Advanced Options" and "A9 Audio" then "0 Auto". You can use one of the force options if you want to be 100% sure.
Open alsamixer.
```
alsamixer
```
Set the volume to a value between 90 to 100 by using the arrow keys. ESC to exit the mixer.
Launch ofxPiMapper example, select a surface and set a video source with audio. Should work.
## Development
Keeping it simple. Developing ofxPiMapper master branch against the latest stable release version of openFrameworks.
## Licence
ofxPiMapper is distributed under the [MIT License](https://en.wikipedia.org/wiki/MIT_License). See the [LICENSE](LICENSE.md) file for further details. Just add my name somewhere along your project [Krisjanis Rijnieks](https://rijnieks.com) whenever possible.
## Supporters
You can become a supporter by donating BitCoins, via PayPal or becoming a Patreon. Please check https://ofxpimapper.com for details. List of supporters below.
- [Marc-André Gasser](https://www.magdesign.ch/)
- Manuel Meißner
## Dependencies
Before moving on, make sure that you have all the dependencies installed.
- ofxGui (available in oF by default)
- ofxXmlSettings (available in oF by default)
- [ofxOMXPlayer](https://github.com/jvcleave/ofxOMXPlayer) (needed only on Raspberry Pi)
To install dependencies, `cd` into `openFrameworks/addons` directory and execute the following:
```bash
git clone https://github.com/jvcleave/ofxOMXPlayer.git
```
The `ofxOMXPlayer` addon recommends you to use its releases. Currently the latest release is `0.9.0-compatible`. To checkout the code of the relase, go to the `ofxOMXPlayer` addon directory and checkout the relase.
```
cd openFrameworks/addons/ofxOMXPlayer
git checkout 0.9.0-compatible
```
You can check the latest releases on the [ofxOMXPlayer GitHub repository](https://github.com/jvcleave/ofxOMXPlayer/releases).

152
addon_config.mk

@ -1,76 +1,76 @@
# All variables and this file are optional, if they are not present the PG and the
# makefiles will try to parse the correct values from the file system.
#
# Variables that specify exclusions can use % as a wildcard to specify that anything in
# that position will match. A partial path can also be specified to, for example, exclude
# a whole folder from the parsed paths from the file system
#
# Variables can be specified using = or +=
# = will clear the contents of that variable both specified from the file or the ones parsed
# from the file system
# += will add the values to the previous ones in the file or the ones parsed from the file
# system
#
# The PG can be used to detect errors in this file, just create a new project with this addon
# and the PG will write to the console the kind of error and in which line it is
meta:
ADDON_NAME = ofxPiMapper
ADDON_DESCRIPTION = Projection mapping addon for openFrameworks
ADDON_AUTHOR = @kr15h
ADDON_TAGS = "addon" "rpi" "mapping"
ADDON_URL = http://github.com/kr15h/ofxPiMapper
common:
# dependencies with other addons, a list of them separated by spaces
# or use += in several lines
ADDON_DEPENDENCIES = ofxXmlSettings ofxGui
# include search paths, this will be usually parsed from the file system
# but if the addon or addon libraries need special search paths they can be
# specified here separated by spaces or one per line using +=
# ADDON_INCLUDES =
# any special flag that should be passed to the compiler when using this
# addon
# ADDON_CFLAGS =
# any special flag that should be passed to the linker when using this
# addon, also used for system libraries with -lname
# ADDON_LDFLAGS =
# linux only, any library that should be included in the project using
# pkg-config
# ADDON_PKG_CONFIG_LIBRARIES =
# osx/iOS only, any framework that should be included in the project
# ADDON_FRAMEWORKS =
# source files, these will be usually parsed from the file system looking
# in the src folders in libs and the root of the addon. if your addon needs
# to include files in different places or a different set of files per platform
# they can be specified here
# ADDON_SOURCES =
# some addons need resources to be copied to the bin/data folder of the project
# specify here any files that need to be copied, you can use wildcards like * and ?
# ADDON_DATA =
# when parsing the file system looking for libraries exclude this for all or
# a specific platform
# ADDON_LIBS_EXCLUDE =
linux64:
# binary libraries, these will be usually parsed from the file system but some
# libraries need to passed to the linker in a specific order
ADDON_LIBS =
linux:
ADDON_LIBS =
win_cb:
ADDON_LIBS =
linuxarmv6l:
ADDON_LIBS =
linuxarmv7l:
ADDON_LIBS =
android/armeabi:
ADDON_LIBS =
# All variables and this file are optional, if they are not present the PG and the
# makefiles will try to parse the correct values from the file system.
#
# Variables that specify exclusions can use % as a wildcard to specify that anything in
# that position will match. A partial path can also be specified to, for example, exclude
# a whole folder from the parsed paths from the file system
#
# Variables can be specified using = or +=
# = will clear the contents of that variable both specified from the file or the ones parsed
# from the file system
# += will add the values to the previous ones in the file or the ones parsed from the file
# system
#
# The PG can be used to detect errors in this file, just create a new project with this addon
# and the PG will write to the console the kind of error and in which line it is
meta:
ADDON_NAME = ofxPiMapper
ADDON_DESCRIPTION = Projection mapping addon for openFrameworks
ADDON_AUTHOR = @kr15h
ADDON_TAGS = "addon" "rpi" "mapping"
ADDON_URL = http://github.com/kr15h/ofxPiMapper
common:
# dependencies with other addons, a list of them separated by spaces
# or use += in several lines
ADDON_DEPENDENCIES = ofxXmlSettings ofxGui
# include search paths, this will be usually parsed from the file system
# but if the addon or addon libraries need special search paths they can be
# specified here separated by spaces or one per line using +=
# ADDON_INCLUDES =
# any special flag that should be passed to the compiler when using this
# addon
# ADDON_CFLAGS =
# any special flag that should be passed to the linker when using this
# addon, also used for system libraries with -lname
# ADDON_LDFLAGS =
# linux only, any library that should be included in the project using
# pkg-config
# ADDON_PKG_CONFIG_LIBRARIES =
# osx/iOS only, any framework that should be included in the project
# ADDON_FRAMEWORKS =
# source files, these will be usually parsed from the file system looking
# in the src folders in libs and the root of the addon. if your addon needs
# to include files in different places or a different set of files per platform
# they can be specified here
# ADDON_SOURCES =
# some addons need resources to be copied to the bin/data folder of the project
# specify here any files that need to be copied, you can use wildcards like * and ?
# ADDON_DATA =
# when parsing the file system looking for libraries exclude this for all or
# a specific platform
# ADDON_LIBS_EXCLUDE =
linux64:
# binary libraries, these will be usually parsed from the file system but some
# libraries need to passed to the linker in a specific order
ADDON_LIBS =
linux:
ADDON_LIBS =
win_cb:
ADDON_LIBS =
linuxarmv6l:
ADDON_LIBS =
linuxarmv7l:
ADDON_LIBS =
android/armeabi:
ADDON_LIBS =

26
example_basic/Makefile

@ -1,13 +1,13 @@
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk

14
example_basic/README.md

@ -1,7 +1,7 @@
# Basic Example
This is a very basic example. It shows how to use ofxPiMapper addon with it's integrated functionality. You can map images and videos with this. ofxPiMapper takes care of loading and saving your composition.
For now you have to put your sources under `bin/data/sources`. There are two directories: `images` and `videos`. As you may expect, put images in the `images` folder and videos in the `videos` one.
The addon is made so that you have to pass the keyboard and mouse events to it. It is because in this way you can gain more control over how it behaves. If you do not pass the keyboard and mouse events, ofxPiMapper reads the configuration file from `data/ofxpimapper.xml` and continues working from there. It just starts up, loads the configuration and displays the composition until the application quits.
# Basic Example
This is a very basic example. It shows how to use ofxPiMapper addon with it's integrated functionality. You can map images and videos with this. ofxPiMapper takes care of loading and saving your composition.
For now you have to put your sources under `bin/data/sources`. There are two directories: `images` and `videos`. As you may expect, put images in the `images` folder and videos in the `videos` one.
The addon is made so that you have to pass the keyboard and mouse events to it. It is because in this way you can gain more control over how it behaves. If you do not pass the keyboard and mouse events, ofxPiMapper reads the configuration file from `data/ofxpimapper.xml` and continues working from there. It just starts up, loads the configuration and displays the composition until the application quits.

8
example_basic/addons.make

@ -1,4 +1,4 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer

6
example_basic/addons.make.norpi

@ -1,3 +1,3 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxGui
ofxPiMapper
ofxXmlSettings

239
example_basic/bin/data/ofxpimapper.xml

@ -1,36 +1,203 @@
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>512.000000000</x>
<y>50.000000000</y>
</vertex>
<vertex>
<x>974.000000000</x>
<y>718.000000000</y>
</vertex>
<vertex>
<x>50.000000000</x>
<y>718.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>video</source-type>
<source-name>gene-nsynthesis-loop-a.mp4</source-name>
</source>
</surface>
</surfaces>
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>452.000000000</x>
<y>221.000000000</y>
</vertex>
<vertex>
<x>1017.744750977</x>
<y>744.464965820</y>
</vertex>
<vertex>
<x>6.254730225</x>
<y>744.464965820</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>video</source-type>
<source-name>gene-nsynthesis-loop-c.mp4</source-name>
<source-loop>1</source-loop>
</source>
</surface>
<surface type="0">
<vertices>
<vertex>
<x>512.000000000</x>
<y>50.000000000</y>
</vertex>
<vertex>
<x>974.000000000</x>
<y>718.000000000</y>
</vertex>
<vertex>
<x>50.000000000</x>
<y>718.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>video</source-type>
<source-name>gene-nsynthesis-loop-a.mp4</source-name>
<source-loop>1</source-loop>
</source>
</surface>
<surface type="2">
<vertices>
<vertex>
<x>-8.000000000</x>
<y>6.000000000</y>
</vertex>
<vertex>
<x>434.000000000</x>
<y>250.000000000</y>
</vertex>
<vertex>
<x>920.000000000</x>
<y>101.000000000</y>
</vertex>
<vertex>
<x>-4.000000000</x>
<y>397.000000000</y>
</vertex>
<vertex>
<x>508.000000000</x>
<y>385.000000000</y>
</vertex>
<vertex>
<x>920.000000000</x>
<y>385.000000000</y>
</vertex>
<vertex>
<x>2.254730225</x>
<y>745.464965820</y>
</vertex>
<vertex>
<x>508.000000000</x>
<y>669.000000000</y>
</vertex>
<vertex>
<x>920.000000000</x>
<y>669.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>0.500000000</y>
</texCoord>
<texCoord>
<x>0.500000000</x>
<y>0.500000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>0.500000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.500000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>none</source-type>
<source-name>none</source-name>
</source>
<properties>
<gridCols>2</gridCols>
<gridRows>2</gridRows>
</properties>
</surface>
<surface type="5">
<vertices>
<vertex>
<x>267.996795654</x>
<y>22.747558594</y>
</vertex>
<vertex>
<x>267.996795654</x>
<y>147.252563477</y>
</vertex>
<vertex>
<x>434.003723145</x>
<y>147.252563477</y>
</vertex>
<vertex>
<x>434.003723145</x>
<y>22.747558594</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>none</source-type>
<source-name>none</source-name>
</source>
<properties>
<perspectiveWarping>1</perspectiveWarping>
</properties>
</surface>
</surfaces>

14
example_basic/src/main.cpp

@ -1,7 +1,7 @@
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofSetupOpenGL(1024,768,OF_WINDOW);
ofRunApp(new ofApp());
}
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofSetupOpenGL(1024,768,OF_WINDOW);
ofRunApp(new ofApp());
}

76
example_basic/src/ofApp.cpp

@ -1,38 +1,38 @@
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
mapper.setup();
#ifdef TARGET_RASPBERRY_PI
ofSetFullscreen(true);
#endif
}
void ofApp::update(){
mapper.update();
}
void ofApp::draw(){
mapper.draw();
}
void ofApp::keyPressed(int key){
mapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
mapper.keyReleased(key);
}
void ofApp::mouseDragged(int x, int y, int button){
mapper.mouseDragged(x, y, button);
}
void ofApp::mousePressed(int x, int y, int button){
mapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
mapper.mouseReleased(x, y, button);
}
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
mapper.setup();
#ifdef TARGET_RASPBERRY_PI
ofSetFullscreen(true);
#endif
}
void ofApp::update(){
mapper.update();
}
void ofApp::draw(){
mapper.draw();
}
void ofApp::keyPressed(int key){
mapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
mapper.keyReleased(key);
}
void ofApp::mouseDragged(int x, int y, int button){
mapper.mouseDragged(x, y, button);
}
void ofApp::mousePressed(int x, int y, int button){
mapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
mapper.mouseReleased(x, y, button);
}

50
example_basic/src/ofApp.h

@ -1,25 +1,25 @@
#pragma once
#include "ofMain.h"
#include "ofxPiMapper.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
// We need to forward key and mouse events to ofxPiMapper.
// By not doing it we have the opportunity to use ofxPiMapper
// witout the interface.
void keyPressed(int key);
void keyReleased(int key);
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
// This is our mapper object.
ofxPiMapper mapper;
};
#pragma once
#include "ofMain.h"
#include "ofxPiMapper.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
// We need to forward key and mouse events to ofxPiMapper.
// By not doing it we have the opportunity to use ofxPiMapper
// witout the interface.
void keyPressed(int key);
void keyReleased(int key);
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
// This is our mapper object.
ofxPiMapper mapper;
};

10
example_camera/.gitignore

@ -1,5 +1,5 @@
obj
*.xcworkspace
*.xcuserdatad
*~
config.make
obj
*.xcworkspace
*.xcuserdatad
*~
config.make

26
example_camera/Makefile

@ -1,13 +1,13 @@
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk

18
example_camera/README.md

@ -1,9 +1,9 @@
# Camera Example
This example demonstrates the possibility to use camera input as a texture source. Make sure you clone the [ofxRPiCameraVideoGrabber](https://github.com/jvcleave/ofxRPiCameraVideoGrabber) addon into your `openFrameworks/addons` folder before compiling on Raspberry Pi.
```
cd openFrameworks/addons
git clone https://github.com/jvcleave/ofxRPiCameraVideoGrabber.git
```
# Camera Example
This example demonstrates the possibility to use camera input as a texture source. Make sure you clone the [ofxRPiCameraVideoGrabber](https://github.com/jvcleave/ofxRPiCameraVideoGrabber) addon into your `openFrameworks/addons` folder before compiling on Raspberry Pi.
```
cd openFrameworks/addons
git clone https://github.com/jvcleave/ofxRPiCameraVideoGrabber.git
```

10
example_camera/addons.make

@ -1,5 +1,5 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer
ofxRPiCameraVideoGrabber
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer
ofxRPiCameraVideoGrabber

6
example_camera/addons.make.norpi

@ -1,3 +1,3 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxGui
ofxPiMapper
ofxXmlSettings

72
example_camera/bin/data/defaultSurfaces.xml

@ -1,36 +1,36 @@
<surfaces>
<surface>
<vertices>
<vertex>
<x>415.000000000</x>
<y>51.000000000</y>
</vertex>
<vertex>
<x>581.000000000</x>
<y>388.000000000</y>
</vertex>
<vertex>
<x>183.000000000</x>
<y>357.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.556249976</x>
<y>0.108333334</y>
</texCoord>
<texCoord>
<x>0.862500012</x>
<y>0.941666663</y>
</texCoord>
<texCoord>
<x>0.118749999</x>
<y>0.862500012</y>
</texCoord>
</texCoords>
<source>
<source-type>fbo</source-type>
<source-name>Camera Source</source-name>
</source>
</surface>
</surfaces>
<surfaces>
<surface>
<vertices>
<vertex>
<x>415.000000000</x>
<y>51.000000000</y>
</vertex>
<vertex>
<x>581.000000000</x>
<y>388.000000000</y>
</vertex>
<vertex>
<x>183.000000000</x>
<y>357.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.556249976</x>
<y>0.108333334</y>
</texCoord>
<texCoord>
<x>0.862500012</x>
<y>0.941666663</y>
</texCoord>
<texCoord>
<x>0.118749999</x>
<y>0.862500012</y>
</texCoord>
</texCoords>
<source>
<source-type>fbo</source-type>
<source-name>Camera Source</source-name>
</source>
</surface>
</surfaces>

140
example_camera/bin/data/ofxpimapper.xml

@ -1,70 +1,70 @@
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>437.000000000</x>
<y>82.000000000</y>
</vertex>
<vertex>
<x>991.000000000</x>
<y>75.000000000</y>
</vertex>
<vertex>
<x>750.000000000</x>
<y>485.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.351562500</x>
<y>0.072222225</y>
</texCoord>
<texCoord>
<x>0.857812524</x>
<y>0.125000000</y>
</texCoord>
<texCoord>
<x>0.549218774</x>
<y>0.695833325</y>
</texCoord>
</texCoords>
<source>
<source-type>fbo</source-type>
<source-name>Camera Source</source-name>
</source>
</surface>
<surface type="0">
<vertices>
<vertex>
<x>437.000000000</x>
<y>82.000000000</y>
</vertex>
<vertex>
<x>750.000000000</x>
<y>485.000000000</y>
</vertex>
<vertex>
<x>112.000000000</x>
<y>476.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.341406256</x>
<y>0.073611110</y>
</texCoord>
<texCoord>
<x>0.557031274</x>
<y>0.690277755</y>
</texCoord>
<texCoord>
<x>0.064843751</x>
<y>0.558333337</y>
</texCoord>
</texCoords>
<source>
<source-type>fbo</source-type>
<source-name>Camera Source</source-name>
</source>
</surface>
</surfaces>
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>437.000000000</x>
<y>82.000000000</y>
</vertex>
<vertex>
<x>991.000000000</x>
<y>75.000000000</y>
</vertex>
<vertex>
<x>750.000000000</x>
<y>485.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.351562500</x>
<y>0.072222225</y>
</texCoord>
<texCoord>
<x>0.857812524</x>
<y>0.125000000</y>
</texCoord>
<texCoord>
<x>0.549218774</x>
<y>0.695833325</y>
</texCoord>
</texCoords>
<source>
<source-type>fbo</source-type>
<source-name>Camera Source</source-name>
</source>
</surface>
<surface type="0">
<vertices>
<vertex>
<x>437.000000000</x>
<y>82.000000000</y>
</vertex>
<vertex>
<x>750.000000000</x>
<y>485.000000000</y>
</vertex>
<vertex>
<x>112.000000000</x>
<y>476.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.341406256</x>
<y>0.073611110</y>
</texCoord>
<texCoord>
<x>0.557031274</x>
<y>0.690277755</y>
</texCoord>
<texCoord>
<x>0.064843751</x>
<y>0.558333337</y>
</texCoord>
</texCoords>
<source>
<source-type>fbo</source-type>
<source-name>Camera Source</source-name>
</source>
</surface>
</surfaces>

124
example_camera/src/CameraSource.cpp

@ -1,62 +1,62 @@
#include "CameraSource.h"
CameraSource::CameraSource(){
name = "Camera Source";
_cameraWidth = 1280;
_cameraHeight = 720;
#ifdef TARGET_RASPBERRY_PI
_omxCameraSettings.width = _cameraWidth;
_omxCameraSettings.height = _cameraHeight;
_omxCameraSettings.framerate = 30;
_omxCameraSettings.enableTexture = true;
_omxCameraSettings.doRecording = false;
_videoGrabber.setup(_omxCameraSettings);
#else
std::vector<ofVideoDevice> devices = _videoGrabber.listDevices();
_cameraFound = false;
for(int i = 0; i < devices.size(); i++){
if(devices[i].bAvailable){
ofLogNotice() << devices[i].id << ": " << devices[i].deviceName;
_cameraFound = true;
break;
}
}
if(_cameraFound){
_videoGrabber.setDeviceID(0);
_videoGrabber.setup(_cameraWidth, _cameraHeight);
}
#endif
allocate(_cameraWidth, _cameraHeight);
}
void CameraSource::update(){
#ifndef TARGET_RASPBERRY_PI
if(_videoGrabber.isInitialized()){
_videoGrabber.update();
}
#endif
}
void CameraSource::draw(){
ofClear(0);
ofSetHexColor(0xffffff);
#ifdef TARGET_RASPBERRY_PI
ofDisableNormalizedTexCoords();
_videoGrabber.draw(0, 0);
ofEnableNormalizedTexCoords();
#else
if(_videoGrabber.isInitialized()){
ofDisableNormalizedTexCoords();
_videoGrabber.draw(0, 0);
ofEnableNormalizedTexCoords();
}else{
ofDrawBitmapString("no camera", _cameraWidth / 2.0f - 40.0f, _cameraHeight / 2.0f + 10.0f);
}
#endif
}
#include "CameraSource.h"
CameraSource::CameraSource(){
name = "Camera Source";
_cameraWidth = 1280;
_cameraHeight = 720;
#ifdef TARGET_RASPBERRY_PI
_omxCameraSettings.width = _cameraWidth;
_omxCameraSettings.height = _cameraHeight;
_omxCameraSettings.framerate = 30;
_omxCameraSettings.enableTexture = true;
_omxCameraSettings.doRecording = false;
_videoGrabber.setup(_omxCameraSettings);
#else
std::vector<ofVideoDevice> devices = _videoGrabber.listDevices();
_cameraFound = false;
for(int i = 0; i < devices.size(); i++){
if(devices[i].bAvailable){
ofLogNotice() << devices[i].id << ": " << devices[i].deviceName;
_cameraFound = true;
break;
}
}
if(_cameraFound){
_videoGrabber.setDeviceID(0);
_videoGrabber.setup(_cameraWidth, _cameraHeight);
}
#endif
allocate(_cameraWidth, _cameraHeight);
}
void CameraSource::update(){
#ifndef TARGET_RASPBERRY_PI
if(_videoGrabber.isInitialized()){
_videoGrabber.update();
}
#endif
}
void CameraSource::draw(){
ofClear(0);
ofSetHexColor(0xffffff);
#ifdef TARGET_RASPBERRY_PI
ofDisableNormalizedTexCoords();
_videoGrabber.draw(0, 0);
ofEnableNormalizedTexCoords();
#else
if(_videoGrabber.isInitialized()){
ofDisableNormalizedTexCoords();
_videoGrabber.draw(0, 0);
ofEnableNormalizedTexCoords();
}else{
ofDrawBitmapString("no camera", _cameraWidth / 2.0f - 40.0f, _cameraHeight / 2.0f + 10.0f);
}
#endif
}

66
example_camera/src/CameraSource.h

@ -1,34 +1,34 @@
/*
* CameraSource
* Camera source for ofxPiMapper
* Created by Krisjanis Rijnieks on 25/01/2016
*/
#pragma once
#include "ofMain.h"
#include "FboSource.h"
#ifdef TARGET_RASPBERRY_PI
#include "ofxRPiCameraVideoGrabber.h"
#endif
class CameraSource : public ofx::piMapper::FboSource {
public:
CameraSource();
void update();
void draw();
private:
#ifdef TARGET_RASPBERRY_PI
OMXCameraSettings _omxCameraSettings;
ofxRPiCameraVideoGrabber _videoGrabber;
#else
ofVideoGrabber _videoGrabber;
#endif
int _cameraWidth;
int _cameraHeight;
bool _cameraFound;
/*
* CameraSource
* Camera source for ofxPiMapper
* Created by Krisjanis Rijnieks on 25/01/2016
*/
#pragma once
#include "ofMain.h"
#include "FboSource.h"
#ifdef TARGET_RASPBERRY_PI
#include "ofxRPiCameraVideoGrabber.h"
#endif
class CameraSource : public ofx::piMapper::FboSource {
public:
CameraSource();
void update();
void draw();
private:
#ifdef TARGET_RASPBERRY_PI
OMXCameraSettings _omxCameraSettings;
ofxRPiCameraVideoGrabber _videoGrabber;
#else
ofVideoGrabber _videoGrabber;
#endif
int _cameraWidth;
int _cameraHeight;
bool _cameraFound;
};

48
example_camera/src/main.cpp

@ -1,24 +1,24 @@
#include "ofMain.h"
#include "ofApp.h"
#include <string>
#include <vector>
int main(int argc, char * argv[]){
bool fullscreen = false;
std::vector<std::string> arguments = std::vector<std::string>(argv, argv + argc);
for(int i = 0; i < arguments.size(); ++i){
if(arguments.at(i) == "-f"){
fullscreen = true;
break;
}
}
if(fullscreen){
ofSetupOpenGL(800, 450, OF_FULLSCREEN);
}else{
ofSetupOpenGL(800, 450, OF_WINDOW);
}
ofRunApp(new ofApp());
}
#include "ofMain.h"
#include "ofApp.h"
#include <string>
#include <vector>
int main(int argc, char * argv[]){
bool fullscreen = false;
std::vector<std::string> arguments = std::vector<std::string>(argv, argv + argc);
for(int i = 0; i < arguments.size(); ++i){
if(arguments.at(i) == "-f"){
fullscreen = true;
break;
}
}
if(fullscreen){
ofSetupOpenGL(800, 450, OF_FULLSCREEN);
}else{
ofSetupOpenGL(800, 450, OF_WINDOW);
}
ofRunApp(new ofApp());
}

72
example_camera/src/ofApp.cpp

@ -1,36 +1,36 @@
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
cameraSource = new CameraSource();
piMapper.registerFboSource(*cameraSource);
piMapper.setup();
}
void ofApp::update(){
piMapper.update();
}
void ofApp::draw(){
piMapper.draw();
}
void ofApp::keyPressed(int key){
piMapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
piMapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
piMapper.mousePressed(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
piMapper.mouseDragged(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
piMapper.mouseReleased(x, y, button);
}
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
cameraSource = new CameraSource();
piMapper.registerFboSource(*cameraSource);
piMapper.setup();
}
void ofApp::update(){
piMapper.update();
}
void ofApp::draw(){
piMapper.draw();
}
void ofApp::keyPressed(int key){
piMapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
piMapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
piMapper.mousePressed(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
piMapper.mouseDragged(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
piMapper.mouseReleased(x, y, button);
}

60
example_camera/src/ofApp.h

@ -1,31 +1,31 @@
/*
* CameraSource example
* Can be used with the Raspberry Pi camera module or the Auvidea HDMI bridge.
* B101 HDMI to CSI-2 Bridge (15 pin FPC).
* Available at http://www.auvidea.eu/index.php/theme-styles/2014-12-30-22-32-06/b101
* Created by Krisjanis Rijnieks on 25/01/2016
* Last modified on 10/02/2016
*/
#pragma once
#include "ofMain.h"
#include "ofxPiMapper.h"
#include "CameraSource.h"
class ofApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseDragged(int x, int y, int button);
void mouseReleased(int x, int y, int button);
ofxPiMapper piMapper;
CameraSource * cameraSource;
/*
* CameraSource example
* Can be used with the Raspberry Pi camera module or the Auvidea HDMI bridge.
* B101 HDMI to CSI-2 Bridge (15 pin FPC).
* Available at http://www.auvidea.eu/index.php/theme-styles/2014-12-30-22-32-06/b101
* Created by Krisjanis Rijnieks on 25/01/2016
* Last modified on 10/02/2016
*/
#pragma once
#include "ofMain.h"
#include "ofxPiMapper.h"
#include "CameraSource.h"
class ofApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseDragged(int x, int y, int button);
void mouseReleased(int x, int y, int button);
ofxPiMapper piMapper;
CameraSource * cameraSource;
};

10
example_fbo-sources/.gitignore

@ -1,5 +1,5 @@
obj
*.xcworkspace
*.xcuserdatad
*~
config.make
obj
*.xcworkspace
*.xcuserdatad
*~
config.make

26
example_fbo-sources/Makefile

@ -1,13 +1,13 @@
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk

56
example_fbo-sources/README.md

@ -1,28 +1,28 @@
# FBO Sources Example
This example shows how to use custom (FBO) source functionality with ofxPiMapper. Below you can see a list of custom sources and feel free to add your own via pull requests!
- ScanlineSource
- SlideShowSource
To build your own source, one should start by extending the `FboSource` class. When the source is ready, it should be instantiated in the `ofApp` class and passed via `mapper.registerFboSource(...source)` function before the `mapper.setup()` call. This will make the source name to appear under **FBO Sources** category in the source selection mode.
Look at the source code of the custom sources to understand how to build one, but essentially it is extending the `FboSource` class of `ofxPiMapper` and overriding the `setup()`, `update()` and `draw()` functions.
In the `setup()` function you should set a name for your custom source.
```
name = "Name Your Source";
```
Then you should set the dimensions of your source by using the `allocate()` function.
```
allocate(500, 500);
```
In the `draw()` of your custom `FboSource` you should decide whether you want the previous frame to be cleared from the gfx buffer or not. If you want to draw a fresh frame, use the `ofClear()` function.
```
ofClear(0); // Clear with black
```
# FBO Sources Example
This example shows how to use custom (FBO) source functionality with ofxPiMapper. Below you can see a list of custom sources and feel free to add your own via pull requests!
- ScanlineSource
- SlideShowSource
To build your own source, one should start by extending the `FboSource` class. When the source is ready, it should be instantiated in the `ofApp` class and passed via `mapper.registerFboSource(...source)` function before the `mapper.setup()` call. This will make the source name to appear under **FBO Sources** category in the source selection mode.
Look at the source code of the custom sources to understand how to build one, but essentially it is extending the `FboSource` class of `ofxPiMapper` and overriding the `setup()`, `update()` and `draw()` functions.
In the `setup()` function you should set a name for your custom source.
```
name = "Name Your Source";
```
Then you should set the dimensions of your source by using the `allocate()` function.
```
allocate(500, 500);
```
In the `draw()` of your custom `FboSource` you should decide whether you want the previous frame to be cleared from the gfx buffer or not. If you want to draw a fresh frame, use the `ofClear()` function.
```
ofClear(0); // Clear with black
```

8
example_fbo-sources/addons.make

@ -1,4 +1,4 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer

6
example_fbo-sources/addons.make.norpi

@ -1,3 +1,3 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxGui
ofxPiMapper
ofxXmlSettings

30
example_fbo-sources/bin/data/magslideshow_settings.xml

@ -1,15 +1,15 @@
<magSlideShow>
<Width>800</Width>
<Height>600</Height>
<SlideDuration>2</SlideDuration> <!-- Optional default duration for each slide-->
<Loop>
<Type>NORMAL</Type> <!-- NONE | NORMAL | PING-PONG -->
<Count>0</Count> <!-- 0 = forever -->
</Loop>
<Transition>
<Type>Dissolve</Type>
<Duration>3</Duration>
</Transition>
<!-- NoResize | Native | Fit | FitProportionally | FillProportionally -->
<ResizeOption>FitProportionally</ResizeOption>
</magSlideShow>
<magSlideShow>
<Width>800</Width>
<Height>600</Height>
<SlideDuration>2</SlideDuration> <!-- Optional default duration for each slide-->
<Loop>
<Type>NORMAL</Type> <!-- NONE | NORMAL | PING-PONG -->
<Count>0</Count> <!-- 0 = forever -->
</Loop>
<Transition>
<Type>Dissolve</Type>
<Duration>3</Duration>
</Transition>
<!-- NoResize | Native | Fit | FitProportionally | FillProportionally -->
<ResizeOption>FitProportionally</ResizeOption>
</magSlideShow>

252
example_fbo-sources/bin/data/ofxpimapper.xml

@ -1,126 +1,126 @@
<surfaces>
<surface type="5">
<vertices>
<vertex>
<x>337.195068359</x>
<y>362.146270752</y>
</vertex>
<vertex>
<x>337.195068359</x>
<y>595.853759766</y>
</vertex>
<vertex>
<x>648.804992676</x>
<y>595.853759766</y>
</vertex>
<vertex>
<x>648.804992676</x>
<y>362.146270752</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image4.jpg</source-name>
</source>
<properties>
<perspectiveWarping>1</perspectiveWarping>
</properties>
</surface>
<surface type="1">
<vertices>
<vertex>
<x>522.590332031</x>
<y>188.924621582</y>
</vertex>
<vertex>
<x>835.409606934</x>
<y>188.924621582</y>
</vertex>
<vertex>
<x>835.409606934</x>
<y>415.075378418</y>
</vertex>
<vertex>
<x>522.590332031</x>
<y>415.075378418</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image1.jpg</source-name>
</source>
<properties>
<perspectiveWarping>1</perspectiveWarping>
</properties>
</surface>
<surface type="0">
<vertices>
<vertex>
<x>325.000000000</x>
<y>196.999847412</y>
</vertex>
<vertex>
<x>479.922424316</x>
<y>421.000091553</y>
</vertex>
<vertex>
<x>170.077636719</x>
<y>421.000091553</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image2.jpg</source-name>
</source>
</surface>
</surfaces>
<surfaces>
<surface type="5">
<vertices>
<vertex>
<x>337.195068359</x>
<y>362.146270752</y>
</vertex>
<vertex>
<x>337.195068359</x>
<y>595.853759766</y>
</vertex>
<vertex>
<x>648.804992676</x>
<y>595.853759766</y>
</vertex>
<vertex>
<x>648.804992676</x>
<y>362.146270752</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image4.jpg</source-name>
</source>
<properties>
<perspectiveWarping>1</perspectiveWarping>
</properties>
</surface>
<surface type="1">
<vertices>
<vertex>
<x>522.590332031</x>
<y>188.924621582</y>
</vertex>
<vertex>
<x>835.409606934</x>
<y>188.924621582</y>
</vertex>
<vertex>
<x>835.409606934</x>
<y>415.075378418</y>
</vertex>
<vertex>
<x>522.590332031</x>
<y>415.075378418</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image1.jpg</source-name>
</source>
<properties>
<perspectiveWarping>1</perspectiveWarping>
</properties>
</surface>
<surface type="0">
<vertices>
<vertex>
<x>325.000000000</x>
<y>196.999847412</y>
</vertex>
<vertex>
<x>479.922424316</x>
<y>421.000091553</y>
</vertex>
<vertex>
<x>170.077636719</x>
<y>421.000091553</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image2.jpg</source-name>
</source>
</surface>
</surfaces>

104
example_fbo-sources/src/BrickSource/BrickSource.cpp

@ -1,52 +1,52 @@
#include "BrickSource.h"
void BrickSource::setup(){
// Give our source a decent name
name = "Brick Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
ofSetFrameRate(60);
// Genereate rects to be rendered into the FBO
int numX = 21;
int numY = 21; // change this to add more or less rects
int motar = 4;
int brickLength = 20;
int brickWidth = 20;
int counter = 0;
for(int k = 0; k < numY;k++){
for(int i = 0; i < numX; i++){
bricks.push_back(ofRectangle(i*(brickLength + motar),
k*(brickWidth + motar),
brickLength,
brickWidth));
brickColor.push_back(ofRandom(0, 220));
}
}
}
// Don't do any drawing here
void BrickSource::update(){
if (ofGetFrameNum()%30 == 0) {
for(int i = 0; i < bricks.size(); i++){
brickColor[i] = ofRandom(0, 220);
}
} // Move quads
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void BrickSource::draw(){
// Fill FBO with our quads
ofClear(0);
//ofBackground(0);
ofFill();
for(int i = 0; i < bricks.size(); i++){
//ofSetLineWidth(ofRandom(5));
ofSetColor(brickColor[i]);
ofDrawRectangle(bricks[i]);
}
}
#include "BrickSource.h"
void BrickSource::setup(){
// Give our source a decent name
name = "Brick Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
ofSetFrameRate(60);
// Genereate rects to be rendered into the FBO
int numX = 21;
int numY = 21; // change this to add more or less rects
int motar = 4;
int brickLength = 20;
int brickWidth = 20;
int counter = 0;
for(int k = 0; k < numY;k++){
for(int i = 0; i < numX; i++){
bricks.push_back(ofRectangle(i*(brickLength + motar),
k*(brickWidth + motar),
brickLength,
brickWidth));
brickColor.push_back(ofRandom(0, 220));
}
}
}
// Don't do any drawing here
void BrickSource::update(){
if (ofGetFrameNum()%30 == 0) {
for(int i = 0; i < bricks.size(); i++){
brickColor[i] = ofRandom(0, 220);
}
} // Move quads
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void BrickSource::draw(){
// Fill FBO with our quads
ofClear(0);
//ofBackground(0);
ofFill();
for(int i = 0; i < bricks.size(); i++){
//ofSetLineWidth(ofRandom(5));
ofSetColor(brickColor[i]);
ofDrawRectangle(bricks[i]);
}
}

30
example_fbo-sources/src/BrickSource/BrickSource.h

@ -1,15 +1,15 @@
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class BrickSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<ofRectangle> bricks;
std::vector<int> brickColor;
int counter;
};
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class BrickSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<ofRectangle> bricks;
std::vector<int> brickColor;
int counter;
};

86
example_fbo-sources/src/CircleSource/CircleSource.cpp

@ -1,43 +1,43 @@
#include "CircleSource.h"
bool col = true;
void CircleSource::setup(){
// Give our source a decent name
name = "Circle Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
ofSetCircleResolution(50);
// Genereate rects to be rendered into the FBO
int numCircles = 10; // change this to add more or less rects
for(int i = 0; i < numCircles; i++){
circlesRadius.push_back(ofRandom(fbo->getHeight()/2));
circlesSpeeds.push_back((1.0f + ofRandom(2)));
}
}
// Don't do any drawing here
void CircleSource::update(){
// Move rects
for(int i = 0; i < circlesRadius.size(); i++){
circlesRadius[i] += circlesSpeeds[i];
if(circlesRadius[i] > fbo->getHeight()/2){
circlesRadius[i] = fbo->getHeight()/2*(-1);
}
}
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void CircleSource::draw(){
// Fill FBO with our rects
ofClear(0);
ofSetColor(255);
ofSetLineWidth(ofRandom(3));
ofNoFill();
for(int i = 0; i < circlesRadius.size(); i++){
ofDrawCircle(fbo->getHeight()/2,fbo->getHeight()/2,circlesRadius[i]);
}
}
#include "CircleSource.h"
bool col = true;
void CircleSource::setup(){
// Give our source a decent name
name = "Circle Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
ofSetCircleResolution(50);
// Genereate rects to be rendered into the FBO
int numCircles = 10; // change this to add more or less rects
for(int i = 0; i < numCircles; i++){
circlesRadius.push_back(ofRandom(fbo->getHeight()/2));
circlesSpeeds.push_back((1.0f + ofRandom(2)));
}
}
// Don't do any drawing here
void CircleSource::update(){
// Move rects
for(int i = 0; i < circlesRadius.size(); i++){
circlesRadius[i] += circlesSpeeds[i];
if(circlesRadius[i] > fbo->getHeight()/2){
circlesRadius[i] = fbo->getHeight()/2*(-1);
}
}
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void CircleSource::draw(){
// Fill FBO with our rects
ofClear(0);
ofSetColor(255);
ofSetLineWidth(ofRandom(3));
ofNoFill();
for(int i = 0; i < circlesRadius.size(); i++){
ofDrawCircle(fbo->getHeight()/2,fbo->getHeight()/2,circlesRadius[i]);
}
}

28
example_fbo-sources/src/CircleSource/CircleSource.h

@ -1,14 +1,14 @@
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class CircleSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<float> circlesRadius;
std::vector<float> circlesSpeeds;
};
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class CircleSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<float> circlesRadius;
std::vector<float> circlesSpeeds;
};

124
example_fbo-sources/src/QuadSource/QuadSource.cpp

@ -1,62 +1,62 @@
#include "QuadSource.h"
void QuadSource::setup(){
// Give our source a decent name
name = "Quad Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
// Genereate rects to be rendered into the FBO
int numQuads = 20; // change this to add more or less rects
for(int i = 0; i < numQuads; i++){
float qsize = ofRandom(fbo->getWidth());
float fbosize = fbo->getWidth();
quads.push_back(ofRectangle(fbosize/2 - qsize/2,
fbosize/2 - qsize/2,
qsize,
qsize));
quadSpeeds.push_back((1.0f + ofRandom(5)));
}
}
// Don't do any drawing here
void QuadSource::update(){
// Move quads
for(int i = 0; i < quads.size(); i++){
quads[i].x -= quadSpeeds[i]/2;
quads[i].y -= quadSpeeds[i]/2;
quads[i].width += quadSpeeds[i];
quads[i].height += quadSpeeds[i];
if(quads[i].width > fbo->getHeight()){
quads[i].x = fbo->getWidth()/2;
quads[i].y = fbo->getWidth()/2;
quads[i].width = 0.0f;
quads[i].height = 0.0f;
}
}
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void QuadSource::draw(){
// Fill FBO with our quads
ofClear(0);
//ofBackground(0);
ofNoFill();
ofSetColor(255);
#if (OF_VERSION_MAJOR == 0 && OF_VERSION_MINOR >= 9) || OF_VERSION_MAJOR > 0
for(int i = 0; i < quads.size(); i++){
ofSetLineWidth(ofRandom(5));
ofDrawRectangle(quads[i]);
}
#else
for(int i = 0; i < quads.size(); i++){
ofRect(quads[i]);
}
#endif
}
#include "QuadSource.h"
void QuadSource::setup(){
// Give our source a decent name
name = "Quad Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
// Genereate rects to be rendered into the FBO
int numQuads = 20; // change this to add more or less rects
for(int i = 0; i < numQuads; i++){
float qsize = ofRandom(fbo->getWidth());
float fbosize = fbo->getWidth();
quads.push_back(ofRectangle(fbosize/2 - qsize/2,
fbosize/2 - qsize/2,
qsize,
qsize));
quadSpeeds.push_back((1.0f + ofRandom(5)));
}
}
// Don't do any drawing here
void QuadSource::update(){
// Move quads
for(int i = 0; i < quads.size(); i++){
quads[i].x -= quadSpeeds[i]/2;
quads[i].y -= quadSpeeds[i]/2;
quads[i].width += quadSpeeds[i];
quads[i].height += quadSpeeds[i];
if(quads[i].width > fbo->getHeight()){
quads[i].x = fbo->getWidth()/2;
quads[i].y = fbo->getWidth()/2;
quads[i].width = 0.0f;
quads[i].height = 0.0f;
}
}
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void QuadSource::draw(){
// Fill FBO with our quads
ofClear(0);
//ofBackground(0);
ofNoFill();
ofSetColor(255);
#if (OF_VERSION_MAJOR == 0 && OF_VERSION_MINOR >= 9) || OF_VERSION_MAJOR > 0
for(int i = 0; i < quads.size(); i++){
ofSetLineWidth(ofRandom(5));
ofDrawRectangle(quads[i]);
}
#else
for(int i = 0; i < quads.size(); i++){
ofRect(quads[i]);
}
#endif
}

28
example_fbo-sources/src/QuadSource/QuadSource.h

@ -1,14 +1,14 @@
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class QuadSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<ofRectangle> quads;
std::vector<float> quadSpeeds;
};
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class QuadSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<ofRectangle> quads;
std::vector<float> quadSpeeds;
};

96
example_fbo-sources/src/ScanLineSource/ScanlineSource.cpp

@ -1,48 +1,48 @@
#include "ScanlineSource.h"
void ScanlineSource::setup(){
// Give our source a decent name
name = "Scanline Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
// Genereate rects to be rendered into the FBO
int numRects = 20; // change this to add more or less rects
for(int i = 0; i < numRects; i++){
rects.push_back(ofRectangle(0,
ofRandom(fbo->getHeight()),
fbo->getWidth(),
ofRandom(20)));
rectSpeeds.push_back((1.0f + ofRandom(5)));
}
}
// Don't do any drawing here
void ScanlineSource::update(){
// Move rects
for(int i = 0; i < rects.size(); i++){
rects[i].y += rectSpeeds[i];
if(rects[i].y > fbo->getHeight()){
rects[i].y = -rects[i].getHeight();
}
}
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void ScanlineSource::draw(){
// Fill FBO with our rects
ofClear(0);
//ofBackground(0);
ofSetColor(255);
#if (OF_VERSION_MAJOR == 0 && OF_VERSION_MINOR >= 9) || OF_VERSION_MAJOR > 0
for(int i = 0; i < rects.size(); i++){
ofDrawRectangle(rects[i]);
}
#else
for(int i = 0; i < rects.size(); i++){
ofRect(rects[i]);
}
#endif
}
#include "ScanlineSource.h"
void ScanlineSource::setup(){
// Give our source a decent name
name = "Scanline Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
// Genereate rects to be rendered into the FBO
int numRects = 20; // change this to add more or less rects
for(int i = 0; i < numRects; i++){
rects.push_back(ofRectangle(0,
ofRandom(fbo->getHeight()),
fbo->getWidth(),
ofRandom(20)));
rectSpeeds.push_back((1.0f + ofRandom(5)));
}
}
// Don't do any drawing here
void ScanlineSource::update(){
// Move rects
for(int i = 0; i < rects.size(); i++){
rects[i].y += rectSpeeds[i];
if(rects[i].y > fbo->getHeight()){
rects[i].y = -rects[i].getHeight();
}
}
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void ScanlineSource::draw(){
// Fill FBO with our rects
ofClear(0);
//ofBackground(0);
ofSetColor(255);
#if (OF_VERSION_MAJOR == 0 && OF_VERSION_MINOR >= 9) || OF_VERSION_MAJOR > 0
for(int i = 0; i < rects.size(); i++){
ofDrawRectangle(rects[i]);
}
#else
for(int i = 0; i < rects.size(); i++){
ofRect(rects[i]);
}
#endif
}

28
example_fbo-sources/src/ScanLineSource/ScanlineSource.h

@ -1,14 +1,14 @@
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class ScanlineSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<ofRectangle> rects;
std::vector<float> rectSpeeds;
};
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class ScanlineSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<ofRectangle> rects;
std::vector<float> rectSpeeds;
};

402
example_fbo-sources/src/SlideShowSource/magSlide.cpp

@ -1,201 +1,201 @@
//
// magSlide.cpp
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#include "magSlide.h"
#include "magSlideTransition.h"
#pragma mark magSlide
int magSlide::idCount = 0;
magSlide::magSlide(std::string type)
{
this->type = type;
position = ofPoint(0, 0);
id = magSlide::idCount;
magSlide::idCount++;
}
void magSlide::update(uint64_t deltaTime)
{
transition->update(deltaTime);
runningTime += deltaTime;
switch (slideState){
// case SlideState::BuildIn:
// if (runningTime >= buildInDuration)
// {
// setState(Normal);
// activeTransition = nullptr;
// }
// break;
case SlideState::Normal:
if (runningTime >= buildOutStartTime){
setState(BuildOut);
}
break;
case SlideState::BuildOut:
if (runningTime >= endTime){
setState(Complete);
}
break;
default:
break;
}
}
void magSlide::setSize(float w, float h)
{
width = w;
height = h;
}
void magSlide::setResizeOption(magSlide::ResizeOptions resizeOption)
{
this->resizeOption = resizeOption;
}
magSlide::ResizeOptions magSlide::getResizeOption() const
{
return resizeOption;
}
void magSlide::setDuration(uint64_t duration)
{
this->duration = duration;
}
void magSlide::setState(SlideState state)
{
// Don't do anything if the new state is the same
// as the current one:
if (slideState == state) return;
slideState = state;
ofEventArgs args;
ofNotifyEvent(slideStateChangedEvent, args, this);
if (slideState == Complete)
{
ofNotifyEvent(slideCompleteEvent, args, this);
}
}
void magSlide::setTransitionDuration(uint64_t tDuration)
{
buildOutDuration = tDuration;
}
const std::string magSlide::getSlideStateName()
{
switch (slideState)
{
// case SlideState::BuildIn:
// return "BuildIn";
case SlideState::BuildOut:
return "BuildOut";
case Normal:
return "Normal";
case SlideState::Complete:
return "Complete";
case SlideState::Off:
return "Off";
}
return "unknown";
}
void magSlide::start(uint64_t startTime)
{
this->startTime = startTime;
runningTime = 0;
endTime = duration + (buildOutDuration*2); // *2 because we take into account transition in and out
buildOutStartTime = duration + buildOutDuration;
slideState = magSlide::SlideState::Normal;
position.set(0, 0);
opacity = 255;
isComplete = false;
}
void magSlide::draw()
{
ofSetColor(255, opacity);
if(transition->isActive())
{
transition->draw();
}
}
////////////////////////////////////////////////////////
#pragma mark MAG_IMAGE_SLIDE
////////////////////////////////////////////////////////
magImageSlide::magImageSlide() : magSlide("magImageSlide") {}
magImageSlide::~magImageSlide() {}
void magImageSlide::setup(ofImage &image)
{
// Make a copy of the image:
this->image = ofImage(image);
image.setAnchorPercent(0.5, 0.5);
width = image.getWidth();
height = image.getHeight();
}
void magImageSlide::draw()
{
magSlide::draw();
image.draw(position, width, height);
}
////////////////////////////////////////////////////////
#pragma mark MAG_VIDEO_SLIDE
////////////////////////////////////////////////////////
magVideoSlide::magVideoSlide() : magSlide("magVideoSlide")
{}
magVideoSlide::~magVideoSlide()
{
videoPlayer.stop();
}
bool magVideoSlide::setup(ofFile &file, bool useVideoDuration)
{
bool success = videoPlayer.load(file.getAbsolutePath());
if (success)
{
videoPlayer.setAnchorPercent(0.5, 0.5);
if (useVideoDuration)
{
useVideoForDuration();
}
}
return success;
}
void magVideoSlide::update()
{
videoPlayer.update();
}
void magVideoSlide::draw()
{
magSlide::draw();
videoPlayer.draw(position.x, position.y, width, height);
}
void magVideoSlide::useVideoForDuration()
{
duration = uint64_t((videoPlayer.getDuration()*1000)) - buildOutDuration;
}
//
// magSlide.cpp
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#include "magSlide.h"
#include "magSlideTransition.h"
#pragma mark magSlide
int magSlide::idCount = 0;
magSlide::magSlide(std::string type)
{
this->type = type;
position = ofPoint(0, 0);
id = magSlide::idCount;
magSlide::idCount++;
}
void magSlide::update(uint64_t deltaTime)
{
transition->update(deltaTime);
runningTime += deltaTime;
switch (slideState){
// case SlideState::BuildIn:
// if (runningTime >= buildInDuration)
// {
// setState(Normal);
// activeTransition = nullptr;
// }
// break;
case SlideState::Normal:
if (runningTime >= buildOutStartTime){
setState(BuildOut);
}
break;
case SlideState::BuildOut:
if (runningTime >= endTime){
setState(Complete);
}
break;
default:
break;
}
}
void magSlide::setSize(float w, float h)
{
width = w;
height = h;
}
void magSlide::setResizeOption(magSlide::ResizeOptions resizeOption)
{
this->resizeOption = resizeOption;
}
magSlide::ResizeOptions magSlide::getResizeOption() const
{
return resizeOption;
}
void magSlide::setDuration(uint64_t duration)
{
this->duration = duration;
}
void magSlide::setState(SlideState state)
{
// Don't do anything if the new state is the same
// as the current one:
if (slideState == state) return;
slideState = state;
ofEventArgs args;
ofNotifyEvent(slideStateChangedEvent, args, this);
if (slideState == Complete)
{
ofNotifyEvent(slideCompleteEvent, args, this);
}
}
void magSlide::setTransitionDuration(uint64_t tDuration)
{
buildOutDuration = tDuration;
}
const std::string magSlide::getSlideStateName()
{
switch (slideState)
{
// case SlideState::BuildIn:
// return "BuildIn";
case SlideState::BuildOut:
return "BuildOut";
case Normal:
return "Normal";
case SlideState::Complete:
return "Complete";
case SlideState::Off:
return "Off";
}
return "unknown";
}
void magSlide::start(uint64_t startTime)
{
this->startTime = startTime;
runningTime = 0;
endTime = duration + (buildOutDuration*2); // *2 because we take into account transition in and out
buildOutStartTime = duration + buildOutDuration;
slideState = magSlide::SlideState::Normal;
position.set(0, 0);
opacity = 255;
isComplete = false;
}
void magSlide::draw()
{
ofSetColor(255, opacity);
if(transition->isActive())
{
transition->draw();
}
}
////////////////////////////////////////////////////////
#pragma mark MAG_IMAGE_SLIDE
////////////////////////////////////////////////////////
magImageSlide::magImageSlide() : magSlide("magImageSlide") {}
magImageSlide::~magImageSlide() {}
void magImageSlide::setup(ofImage &image)
{
// Make a copy of the image:
this->image = ofImage(image);
image.setAnchorPercent(0.5, 0.5);
width = image.getWidth();
height = image.getHeight();
}
void magImageSlide::draw()
{
magSlide::draw();
image.draw(position, width, height);
}
////////////////////////////////////////////////////////
#pragma mark MAG_VIDEO_SLIDE
////////////////////////////////////////////////////////
magVideoSlide::magVideoSlide() : magSlide("magVideoSlide")
{}
magVideoSlide::~magVideoSlide()
{
videoPlayer.stop();
}
bool magVideoSlide::setup(ofFile &file, bool useVideoDuration)
{
bool success = videoPlayer.load(file.getAbsolutePath());
if (success)
{
videoPlayer.setAnchorPercent(0.5, 0.5);
if (useVideoDuration)
{
useVideoForDuration();
}
}
return success;
}
void magVideoSlide::update()
{
videoPlayer.update();
}
void magVideoSlide::draw()
{
magSlide::draw();
videoPlayer.draw(position.x, position.y, width, height);
}
void magVideoSlide::useVideoForDuration()
{
duration = uint64_t((videoPlayer.getDuration()*1000)) - buildOutDuration;
}

526
example_fbo-sources/src/SlideShowSource/magSlide.h

@ -1,263 +1,263 @@
//
// Created by Cristobal Mendoza on 11/9/17.
//
#ifndef MAGSLIDE_H
#define MAGSLIDE_H
#include "ofMain.h"
class magSlideTransition;
class magSlide
{
public:
magSlide(std::string type);
// ~magSlide();
virtual void update(uint64_t deltaTime);
virtual void draw();
/**
* Sets the slide up for playback. This method must be
* called before displaying the slide.
* @param startTime
*/
void start(uint64_t startTime);
enum ResizeOptions : short
{
/**
* No resizing applied, displays the slide in its native pixel dimensions.
* This is the default behavior.
*/
NoResize = 0,
/**
* Explicitly set a slide to display in its native dimension.
* None and NoResize result in the same output, but if you specify
* a default resizing option in your slideshow and you want a particular
* slide not to resize, you must specify this option. Otherwise the
* slide show option will apply.
*/
Native,
/**
* Sets width and height to match the source's.
* This will distort the slide if the aspect ratios
* don't match.
*/
Fit,
/**
* Resizes the largest dimension to the source's max,
* the other dimension is resized proportionally.
*/
FitProportionally,
/**
* Resizes the shortest dimensions to the source's max,
*/
FillProportionally,
};
enum SlideState : short
{
Off = 0,
// BuildIn,
Normal,
BuildOut,
Complete
};
const std::string &getType()
{ return type; }
float getWidth()
{ return width; }
float getHeight()
{ return height; }
float getOpacity() const
{
return opacity;
}
void setOpacity(float opacity)
{
magSlide::opacity = opacity;
}
/**
* Change the display size of a slide. This will implicitly
* set resizeOptions to ResizeOption.NoResize.
* This method does not resize the pixel source of the slide.
* @param w The new width
* @param h The new height
*/
virtual void setSize(float w, float h);
uint64_t getDuration()
{
return duration;
}
/**
* Sets the display time of the slide, excluding
* builds (in or out)
* @param duration in milliseconds.
*/
void setDuration(uint64_t duration);
/**
* Sets the duration of the buildIn and buildOut
* transitions. Transition times are added to the
* duration of the slide.
* @param tDuration in milliseconds.
*/
void setTransitionDuration(uint64_t tDuration);
ResizeOptions getResizeOption() const;
void setResizeOption(ResizeOptions resizeOption);
SlideState getSlideState() const
{
return slideState;
}
bool isSlideComplete()
{ return isComplete; }
int getId()
{ return id; }
const std::string getSlideStateName();
//////////////////////////////
/// Events
//////////////////////////////
ofEvent<ofEventArgs> slideCompleteEvent;
ofEvent<ofEventArgs> slideStateChangedEvent;
friend class magSlideShowSource;
protected:
int id;
std::string type;
float width;
float height;
ofPoint position;
public:
const ofPoint &getPosition() const
{
return position;
}
void setPosition(const ofPoint &position)
{
magSlide::position = position;
}
void setPosition(float x, float y)
{
position.set(x, y);
}
protected:
float opacity = 255;
ResizeOptions resizeOption = NoResize;
SlideState slideState = Off;
bool isComplete = false;
// std::shared_ptr<magSlideTransition> buildIn = nullptr;
// std::shared_ptr<magSlideTransition> buildOut = nullptr;
std::shared_ptr<magSlideTransition> transition = nullptr;
public:
const shared_ptr<magSlideTransition> &getTransition() const
{
return transition;
}
protected:
/**
* The duration of the slide in millis, not counting builds
*/
uint64_t duration;
/**
* The start time of the slide in milliseconds, in "local time".
* In practice, this means that the start time is always 0.
*/
uint64_t startTime;
/**
* The end time of the slide in milliseconds, in "local time".
* The endTime is startTime + buildInDuration + duration + buildOutDuration.
*/
uint64_t endTime;
/**
* The duration of the build in transition or effect, in milliseconds.
*/
// uint64_t buildInDuration;
/**
* The duration of the build out transition or effect, in milliseconds.
*/
uint64_t buildOutDuration;
/**
* The "local time" start of the build out transition. This time should also
* signal the enqueuing of the next slide, if applicable.
*/
uint64_t buildOutStartTime;
/**
* The amount of time the slide has been displayed, in milliseconds.
* This constitutes the "local time" of the slide.
*/
uint64_t runningTime;
void setState(SlideState state);
static int idCount;
};
class magImageSlide : public magSlide
{
public:
magImageSlide();
~ magImageSlide();
/**
* Sets up an image slide.
* @param image is copied into the member magImageSlide::image and is
* not modified in any way.
*/
void setup(ofImage &image);
void draw();
protected:
ofImage image;
};
class magVideoSlide : public magSlide
{
public:
magVideoSlide();
~magVideoSlide();
bool setup(ofFile &file, bool useVideoDuration = false);
void update();
void draw();
/**
* Sets the slide duration to the duration of the video.
* magSlide::duration will be changed by this call, so if you later
* change your mind you'll have to use magSlide::setDuration.
*/
void useVideoForDuration();
protected:
ofVideoPlayer videoPlayer;
};
#endif
//
// Created by Cristobal Mendoza on 11/9/17.
//
#ifndef MAGSLIDE_H
#define MAGSLIDE_H
#include "ofMain.h"
class magSlideTransition;
class magSlide
{
public:
magSlide(std::string type);
// ~magSlide();
virtual void update(uint64_t deltaTime);
virtual void draw();
/**
* Sets the slide up for playback. This method must be
* called before displaying the slide.
* @param startTime
*/
void start(uint64_t startTime);
enum ResizeOptions : short
{
/**
* No resizing applied, displays the slide in its native pixel dimensions.
* This is the default behavior.
*/
NoResize = 0,
/**
* Explicitly set a slide to display in its native dimension.
* None and NoResize result in the same output, but if you specify
* a default resizing option in your slideshow and you want a particular
* slide not to resize, you must specify this option. Otherwise the
* slide show option will apply.
*/
Native,
/**
* Sets width and height to match the source's.
* This will distort the slide if the aspect ratios
* don't match.
*/
Fit,
/**
* Resizes the largest dimension to the source's max,
* the other dimension is resized proportionally.
*/
FitProportionally,
/**
* Resizes the shortest dimensions to the source's max,
*/
FillProportionally,
};
enum SlideState : short
{
Off = 0,
// BuildIn,
Normal,
BuildOut,
Complete
};
const std::string &getType()
{ return type; }
float getWidth()
{ return width; }
float getHeight()
{ return height; }
float getOpacity() const
{
return opacity;
}
void setOpacity(float opacity)
{
magSlide::opacity = opacity;
}
/**
* Change the display size of a slide. This will implicitly
* set resizeOptions to ResizeOption.NoResize.
* This method does not resize the pixel source of the slide.
* @param w The new width
* @param h The new height
*/
virtual void setSize(float w, float h);
uint64_t getDuration()
{
return duration;
}
/**
* Sets the display time of the slide, excluding
* builds (in or out)
* @param duration in milliseconds.
*/
void setDuration(uint64_t duration);
/**
* Sets the duration of the buildIn and buildOut
* transitions. Transition times are added to the
* duration of the slide.
* @param tDuration in milliseconds.
*/
void setTransitionDuration(uint64_t tDuration);
ResizeOptions getResizeOption() const;
void setResizeOption(ResizeOptions resizeOption);
SlideState getSlideState() const
{
return slideState;
}
bool isSlideComplete()
{ return isComplete; }
int getId()
{ return id; }
const std::string getSlideStateName();
//////////////////////////////
/// Events
//////////////////////////////
ofEvent<ofEventArgs> slideCompleteEvent;
ofEvent<ofEventArgs> slideStateChangedEvent;
friend class magSlideShowSource;
protected:
int id;
std::string type;
float width;
float height;
ofPoint position;
public:
const ofPoint &getPosition() const
{
return position;
}
void setPosition(const ofPoint &position)
{
magSlide::position = position;
}
void setPosition(float x, float y)
{
position.set(x, y);
}
protected:
float opacity = 255;
ResizeOptions resizeOption = NoResize;
SlideState slideState = Off;
bool isComplete = false;
// std::shared_ptr<magSlideTransition> buildIn = nullptr;
// std::shared_ptr<magSlideTransition> buildOut = nullptr;
std::shared_ptr<magSlideTransition> transition = nullptr;
public:
const shared_ptr<magSlideTransition> &getTransition() const
{
return transition;
}
protected:
/**
* The duration of the slide in millis, not counting builds
*/
uint64_t duration;
/**
* The start time of the slide in milliseconds, in "local time".
* In practice, this means that the start time is always 0.
*/
uint64_t startTime;
/**
* The end time of the slide in milliseconds, in "local time".
* The endTime is startTime + buildInDuration + duration + buildOutDuration.
*/
uint64_t endTime;
/**
* The duration of the build in transition or effect, in milliseconds.
*/
// uint64_t buildInDuration;
/**
* The duration of the build out transition or effect, in milliseconds.
*/
uint64_t buildOutDuration;
/**
* The "local time" start of the build out transition. This time should also
* signal the enqueuing of the next slide, if applicable.
*/
uint64_t buildOutStartTime;
/**
* The amount of time the slide has been displayed, in milliseconds.
* This constitutes the "local time" of the slide.
*/
uint64_t runningTime;
void setState(SlideState state);
static int idCount;
};
class magImageSlide : public magSlide
{
public:
magImageSlide();
~ magImageSlide();
/**
* Sets up an image slide.
* @param image is copied into the member magImageSlide::image and is
* not modified in any way.
*/
void setup(ofImage &image);
void draw();
protected:
ofImage image;
};
class magVideoSlide : public magSlide
{
public:
magVideoSlide();
~magVideoSlide();
bool setup(ofFile &file, bool useVideoDuration = false);
void update();
void draw();
/**
* Sets the slide duration to the duration of the video.
* magSlide::duration will be changed by this call, so if you later
* change your mind you'll have to use magSlide::setDuration.
*/
void useVideoForDuration();
protected:
ofVideoPlayer videoPlayer;
};
#endif

1058
example_fbo-sources/src/SlideShowSource/magSlideShowSource.cpp

File diff suppressed because it is too large

334
example_fbo-sources/src/SlideShowSource/magSlideShowSource.h

@ -1,167 +1,167 @@
//
// magSlideShowSource.h
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#ifndef MAGSLIDESHOWSOURCE_H
#define MAGSLIDESHOWSOURCE_H
#include "FboSource.h"
#include "magSlide.h"
#include "DirectoryWatcher.h"
class magSlide;
class magSlideShowSource : public ofx::piMapper::FboSource {
public:
magSlideShowSource();
/**
* Default settings file name.
*/
static const std::string SettingsFileName;
struct Settings; // forward declaration
bool initialize(magSlideShowSource::Settings settings);
void setup() override;
void update() override;
void draw() override;
/**
* Removes all slides and then attempts to create a new slide show
* based on the contents of the ofDirectory specified. The files may
* be images or videos, which will be transformed into the appropriate slide type.
* Any other file type in the directory is ignored (including other directories).
* The slide order is alphabetical according to filename.
*
* @param dir The ofDirectory to use as a source for a slide show.
* @return true if at least one slide was created. false is returned
* otherwise. Check the console for the specific error.
*/
bool createFromFolderContents(std::string path);
bool loadFromXml(std::string path);
void addSlide(std::shared_ptr<magSlide> slide);
void play();
void pause();
void playNextSlide();
void playPrevSlide();
void playSlide(int slideIndex);
enum LoopType : int {
NONE = 0,
NORMAL,
PING_PONG
};
struct Settings {
/**
* The pixel width of the FBO.
*/
float width = 1280;
/**
* The pixel height of the FBO.
*/
float height = 720;
/**
* An optional default slide duration, in seconds.
* If a slide specifies a duration this value is ignored.
*/
float slideDuration = 5;
/**
* The default transition for the slide show.
*/
std::string transitionName = "Dissolve";
/**
* Default transition duration.
*/
float transitionDuration = 1;
/**
* If specified, all applicable files in the folder will
* be used as slides in the slide show. They will be ordered
* alphabetically according to their file names.
*
* If path is relative, the root will likely be the Data folder.
*/
std::string slidesFolderPath = "sources/images";
/**
* If specified,
*/
std::string slideshowFilePath;
/**
* Loop type for the slide show. See @code LoopType for options.
* The default is @code LoopType:None.
*/
LoopType loopType = LoopType::NONE;
/**
* The number of loops to perform, if the loopType is not NONE.
* If the value is 0 or less than 0, the slide show loops forever.
*/
int numLoops = 0;
/**
* The resizing option for the slide show. The default is FitProportionally.
* If a slide already has a resizing option applied, that option will be
* respected and this resizeOption will not be used.
*/
magSlide::ResizeOptions resizeOption = magSlide::ResizeOptions::FitProportionally;
};
////////////////////////////////////////////
//// Event Listeners
////////////////////////////////////////////
void slideStateChanged(const void *sender, ofEventArgs &args);
void slideComplete(const void *sender, ofEventArgs &args);
virtual ~magSlideShowSource();
/**
* Fires when the slide show is done, which happens when
* the loop count is equal to Settings::numLoops, or when
* the last slide is played when @code LoopType::NONE is specified.
* Sender is this slide show.
*/
ofEvent<ofEventArgs> slideshowCompleteEvent;
/**
* Fires when the slide show reaches the last slide
* and will perform a loop in the next call.
* Sender is this slide show.
*/
ofEvent<ofEventArgs> slideshowWillLoopEvent;
protected:
Settings settings;
std::vector<std::shared_ptr<magSlide>> slides;
private:
// std::shared_ptr<magSlide> currentSlide;
std::vector<std::shared_ptr<magSlide>> activeSlides;
void enqueueSlide(std::shared_ptr<magSlide> slide, uint64_t startTime);
uint64_t lastTime;
uint64_t deltaTime;
uint64_t runningTime;
bool isInitialized = false;
bool isPlaying = false;
int currentSlideIndex = 0;
int direction = 1;
int loopCount = 0;
ofx::piMapper::DirectoryWatcher * directoryWatcher;
void fileAddedListener(const void * sender);
void fileRemovedListener(const void * sender);
bool doInit;
bool doPlayNextSlide = false;
};
#endif
//
// magSlideShowSource.h
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#ifndef MAGSLIDESHOWSOURCE_H
#define MAGSLIDESHOWSOURCE_H
#include "FboSource.h"
#include "magSlide.h"
#include "DirectoryWatcher.h"
class magSlide;
class magSlideShowSource : public ofx::piMapper::FboSource {
public:
magSlideShowSource();
/**
* Default settings file name.
*/
static const std::string SettingsFileName;
struct Settings; // forward declaration
bool initialize(magSlideShowSource::Settings settings);
void setup() override;
void update() override;
void draw() override;
/**
* Removes all slides and then attempts to create a new slide show
* based on the contents of the ofDirectory specified. The files may
* be images or videos, which will be transformed into the appropriate slide type.
* Any other file type in the directory is ignored (including other directories).
* The slide order is alphabetical according to filename.
*
* @param dir The ofDirectory to use as a source for a slide show.
* @return true if at least one slide was created. false is returned
* otherwise. Check the console for the specific error.
*/
bool createFromFolderContents(std::string path);
bool loadFromXml(std::string path);
void addSlide(std::shared_ptr<magSlide> slide);
void play();
void pause();
void playNextSlide();
void playPrevSlide();
void playSlide(int slideIndex);
enum LoopType : int {
NONE = 0,
NORMAL,
PING_PONG
};
struct Settings {
/**
* The pixel width of the FBO.
*/
float width = 1280;
/**
* The pixel height of the FBO.
*/
float height = 720;
/**
* An optional default slide duration, in seconds.
* If a slide specifies a duration this value is ignored.
*/
float slideDuration = 5;
/**
* The default transition for the slide show.
*/
std::string transitionName = "Dissolve";
/**
* Default transition duration.
*/
float transitionDuration = 1;
/**
* If specified, all applicable files in the folder will
* be used as slides in the slide show. They will be ordered
* alphabetically according to their file names.
*
* If path is relative, the root will likely be the Data folder.
*/
std::string slidesFolderPath = "sources/images";
/**
* If specified,
*/
std::string slideshowFilePath;
/**
* Loop type for the slide show. See @code LoopType for options.
* The default is @code LoopType:None.
*/
LoopType loopType = LoopType::NONE;
/**
* The number of loops to perform, if the loopType is not NONE.
* If the value is 0 or less than 0, the slide show loops forever.
*/
int numLoops = 0;
/**
* The resizing option for the slide show. The default is FitProportionally.
* If a slide already has a resizing option applied, that option will be
* respected and this resizeOption will not be used.
*/
magSlide::ResizeOptions resizeOption = magSlide::ResizeOptions::FitProportionally;
};
////////////////////////////////////////////
//// Event Listeners
////////////////////////////////////////////
void slideStateChanged(const void *sender, ofEventArgs &args);
void slideComplete(const void *sender, ofEventArgs &args);
virtual ~magSlideShowSource();
/**
* Fires when the slide show is done, which happens when
* the loop count is equal to Settings::numLoops, or when
* the last slide is played when @code LoopType::NONE is specified.
* Sender is this slide show.
*/
ofEvent<ofEventArgs> slideshowCompleteEvent;
/**
* Fires when the slide show reaches the last slide
* and will perform a loop in the next call.
* Sender is this slide show.
*/
ofEvent<ofEventArgs> slideshowWillLoopEvent;
protected:
Settings settings;
std::vector<std::shared_ptr<magSlide>> slides;
private:
// std::shared_ptr<magSlide> currentSlide;
std::vector<std::shared_ptr<magSlide>> activeSlides;
void enqueueSlide(std::shared_ptr<magSlide> slide, uint64_t startTime);
uint64_t lastTime;
uint64_t deltaTime;
uint64_t runningTime;
bool isInitialized = false;
bool isPlaying = false;
int currentSlideIndex = 0;
int direction = 1;
int loopCount = 0;
ofx::piMapper::DirectoryWatcher * directoryWatcher;
void fileAddedListener(const void * sender);
void fileRemovedListener(const void * sender);
bool doInit;
bool doPlayNextSlide = false;
};
#endif

120
example_fbo-sources/src/SlideShowSource/magSlideTransition.cpp

@ -1,60 +1,60 @@
//
// magSlideTransition.cpp
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#include "magSlideTransition.h"
void magSlideTransition::start(std::shared_ptr<magSlide> nextSlide)
{
runningTime = 0;
active = true;
this->nextSlide = nextSlide;
}
void magSlideTransition::update(uint64_t timeDelta)
{
if (!active) return;
runningTime += timeDelta;
if (runningTime >= duration)
{
ofEventArgs arghh; // arghhhh...
nextSlide->setOpacity(255);
nextSlide->setPosition(0, 0);
end();
transitionCompleteEvent.notify(this, arghh);
active = false;
}
}
uint64_t magSlideTransition::getRunningTime()
{
return runningTime;
}
float magSlideTransition::getNormalizedTime()
{
return (double)runningTime / (double)duration;
}
void magDissolveTransition::draw()
{
slide->setOpacity(255 - (getNormalizedTime() * 255));
nextSlide->setOpacity(getNormalizedTime()*255);
}
void magDissolveTransition::start(std::shared_ptr<magSlide> nextSlide)
{
magSlideTransition::start(nextSlide);
nextSlide->setOpacity(0);
}
void magDissolveTransition::end()
{
nextSlide->setOpacity(255);
slide->setOpacity(0);
}
//
// magSlideTransition.cpp
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#include "magSlideTransition.h"
void magSlideTransition::start(std::shared_ptr<magSlide> nextSlide)
{
runningTime = 0;
active = true;
this->nextSlide = nextSlide;
}
void magSlideTransition::update(uint64_t timeDelta)
{
if (!active) return;
runningTime += timeDelta;
if (runningTime >= duration)
{
ofEventArgs arghh; // arghhhh...
nextSlide->setOpacity(255);
nextSlide->setPosition(0, 0);
end();
transitionCompleteEvent.notify(this, arghh);
active = false;
}
}
uint64_t magSlideTransition::getRunningTime()
{
return runningTime;
}
float magSlideTransition::getNormalizedTime()
{
return (double)runningTime / (double)duration;
}
void magDissolveTransition::draw()
{
slide->setOpacity(255 - (getNormalizedTime() * 255));
nextSlide->setOpacity(getNormalizedTime()*255);
}
void magDissolveTransition::start(std::shared_ptr<magSlide> nextSlide)
{
magSlideTransition::start(nextSlide);
nextSlide->setOpacity(0);
}
void magDissolveTransition::end()
{
nextSlide->setOpacity(255);
slide->setOpacity(0);
}

258
example_fbo-sources/src/SlideShowSource/magSlideTransition.h

@ -1,129 +1,129 @@
//
// magSlideTransition.h
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#ifndef MAGSLIDETRANSITION_H
#define MAGSLIDETRANSITION_H
#include "magSlide.h"
class magSlideTransitionFactory;
class magSlideTransition
{
public:
/**
* Subclassing notes: Make sure to provide a value for name in your
* magSlideTransition subclass.
*/
magSlideTransition() { name = "Void"; }
/**
* Begins the transition. This needs to be called in order for the
* transition to do anything.
* @param nextSlide The subsequent slide in the slide show needs to be
* passed here.
*
* You can override this call to set any initial conditions to the transition,
* but make sure to call this method in your override.
*/
virtual void start(std::shared_ptr<magSlide> nextSlide);
/**
* Called automatically when the transition is complete. Useful to set
* end states for the parameters of the slide and nextSlide. Default implementation
* does nothing.
*/
virtual void end(){}
/**
* NOTE: The transition settings system is not yet implemented.
* Called when the transition is created. Loads settings for magSlideTransition
* subclasses. The default implementation does nothing.
* @param settings ofParameterGroup with settings for your custom magSlideTransition
* subclass.
*/
virtual void loadSettings(ofParameterGroup &settings){}
/**
* Updates the transition.
* @param timeDelta The elapsed time (in ms.) between the last call to update() and
* this one (i.e. the frame time).
*
* If you need to override update, make sure to call this implementation
* in your subclass.
*/
virtual void update(uint64_t timeDelta);
/**
* Draws the transition. Default implementation does nothing.
*/
virtual void draw(){
ofLogNotice("magSlideTransition") << "transition draw - this should be overriden " << getNormalizedTime();
}
/**
* Current running time in milliseconds.
* @return uint64_t
*/
uint64_t getRunningTime();
/**
* Returns the current time in normalized form.
* 0 = start, 1 = end.
* @return Float between 0 and 1.
*/
float getNormalizedTime();
std::string const &getName() const
{
return name;
}
const shared_ptr<magSlide> &getNextSlide() const
{
return nextSlide;
}
bool isActive() const
{
return active;
}
/**
* Sender is a raw pointer to this magSlideTransition
*/
ofEvent<ofEventArgs> transitionCompleteEvent;
protected:
std::string name;
std::shared_ptr<magSlide> slide;
std::shared_ptr<magSlide> nextSlide;
uint64_t runningTime;
uint64_t duration;
uint64_t endTime;
bool active = false;
protected:
friend class magSlideTransitionFactory;
};
class magDissolveTransition : public magSlideTransition
{
public:
magDissolveTransition()
{
name = "Dissolve";
}
void start(std::shared_ptr<magSlide> nextSlide) override;
void draw() override;
void end() override;
};
#endif
//
// magSlideTransition.h
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#ifndef MAGSLIDETRANSITION_H
#define MAGSLIDETRANSITION_H
#include "magSlide.h"
class magSlideTransitionFactory;
class magSlideTransition
{
public:
/**
* Subclassing notes: Make sure to provide a value for name in your
* magSlideTransition subclass.
*/
magSlideTransition() { name = "Void"; }
/**
* Begins the transition. This needs to be called in order for the
* transition to do anything.
* @param nextSlide The subsequent slide in the slide show needs to be
* passed here.
*
* You can override this call to set any initial conditions to the transition,
* but make sure to call this method in your override.
*/
virtual void start(std::shared_ptr<magSlide> nextSlide);
/**
* Called automatically when the transition is complete. Useful to set
* end states for the parameters of the slide and nextSlide. Default implementation
* does nothing.
*/
virtual void end(){}
/**
* NOTE: The transition settings system is not yet implemented.
* Called when the transition is created. Loads settings for magSlideTransition
* subclasses. The default implementation does nothing.
* @param settings ofParameterGroup with settings for your custom magSlideTransition
* subclass.
*/
virtual void loadSettings(ofParameterGroup &settings){}
/**
* Updates the transition.
* @param timeDelta The elapsed time (in ms.) between the last call to update() and
* this one (i.e. the frame time).
*
* If you need to override update, make sure to call this implementation
* in your subclass.
*/
virtual void update(uint64_t timeDelta);
/**
* Draws the transition. Default implementation does nothing.
*/
virtual void draw(){
ofLogNotice("magSlideTransition") << "transition draw - this should be overriden " << getNormalizedTime();
}
/**
* Current running time in milliseconds.
* @return uint64_t
*/
uint64_t getRunningTime();
/**
* Returns the current time in normalized form.
* 0 = start, 1 = end.
* @return Float between 0 and 1.
*/
float getNormalizedTime();
std::string const &getName() const
{
return name;
}
const shared_ptr<magSlide> &getNextSlide() const
{
return nextSlide;
}
bool isActive() const
{
return active;
}
/**
* Sender is a raw pointer to this magSlideTransition
*/
ofEvent<ofEventArgs> transitionCompleteEvent;
protected:
std::string name;
std::shared_ptr<magSlide> slide;
std::shared_ptr<magSlide> nextSlide;
uint64_t runningTime;
uint64_t duration;
uint64_t endTime;
bool active = false;
protected:
friend class magSlideTransitionFactory;
};
class magDissolveTransition : public magSlideTransition
{
public:
magDissolveTransition()
{
name = "Dissolve";
}
void start(std::shared_ptr<magSlide> nextSlide) override;
void draw() override;
void end() override;
};
#endif

152
example_fbo-sources/src/SlideShowSource/magSlideTransitionFactory.cpp

@ -1,76 +1,76 @@
//
// Created by Cristobal Mendoza on 12/3/17.
//
#include "magSlideTransitionFactory.h"
/*
*
*
*
class Base {};
class DerivedA : public Base {};
class DerivedB : public Base {};
class DerivedC : public Base {};
Base* create(const std::string& type)
{
static std::map<std::string, std::function<Base*()>> type_creator_map =
{
{"DerivedA", [](){return new DerivedA();}},
{"DerivedB", [](){return new DerivedB();}},
{"DerivedC", [](){return new DerivedC();}}
};
auto it = type_creator_map.find(type);
if(it != type_creator_map.end())
{
return it->second();
}
return nullptr;
}
*/
magSlideTransitionFactory* magSlideTransitionFactory::_instance = 0;
magSlideTransitionFactory::magSlideTransitionFactory()
{
magSlideTransition voidTransition;
magDissolveTransition dissolve;
registerTransition<magSlideTransition>(voidTransition);
registerTransition<magDissolveTransition>(dissolve);
}
magSlideTransitionFactory* magSlideTransitionFactory::instance()
{
if (_instance == 0)
{
_instance = new magSlideTransitionFactory();
}
return _instance;
}
std::shared_ptr<magSlideTransition>
magSlideTransitionFactory::createTransition(std::string transitionName, std::shared_ptr<magSlide> slide,
ofParameterGroup &settings, uint64_t duration)
{
std::shared_ptr<magSlideTransition> transition;
if (transitionsMap.count(transitionName) > 0)
{
transition = transitionsMap[transitionName]();
}
else
{
transition = transitionsMap[transition->getName()]();
}
transition->slide = slide;
transition->duration = duration;
transition->loadSettings(settings);
return transition;
}
//
// Created by Cristobal Mendoza on 12/3/17.
//
#include "magSlideTransitionFactory.h"
/*
*
*
*
class Base {};
class DerivedA : public Base {};
class DerivedB : public Base {};
class DerivedC : public Base {};
Base* create(const std::string& type)
{
static std::map<std::string, std::function<Base*()>> type_creator_map =
{
{"DerivedA", [](){return new DerivedA();}},
{"DerivedB", [](){return new DerivedB();}},
{"DerivedC", [](){return new DerivedC();}}
};
auto it = type_creator_map.find(type);
if(it != type_creator_map.end())
{
return it->second();
}
return nullptr;
}
*/
magSlideTransitionFactory* magSlideTransitionFactory::_instance = 0;
magSlideTransitionFactory::magSlideTransitionFactory()
{
magSlideTransition voidTransition;
magDissolveTransition dissolve;
registerTransition<magSlideTransition>(voidTransition);
registerTransition<magDissolveTransition>(dissolve);
}
magSlideTransitionFactory* magSlideTransitionFactory::instance()
{
if (_instance == 0)
{
_instance = new magSlideTransitionFactory();
}
return _instance;
}
std::shared_ptr<magSlideTransition>
magSlideTransitionFactory::createTransition(std::string transitionName, std::shared_ptr<magSlide> slide,
ofParameterGroup &settings, uint64_t duration)
{
std::shared_ptr<magSlideTransition> transition;
if (transitionsMap.count(transitionName) > 0)
{
transition = transitionsMap[transitionName]();
}
else
{
transition = transitionsMap[transition->getName()]();
}
transition->slide = slide;
transition->duration = duration;
transition->loadSettings(settings);
return transition;
}

82
example_fbo-sources/src/SlideShowSource/magSlideTransitionFactory.h

@ -1,41 +1,41 @@
//
// Created by Cristobal Mendoza on 12/3/17.
//
#ifndef MAGSLIDETRANSITIONFACTORY_H
#define MAGSLIDETRANSITIONFACTORY_H
#include "magSlide.h"
#include "magSlideTransition.h"
/**
* Factory class to register and instantiate transitions.
*/
class magSlideTransitionFactory
{
public:
static magSlideTransitionFactory* instance();
std::shared_ptr<magSlideTransition> createTransition(std::string transitionName,
std::shared_ptr<magSlide> slide,
ofParameterGroup &group,
uint64_t duration);
template<typename T>
void registerTransition(T transition)
{
if (transitionsMap.count(transition.getName()) == 0)
{
transitionsMap[transition.getName()] = [](){
return std::make_shared<T>();
};
}
}
protected:
std::unordered_map<std::string, std::function<std::shared_ptr<magSlideTransition>()>> transitionsMap;
private:
static magSlideTransitionFactory* _instance;
magSlideTransitionFactory();
};
#endif //MAGSLIDETRANSITIONFACTORY_H
//
// Created by Cristobal Mendoza on 12/3/17.
//
#ifndef MAGSLIDETRANSITIONFACTORY_H
#define MAGSLIDETRANSITIONFACTORY_H
#include "magSlide.h"
#include "magSlideTransition.h"
/**
* Factory class to register and instantiate transitions.
*/
class magSlideTransitionFactory
{
public:
static magSlideTransitionFactory* instance();
std::shared_ptr<magSlideTransition> createTransition(std::string transitionName,
std::shared_ptr<magSlide> slide,
ofParameterGroup &group,
uint64_t duration);
template<typename T>
void registerTransition(T transition)
{
if (transitionsMap.count(transition.getName()) == 0)
{
transitionsMap[transition.getName()] = [](){
return std::make_shared<T>();
};
}
}
protected:
std::unordered_map<std::string, std::function<std::shared_ptr<magSlideTransition>()>> transitionsMap;
private:
static magSlideTransitionFactory* _instance;
magSlideTransitionFactory();
};
#endif //MAGSLIDETRANSITIONFACTORY_H

174
example_fbo-sources/src/SyphonSource/SyphonSource.cpp

@ -1,87 +1,87 @@
// #include "SyphonSource.h"
//
// void SyphonSource::setup(){
// // Give our source a decent name
// name = "Syphon Source";
//
// // Allocate our FBO source, decide how big it should be
// allocate(500, 500);
//
// //setup our directory
// dir.setup();
// //setup our client
// mClient.setup();
//
// //register for our directory's callbacks
// ofAddListener(dir.events.serverAnnounced, this, &SyphonSource::serverAnnounced);
// // not yet implemented
// //ofAddListener(dir.events.serverUpdated, this, &ofApp::serverUpdated);
// ofAddListener(dir.events.serverRetired, this, &SyphonSource::serverRetired);
//
// dirIdx = -1;
// }
//
// //these are our directory's callbacks
// void SyphonSource::serverAnnounced(ofxSyphonServerDirectoryEventArgs &arg)
// {
// for( auto& dir : arg.servers ){
// ofLogNotice("ofxSyphonServerDirectory Server Announced")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
// }
// dirIdx = 0;
// }
//
// void SyphonSource::serverUpdated(ofxSyphonServerDirectoryEventArgs &arg)
// {
// for( auto& dir : arg.servers ){
// ofLogNotice("ofxSyphonServerDirectory Server Updated")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
// }
// dirIdx = 0;
// }
//
// void SyphonSource::serverRetired(ofxSyphonServerDirectoryEventArgs &arg)
// {
// for( auto& dir : arg.servers ){
// ofLogNotice("ofxSyphonServerDirectory Server Retired")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
// }
// dirIdx = 0;
// }
//
//
// // Don't do any drawing here
// void SyphonSource::update(){
//
// }
//
// // No need to take care of fbo.begin() and fbo.end() here.
// // All within draw() is being rendered into fbo;
// void SyphonSource::draw(){
// if(dir.isValidIndex(dirIdx))
// mClient.draw(0, 0);
// }
//
// //--------------------------------------------------------------
// void SyphonSource::keyReleased(int key){
// //press any key to move through all available Syphon servers
// if (dir.size() > 0)
// {
// dirIdx++;
// if(dirIdx > dir.size() - 1)
// dirIdx = 0;
//
// mClient.set(dir.getDescription(dirIdx));
// string serverName = mClient.getServerName();
// string appName = mClient.getApplicationName();
//
// if(serverName == ""){
// serverName = "null";
// }
// if(appName == ""){
// appName = "null";
// }
// ofSetWindowTitle(serverName + ":" + appName);
// }
// else
// {
// ofSetWindowTitle("No Server");
// }
// }
// #include "SyphonSource.h"
//
// void SyphonSource::setup(){
// // Give our source a decent name
// name = "Syphon Source";
//
// // Allocate our FBO source, decide how big it should be
// allocate(500, 500);
//
// //setup our directory
// dir.setup();
// //setup our client
// mClient.setup();
//
// //register for our directory's callbacks
// ofAddListener(dir.events.serverAnnounced, this, &SyphonSource::serverAnnounced);
// // not yet implemented
// //ofAddListener(dir.events.serverUpdated, this, &ofApp::serverUpdated);
// ofAddListener(dir.events.serverRetired, this, &SyphonSource::serverRetired);
//
// dirIdx = -1;
// }
//
// //these are our directory's callbacks
// void SyphonSource::serverAnnounced(ofxSyphonServerDirectoryEventArgs &arg)
// {
// for( auto& dir : arg.servers ){
// ofLogNotice("ofxSyphonServerDirectory Server Announced")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
// }
// dirIdx = 0;
// }
//
// void SyphonSource::serverUpdated(ofxSyphonServerDirectoryEventArgs &arg)
// {
// for( auto& dir : arg.servers ){
// ofLogNotice("ofxSyphonServerDirectory Server Updated")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
// }
// dirIdx = 0;
// }
//
// void SyphonSource::serverRetired(ofxSyphonServerDirectoryEventArgs &arg)
// {
// for( auto& dir : arg.servers ){
// ofLogNotice("ofxSyphonServerDirectory Server Retired")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
// }
// dirIdx = 0;
// }
//
//
// // Don't do any drawing here
// void SyphonSource::update(){
//
// }
//
// // No need to take care of fbo.begin() and fbo.end() here.
// // All within draw() is being rendered into fbo;
// void SyphonSource::draw(){
// if(dir.isValidIndex(dirIdx))
// mClient.draw(0, 0);
// }
//
// //--------------------------------------------------------------
// void SyphonSource::keyReleased(int key){
// //press any key to move through all available Syphon servers
// if (dir.size() > 0)
// {
// dirIdx++;
// if(dirIdx > dir.size() - 1)
// dirIdx = 0;
//
// mClient.set(dir.getDescription(dirIdx));
// string serverName = mClient.getServerName();
// string appName = mClient.getApplicationName();
//
// if(serverName == ""){
// serverName = "null";
// }
// if(appName == ""){
// appName = "null";
// }
// ofSetWindowTitle(serverName + ":" + appName);
// }
// else
// {
// ofSetWindowTitle("No Server");
// }
// }

42
example_fbo-sources/src/SyphonSource/SyphonSource.h

@ -1,21 +1,21 @@
// #pragma once
//
// #include "ofMain.h"
// #include "FboSource.h"
// #include "ofxSyphon.h"
// class SyphonSource : public ofx::piMapper::FboSource {
// public:
// void setup();
// void update();
// void draw();
//
// void keyReleased(int key);
//
// void serverAnnounced(ofxSyphonServerDirectoryEventArgs &arg);
// void serverUpdated(ofxSyphonServerDirectoryEventArgs &args);
// void serverRetired(ofxSyphonServerDirectoryEventArgs &arg);
//
// ofxSyphonServerDirectory dir;
// ofxSyphonClient mClient;
// int dirIdx;
// };
// #pragma once
//
// #include "ofMain.h"
// #include "FboSource.h"
// #include "ofxSyphon.h"
// class SyphonSource : public ofx::piMapper::FboSource {
// public:
// void setup();
// void update();
// void draw();
//
// void keyReleased(int key);
//
// void serverAnnounced(ofxSyphonServerDirectoryEventArgs &arg);
// void serverUpdated(ofxSyphonServerDirectoryEventArgs &args);
// void serverRetired(ofxSyphonServerDirectoryEventArgs &arg);
//
// ofxSyphonServerDirectory dir;
// ofxSyphonClient mClient;
// int dirIdx;
// };

14
example_fbo-sources/src/main.cpp

@ -1,7 +1,7 @@
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofSetupOpenGL(1024, 768, OF_WINDOW);
ofRunApp(new ofApp());
}
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofSetupOpenGL(1024, 768, OF_WINDOW);
ofRunApp(new ofApp());
}

114
example_fbo-sources/src/ofApp.cpp

@ -1,57 +1,57 @@
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
// Enable or disable audio for video sources globally
// Set this to false to save resources on the Raspberry Pi
ofx::piMapper::VideoSource::enableAudio = true;
ofx::piMapper::VideoSource::useHDMIForAudio = false;
// Register our sources.
// This should be done before mapper.setup().
piMapper.registerFboSource(ScanLSource);
piMapper.registerFboSource(QuadiSource);
piMapper.registerFboSource(CircLSource);
piMapper.registerFboSource(BricksSource);
//piMapper.registerFboSource(SyphonClient);
//piMapper.registerFboSource(slideShowSource);
piMapper.setup();
// This will set the app fullscreen if compiled on Raspberry Pi.
#ifdef TARGET_RASPBERRY_PI
ofSetFullscreen(true);
#endif
// Start slideshow.
//slideShowSource.play();
}
void ofApp::update(){
piMapper.update();
}
void ofApp::draw(){
piMapper.draw();
}
void ofApp::keyPressed(int key){
piMapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
piMapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
piMapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
piMapper.mouseReleased(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
piMapper.mouseDragged(x, y, button);
}
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
// Enable or disable audio for video sources globally
// Set this to false to save resources on the Raspberry Pi
ofx::piMapper::VideoSource::enableAudio = true;
ofx::piMapper::VideoSource::useHDMIForAudio = false;
// Register our sources.
// This should be done before mapper.setup().
piMapper.registerFboSource(ScanLSource);
piMapper.registerFboSource(QuadiSource);
piMapper.registerFboSource(CircLSource);
piMapper.registerFboSource(BricksSource);
//piMapper.registerFboSource(SyphonClient);
//piMapper.registerFboSource(slideShowSource);
piMapper.setup();
// This will set the app fullscreen if compiled on Raspberry Pi.
#ifdef TARGET_RASPBERRY_PI
ofSetFullscreen(true);
#endif
// Start slideshow.
//slideShowSource.play();
}
void ofApp::update(){
piMapper.update();
}
void ofApp::draw(){
piMapper.draw();
}
void ofApp::keyPressed(int key){
piMapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
piMapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
piMapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
piMapper.mouseReleased(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
piMapper.mouseDragged(x, y, button);
}

74
example_fbo-sources/src/ofApp.h

@ -1,37 +1,37 @@
#pragma once
#include "ofMain.h"
#include "ofxPiMapper.h"
#include "VideoSource.h"
#include "ScanlineSource.h"
#include "CircleSource.h"
#include "QuadSource.h"
#include "BrickSource.h"
//#include "SyphonSource.h"
#include "magSlideShowSource.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper piMapper;
// By using a custom source that is derived from FboSource
// you will be able to see the source listed in sources editor
ScanlineSource ScanLSource;
QuadSource QuadiSource;
CircleSource CircLSource;
BrickSource BricksSource;
//SyphonSource SyphonClient;
magSlideShowSource slideShowSource;
};
#pragma once
#include "ofMain.h"
#include "ofxPiMapper.h"
#include "VideoSource.h"
#include "ScanlineSource.h"
#include "CircleSource.h"
#include "QuadSource.h"
#include "BrickSource.h"
//#include "SyphonSource.h"
#include "magSlideShowSource.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper piMapper;
// By using a custom source that is derived from FboSource
// you will be able to see the source listed in sources editor
ScanlineSource ScanLSource;
QuadSource QuadiSource;
CircleSource CircLSource;
BrickSource BricksSource;
//SyphonSource SyphonClient;
magSlideShowSource slideShowSource;
};

12
example_pocketvj/.gitignore

@ -1,6 +1,6 @@
obj
*.xcworkspace
*.xcuserdatad
*~
config.make
bin/*.app
obj
*.xcworkspace
*.xcuserdatad
*~
config.make
bin/*.app

26
example_pocketvj/Makefile

@ -1,13 +1,13 @@
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk

8
example_pocketvj/addons.make

@ -1,4 +1,4 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer

6
example_pocketvj/addons.make.norpi

@ -1,3 +1,3 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxGui
ofxPiMapper
ofxXmlSettings

72
example_pocketvj/bin/data/ofxpimapper.xml

@ -1,36 +1,36 @@
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>431.000000000</x>
<y>13.000000000</y>
</vertex>
<vertex>
<x>781.000000000</x>
<y>363.000000000</y>
</vertex>
<vertex>
<x>81.000000000</x>
<y>363.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image1.jpg</source-name>
</source>
</surface>
</surfaces>
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>431.000000000</x>
<y>13.000000000</y>
</vertex>
<vertex>
<x>781.000000000</x>
<y>363.000000000</y>
</vertex>
<vertex>
<x>81.000000000</x>
<y>363.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image1.jpg</source-name>
</source>
</surface>
</surfaces>

18
example_pocketvj/src/main.cpp

@ -1,9 +1,9 @@
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofGLFWWindowSettings settings;
settings.windowMode = OF_FULLSCREEN;
ofCreateWindow(settings);
ofRunApp(new ofApp);
}
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofGLFWWindowSettings settings;
settings.windowMode = OF_FULLSCREEN;
ofCreateWindow(settings);
ofRunApp(new ofApp);
}

248
example_pocketvj/src/ofApp.cpp

@ -1,124 +1,124 @@
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
mapper.setup();
// Set different info text for PocketVJ
std::string multilineInfoText =
"Custom ofxPiMapper shortcuts\n\n"
"Good day user.\n"
"Shortcuts have been customized.\n"
"Please make sure to provide your own documentation.";
mapper.setInfoText(multilineInfoText);
}
void ofApp::update(){
mapper.update();
}
void ofApp::draw(){
mapper.draw();
}
void ofApp::keyPressed(int key){
if(key == '1'){
mapper.setMode(ofx::piMapper::PRESENTATION_MODE);
}else if(key == '2'){
mapper.setMode(ofx::piMapper::TEXTURE_MODE);
}else if(key == '3'){
mapper.setMode(ofx::piMapper::MAPPING_MODE);
}else if(key == '4'){
mapper.setMode(ofx::piMapper::SOURCE_MODE);
}else if(key == 'c'){
mapper.toggleInfo();
}else if(key == 't'){
mapper.createSurface(ofx::piMapper::TRIANGLE_SURFACE);
}else if(key == 'q'){
mapper.createSurface(ofx::piMapper::QUAD_SURFACE);
}else if(key == 'r'){
mapper.createSurface(ofx::piMapper::CIRCLE_SURFACE);
}else if(key == 'x'){
mapper.createSurface(ofx::piMapper::HEXAGON_SURFACE);
}else if(key == 'g'){
mapper.createSurface(ofx::piMapper::GRID_WARP_SURFACE);
}else if(key == 'a'){
mapper.duplicateSurface();
}else if(key == 'o'){
mapper.scaleUp();
}else if(key == 'i'){
mapper.scaleDown();
}else if(key == 'p'){
mapper.togglePerspective();
}else if(key == 'v'){
mapper.addGridColumn();
}else if(key == 'b'){
mapper.removeGridColumn();
}else if(key == 'n'){
mapper.addGridRow();
}else if(key == 'm'){
mapper.removeGridRow();
}else if(key == '.'){
mapper.selectNextSurface();
}else if(key == ','){
mapper.selectPrevSurface();
}else if(key == 'k'){
mapper.selectNextVertex();
}else if(key == 'l'){
mapper.selectPrevVertex();
}else if(key == 'h'){
mapper.moveLayerUp();
}else if(key == 'j'){
mapper.moveLayerDown();
}else if(key == 's'){
mapper.saveProject();
}else if(key == 'y'){
mapper.toggleLayerPanel();
}else if(key == 'z'){
mapper.undo();
}else if(key == 'd'){
mapper.eraseSurface(mapper.getSelectedSurface());
}else if(key == 'w'){
mapper.togglePause();
}else if(key == '5'){
mapper.setNextSource();
}else if(key == '8'){
mapper.moveSelection(ofx::piMapper::Vec3(0.0f, -1.0f, 0.0f));
}else if(key == '9'){
mapper.moveSelection(ofx::piMapper::Vec3(0.0f, 1.0f, 0.0f));
}else if(key == '7'){
mapper.moveSelection(ofx::piMapper::Vec3(-1.0f, 0.0f, 0.0f));
}else if(key == '0'){
mapper.moveSelection(ofx::piMapper::Vec3(1.0f, 0.0f, 0.0f));
}else if(key == '/'){
bool shiftIsDown = mapper.toggleShift();
if(shiftIsDown){
ofLogNotice("ofApp") << "Shift key is down";
}else{
ofLogNotice("ofApp") << "Shift key is up";
}
}
/* For these one has to figure out her own ways.
* rbt Reboot (Raspberry Pi only)
* sdn Shutdown (Raspberry Pi only)
* new Clear composition (remove all surfaces)
* ext Exit application and return to command line
*/
}
void ofApp::keyReleased(int key){
mapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
mapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
mapper.mouseReleased(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
mapper.mouseDragged(x, y, button);
}
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
mapper.setup();
// Set different info text for PocketVJ
std::string multilineInfoText =
"Custom ofxPiMapper shortcuts\n\n"
"Good day user.\n"
"Shortcuts have been customized.\n"
"Please make sure to provide your own documentation.";
mapper.setInfoText(multilineInfoText);
}
void ofApp::update(){
mapper.update();
}
void ofApp::draw(){
mapper.draw();
}
void ofApp::keyPressed(int key){
if(key == '1'){
mapper.setMode(ofx::piMapper::PRESENTATION_MODE);
}else if(key == '2'){
mapper.setMode(ofx::piMapper::TEXTURE_MODE);
}else if(key == '3'){
mapper.setMode(ofx::piMapper::MAPPING_MODE);
}else if(key == '4'){
mapper.setMode(ofx::piMapper::SOURCE_MODE);
}else if(key == 'c'){
mapper.toggleInfo();
}else if(key == 't'){
mapper.createSurface(ofx::piMapper::TRIANGLE_SURFACE);
}else if(key == 'q'){
mapper.createSurface(ofx::piMapper::QUAD_SURFACE);
}else if(key == 'r'){
mapper.createSurface(ofx::piMapper::CIRCLE_SURFACE);
}else if(key == 'x'){
mapper.createSurface(ofx::piMapper::HEXAGON_SURFACE);
}else if(key == 'g'){
mapper.createSurface(ofx::piMapper::GRID_WARP_SURFACE);
}else if(key == 'a'){
mapper.duplicateSurface();
}else if(key == 'o'){
mapper.scaleUp();
}else if(key == 'i'){
mapper.scaleDown();
}else if(key == 'p'){
mapper.togglePerspective();
}else if(key == 'v'){
mapper.addGridColumn();
}else if(key == 'b'){
mapper.removeGridColumn();
}else if(key == 'n'){
mapper.addGridRow();
}else if(key == 'm'){
mapper.removeGridRow();
}else if(key == '.'){
mapper.selectNextSurface();
}else if(key == ','){
mapper.selectPrevSurface();
}else if(key == 'k'){
mapper.selectNextVertex();
}else if(key == 'l'){
mapper.selectPrevVertex();
}else if(key == 'h'){
mapper.moveLayerUp();
}else if(key == 'j'){
mapper.moveLayerDown();
}else if(key == 's'){
mapper.saveProject();
}else if(key == 'y'){
mapper.toggleLayerPanel();
}else if(key == 'z'){
mapper.undo();
}else if(key == 'd'){
mapper.eraseSurface(mapper.getSelectedSurface());
}else if(key == 'w'){
mapper.togglePause();
}else if(key == '5'){
mapper.setNextSource();
}else if(key == '8'){
mapper.moveSelection(ofx::piMapper::Vec3(0.0f, -1.0f, 0.0f));
}else if(key == '9'){
mapper.moveSelection(ofx::piMapper::Vec3(0.0f, 1.0f, 0.0f));
}else if(key == '7'){
mapper.moveSelection(ofx::piMapper::Vec3(-1.0f, 0.0f, 0.0f));
}else if(key == '0'){
mapper.moveSelection(ofx::piMapper::Vec3(1.0f, 0.0f, 0.0f));
}else if(key == '/'){
bool shiftIsDown = mapper.toggleShift();
if(shiftIsDown){
ofLogNotice("ofApp") << "Shift key is down";
}else{
ofLogNotice("ofApp") << "Shift key is up";
}
}
/* For these one has to figure out her own ways.
* rbt Reboot (Raspberry Pi only)
* sdn Shutdown (Raspberry Pi only)
* new Clear composition (remove all surfaces)
* ext Exit application and return to command line
*/
}
void ofApp::keyReleased(int key){
mapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
mapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
mapper.mouseReleased(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
mapper.mouseDragged(x, y, button);
}

42
example_pocketvj/src/ofApp.h

@ -1,21 +1,21 @@
#pragma once
#include "ofMain.h"
#include "ofxPiMapper.h"
#include "Vec3.h"
class ofApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper mapper;
};
#pragma once
#include "ofMain.h"
#include "ofxPiMapper.h"
#include "Vec3.h"
class ofApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper mapper;
};

26
example_remote-client/Makefile

@ -1,13 +1,13 @@
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk

44
example_remote-client/README.md

@ -1,22 +1,22 @@
# Remote Control Client for ofxPiMapper
This example demonstrates a TCP **client** for ofxPiMapper remote control. The other part of this is the [Remote Control Server](../example_remote-server). What it does is the following.
- Reads IP address and port defined in `bin/data/config.json`.
- Connects to server by using the IP address and port.
- Once connected, ofxPiMapper configuration is received.
- Instance of ofxPiMapper class is being set up.
- TCP messages are sent on every keyboard and mouse event.
In reality this example should be used as the remote control residing on your laptop computa. Set up your Raspberry Pi, connect it to the same network as your laptop and get to know the IP address of the Raspberry Pi. Update `bin/data/config.json` with the IP address of your Raspberry Pi and launch the app!
**Warning!** Sources are not being sent. Click once with the mouse after the application launches to see the borders of the surfaces. There should be a green rectangle visible in the top left corner of the screen if the connection is successfull.
## Dependencies
JSON is used as the data format between ofxPiMapper remote control server and client, therefore additionally [ofxJSON](https://github.com/jeffcrouse/ofxJSON) addon is used. Install it by using the following lines of bash code.
```
cd openFrameworks/addons
git clone --depth=1 https://github.com/jeffcrouse/ofxJSON
```
# Remote Control Client for ofxPiMapper
This example demonstrates a TCP **client** for ofxPiMapper remote control. The other part of this is the [Remote Control Server](../example_remote-server). What it does is the following.
- Reads IP address and port defined in `bin/data/config.json`.
- Connects to server by using the IP address and port.
- Once connected, ofxPiMapper configuration is received.
- Instance of ofxPiMapper class is being set up.
- TCP messages are sent on every keyboard and mouse event.
In reality this example should be used as the remote control residing on your laptop computa. Set up your Raspberry Pi, connect it to the same network as your laptop and get to know the IP address of the Raspberry Pi. Update `bin/data/config.json` with the IP address of your Raspberry Pi and launch the app!
**Warning!** Sources are not being sent. Click once with the mouse after the application launches to see the borders of the surfaces. There should be a green rectangle visible in the top left corner of the screen if the connection is successfull.
## Dependencies
JSON is used as the data format between ofxPiMapper remote control server and client, therefore additionally [ofxJSON](https://github.com/jeffcrouse/ofxJSON) addon is used. Install it by using the following lines of bash code.
```
cd openFrameworks/addons
git clone --depth=1 https://github.com/jeffcrouse/ofxJSON
```

12
example_remote-client/addons.make

@ -1,6 +1,6 @@
ofxGui
ofxJSON
ofxNetwork
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer
ofxGui
ofxJSON
ofxNetwork
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer

10
example_remote-client/addons.make.norpi

@ -1,5 +1,5 @@
ofxGui
ofxJSON
ofxNetwork
ofxPiMapper
ofxXmlSettings
ofxGui
ofxJSON
ofxNetwork
ofxPiMapper
ofxXmlSettings

8
example_remote-client/bin/data/config.json

@ -1,4 +1,4 @@
{
"ip":"127.0.0.1",
"port":9999
}
{
"ip":"127.0.0.1",
"port":9999
}

72
example_remote-client/bin/data/ofxpimapper.xml

@ -1,36 +1,36 @@
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>640.000000000</x>
<y>50.000000000</y>
</vertex>
<vertex>
<x>1230.000000000</x>
<y>750.000000000</y>
</vertex>
<vertex>
<x>50.000000000</x>
<y>750.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>video</source-type>
<source-name>gene-nsynthesis-loop-b.mp4</source-name>
</source>
</surface>
</surfaces>
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>640.000000000</x>
<y>50.000000000</y>
</vertex>
<vertex>
<x>1230.000000000</x>
<y>750.000000000</y>
</vertex>
<vertex>
<x>50.000000000</x>
<y>750.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>video</source-type>
<source-name>gene-nsynthesis-loop-b.mp4</source-name>
</source>
</surface>
</surfaces>

98
example_remote-client/src/TCPClient.cpp

@ -1,49 +1,49 @@
#include "TCPClient.h"
shared_ptr<TCPClient> TCPClient::_instance = 0;
shared_ptr<TCPClient> TCPClient::instance(){
if(_instance == 0){
_instance = shared_ptr<TCPClient>(new TCPClient);
}
return _instance;
}
TCPClient::TCPClient(){
}
void TCPClient::setup(string ip, int port){
_tcpClient.setup(ip, port);
}
void TCPClient::update(){
if(_tcpClient.isConnected()){
string rx = _tcpClient.receive();
if(rx.length() > 0){
ofxJSONElement json;
json["event"] = "received";
json["data"] = rx;
ofMessage m(json.getRawString());
ofSendMessage(m);
}
}
}
void TCPClient::draw(){
if(_tcpClient.isConnected()){
ofSetColor(0, 255, 0);
}else{
ofSetColor(255, 0, 0);
}
ofPushMatrix();
ofTranslate(10, 10);
ofDrawRectangle(0, 0, 10, 10);
ofPopMatrix();
}
void TCPClient::send(string message){
_tcpClient.send(message);
}
#include "TCPClient.h"
shared_ptr<TCPClient> TCPClient::_instance = 0;
shared_ptr<TCPClient> TCPClient::instance(){
if(_instance == 0){
_instance = shared_ptr<TCPClient>(new TCPClient);
}
return _instance;
}
TCPClient::TCPClient(){
}
void TCPClient::setup(string ip, int port){
_tcpClient.setup(ip, port);
}
void TCPClient::update(){
if(_tcpClient.isConnected()){
string rx = _tcpClient.receive();
if(rx.length() > 0){
ofxJSONElement json;
json["event"] = "received";
json["data"] = rx;
ofMessage m(json.getRawString());
ofSendMessage(m);
}
}
}
void TCPClient::draw(){
if(_tcpClient.isConnected()){
ofSetColor(0, 255, 0);
}else{
ofSetColor(255, 0, 0);
}
ofPushMatrix();
ofTranslate(10, 10);
ofDrawRectangle(0, 0, 10, 10);
ofPopMatrix();
}
void TCPClient::send(string message){
_tcpClient.send(message);
}

44
example_remote-client/src/TCPClient.h

@ -1,22 +1,22 @@
#pragma once
#include "ofMain.h"
#include "ofxNetwork.h"
#include "ofxJSONElement.h"
class TCPClient{
public:
static shared_ptr<TCPClient> instance();
void setup(string ip, int port);
void update();
void draw();
void send(string message);
private:
TCPClient();
static shared_ptr<TCPClient> _instance;
ofxTCPClient _tcpClient;
};
#pragma once
#include "ofMain.h"
#include "ofxNetwork.h"
#include "ofxJSONElement.h"
class TCPClient{
public:
static shared_ptr<TCPClient> instance();
void setup(string ip, int port);
void update();
void draw();
void send(string message);
private:
TCPClient();
static shared_ptr<TCPClient> _instance;
ofxTCPClient _tcpClient;
};

14
example_remote-client/src/main.cpp

@ -1,7 +1,7 @@
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofSetupOpenGL(1280, 800, OF_WINDOW);
ofRunApp(new ofApp());
}
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofSetupOpenGL(1280, 800, OF_WINDOW);
ofRunApp(new ofApp());
}

218
example_remote-client/src/ofApp.cpp

@ -1,109 +1,109 @@
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
isMapperSetup = false;
// Set IP address of your RasPi in data/config.json
ofxJSONElement json;
json.open("config.json");
TCPClient::instance()->setup(json["ip"].asString(), json["port"].asInt());
}
void ofApp::update(){
TCPClient::instance()->update();
if(isMapperSetup){
mapper.update();
}
}
void ofApp::draw(){
TCPClient::instance()->draw();
if(isMapperSetup){
mapper.draw();
}
}
// This is where we get configuration from the server part of this.
void ofApp::gotMessage(ofMessage m){
ofxJSONElement json;
bool ok = json.parse(m.message);
if(ok){
if(json["event"] == "received"){
std::string buffer = json["data"].asString();
ofxXmlSettings xml;
xml.loadFromBuffer(buffer);
xml.save("ofxpimapper.xml");
mapper.setup();
isMapperSetup = true;
}
}
}
void ofApp::keyPressed(int key){
if(isMapperSetup){
mapper.keyPressed(key);
ofxJSONElement json;
json["event"] = "keyPressed";
json["key"] = key;
TCPClient::instance()->send(json.getRawString());
}
}
void ofApp::keyReleased(int key){
if(isMapperSetup){
mapper.keyReleased(key);
ofxJSONElement json;
json["event"] = "keyReleased";
json["key"] = key;
TCPClient::instance()->send(json.getRawString());
}
}
void ofApp::mousePressed(int x, int y, int button){
if(isMapperSetup){
mapper.mousePressed(x, y, button);
ofxJSONElement json;
json["event"] = "mousePressed";
json["x"] = x;
json["y"] = y;
json["button"] = button;
TCPClient::instance()->send(json.getRawString());
}
}
void ofApp::mouseReleased(int x, int y, int button){
if(isMapperSetup){
mapper.mouseReleased(x, y, button);
ofxJSONElement json;
json["event"] = "mouseReleased";
json["x"] = x;
json["y"] = y;
json["button"] = button;
TCPClient::instance()->send(json.getRawString());
}
}
void ofApp::mouseDragged(int x, int y, int button){
if(isMapperSetup){
mapper.mouseDragged(x, y, button);
ofxJSONElement json;
json["event"] = "mouseDragged";
json["x"] = x;
json["y"] = y;
json["button"] = button;
TCPClient::instance()->send(json.getRawString());
}
}
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
isMapperSetup = false;
// Set IP address of your RasPi in data/config.json
ofxJSONElement json;
json.open("config.json");
TCPClient::instance()->setup(json["ip"].asString(), json["port"].asInt());
}
void ofApp::update(){
TCPClient::instance()->update();
if(isMapperSetup){
mapper.update();
}
}
void ofApp::draw(){
TCPClient::instance()->draw();
if(isMapperSetup){
mapper.draw();
}
}
// This is where we get configuration from the server part of this.
void ofApp::gotMessage(ofMessage m){
ofxJSONElement json;
bool ok = json.parse(m.message);
if(ok){
if(json["event"] == "received"){
std::string buffer = json["data"].asString();
ofxXmlSettings xml;
xml.loadFromBuffer(buffer);
xml.save("ofxpimapper.xml");
mapper.setup();
isMapperSetup = true;
}
}
}
void ofApp::keyPressed(int key){
if(isMapperSetup){
mapper.keyPressed(key);
ofxJSONElement json;
json["event"] = "keyPressed";
json["key"] = key;
TCPClient::instance()->send(json.getRawString());
}
}
void ofApp::keyReleased(int key){
if(isMapperSetup){
mapper.keyReleased(key);
ofxJSONElement json;
json["event"] = "keyReleased";
json["key"] = key;
TCPClient::instance()->send(json.getRawString());
}
}
void ofApp::mousePressed(int x, int y, int button){
if(isMapperSetup){
mapper.mousePressed(x, y, button);
ofxJSONElement json;
json["event"] = "mousePressed";
json["x"] = x;
json["y"] = y;
json["button"] = button;
TCPClient::instance()->send(json.getRawString());
}
}
void ofApp::mouseReleased(int x, int y, int button){
if(isMapperSetup){
mapper.mouseReleased(x, y, button);
ofxJSONElement json;
json["event"] = "mouseReleased";
json["x"] = x;
json["y"] = y;
json["button"] = button;
TCPClient::instance()->send(json.getRawString());
}
}
void ofApp::mouseDragged(int x, int y, int button){
if(isMapperSetup){
mapper.mouseDragged(x, y, button);
ofxJSONElement json;
json["event"] = "mouseDragged";
json["x"] = x;
json["y"] = y;
json["button"] = button;
TCPClient::instance()->send(json.getRawString());
}
}

50
example_remote-client/src/ofApp.h

@ -1,25 +1,25 @@
#pragma once
#include "ofMain.h"
#include "TCPClient.h"
#include "ofxPiMapper.h"
#include "ofxJSONElement.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void gotMessage(ofMessage m);
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper mapper;
bool isMapperSetup;
};
#pragma once
#include "ofMain.h"
#include "TCPClient.h"
#include "ofxPiMapper.h"
#include "ofxJSONElement.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void gotMessage(ofMessage m);
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper mapper;
bool isMapperSetup;
};

26
example_remote-server/Makefile

@ -1,13 +1,13 @@
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk

50
example_remote-server/README.md

@ -1,25 +1,25 @@
# Remote Control Server for ofxPiMapper
This example demonstrates a TCP server for ofxPiMapper remote control. The other part of this is the [Remote Control Client](../example_remote-client). What it does is the following.
- It creates a `TCPServer` singleton.
- Waits for a client to connect via TCP.
- Sends ofxPiMapper configuration once client is connected.
- Accepts keyboard and mouse events from client after.
- Forwards events to ofxPiMapper instance.
In a real-world scenario, the server should reside on the Raspberry Pi side of your installation. The Raspberry Pi should be connected to wired or wireless network. An IP address should be set.
The client should know the following.
- The **IP address** of the Raspberry Pi with the server.
- The port, which is **9999** in this case.
## Dependencies
JSON is used as the data format between ofxPiMapper remote control server and client, therefore additionally [ofxJSON](https://github.com/jeffcrouse/ofxJSON) addon is used. Install it by using the following lines of bash code.
```
cd openFrameworks/addons
git clone --depth=1 https://github.com/jeffcrouse/ofxJSON
```
# Remote Control Server for ofxPiMapper
This example demonstrates a TCP server for ofxPiMapper remote control. The other part of this is the [Remote Control Client](../example_remote-client). What it does is the following.
- It creates a `TCPServer` singleton.
- Waits for a client to connect via TCP.
- Sends ofxPiMapper configuration once client is connected.
- Accepts keyboard and mouse events from client after.
- Forwards events to ofxPiMapper instance.
In a real-world scenario, the server should reside on the Raspberry Pi side of your installation. The Raspberry Pi should be connected to wired or wireless network. An IP address should be set.
The client should know the following.
- The **IP address** of the Raspberry Pi with the server.
- The port, which is **9999** in this case.
## Dependencies
JSON is used as the data format between ofxPiMapper remote control server and client, therefore additionally [ofxJSON](https://github.com/jeffcrouse/ofxJSON) addon is used. Install it by using the following lines of bash code.
```
cd openFrameworks/addons
git clone --depth=1 https://github.com/jeffcrouse/ofxJSON
```

12
example_remote-server/addons.make

@ -1,6 +1,6 @@
ofxGui
ofxJSON
ofxNetwork
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer
ofxGui
ofxJSON
ofxNetwork
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer

10
example_remote-server/addons.make.norpi

@ -1,5 +1,5 @@
ofxGui
ofxJSON
ofxNetwork
ofxPiMapper
ofxXmlSettings
ofxGui
ofxJSON
ofxNetwork
ofxPiMapper
ofxXmlSettings

72
example_remote-server/bin/data/ofxpimapper.xml

@ -1,36 +1,36 @@
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>640.000000000</x>
<y>50.000000000</y>
</vertex>
<vertex>
<x>1230.000000000</x>
<y>750.000000000</y>
</vertex>
<vertex>
<x>50.000000000</x>
<y>750.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>gene-nsynthesis.jpg</source-name>
</source>
</surface>
</surfaces>
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>640.000000000</x>
<y>50.000000000</y>
</vertex>
<vertex>
<x>1230.000000000</x>
<y>750.000000000</y>
</vertex>
<vertex>
<x>50.000000000</x>
<y>750.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.500000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>gene-nsynthesis.jpg</source-name>
</source>
</surface>
</surfaces>

190
example_remote-server/src/TCPServer.cpp

@ -1,95 +1,95 @@
#include "TCPServer.h"
shared_ptr<TCPServer> TCPServer::_instance = 0;
shared_ptr<TCPServer> TCPServer::instance(){
if(_instance == 0){
_instance = shared_ptr<TCPServer>(new TCPServer);
}
return _instance;
}
TCPServer::TCPServer(){
std::cout << "TCPServer initialized" << std::endl;
}
void TCPServer::setup(int port){
_tcpServer.setup(port);
}
void TCPServer::update(){
int numClients = _tcpServer.getLastID();
for(auto i = 0; i < numClients; ++i){
if(_tcpServer.isClientConnected(i)){
// Notify application when new client connects
if(!_tcpConnections[i]){
ofxJSONElement json;
json["ip"] = _tcpServer.getClientIP(i);
json["port"] = _tcpServer.getClientPort(i);
json["id"] = i;
json["event"] = "connected";
ofMessage message(json.getRawString());
ofSendMessage(message);
_tcpConnections[i] = true;
}
// Receive messages
string rx = _tcpServer.receive(i);
if(rx.length() > 0){
ofxJSONElement json;
bool ok = json.parse(rx);
if(!ok){
json["ip"] = _tcpServer.getClientIP(i);
json["port"] = _tcpServer.getClientPort(i);
json["id"] = i;
json["event"] = "received";
json["data"] = rx;
}
ofMessage message(json.getRawString());
ofSendMessage(message);
}
}else{
// Notify application when client disconnects
if(_tcpConnections[i]){
ofxJSONElement json;
json["ip"] = _tcpServer.getClientIP(i);
json["port"] = _tcpServer.getClientPort(i);
json["id"] = i;
json["event"] = "disconnected";
ofMessage message(json.getRawString());
ofSendMessage(message);
_tcpConnections[i] = false;
}
}
}
}
void TCPServer::draw(){
int numClients = _tcpServer.getLastID();
int clientsConnected = 0;
for(auto i = 0; i < numClients; ++i){
if(_tcpServer.isClientConnected(i)){
ofPushMatrix();
ofTranslate(10, 10);
ofPushStyle();
ofSetColor(0, 255, 0);
ofDrawRectangle(clientsConnected * 20, 0, 10, 10);
ofPopStyle();
ofPopMatrix();
clientsConnected++;
}
}
}
void TCPServer::send(int clientID, std::string message){
_tcpServer.send(clientID, message);
}
#include "TCPServer.h"
shared_ptr<TCPServer> TCPServer::_instance = 0;
shared_ptr<TCPServer> TCPServer::instance(){
if(_instance == 0){
_instance = shared_ptr<TCPServer>(new TCPServer);
}
return _instance;
}
TCPServer::TCPServer(){
std::cout << "TCPServer initialized" << std::endl;
}
void TCPServer::setup(int port){
_tcpServer.setup(port);
}
void TCPServer::update(){
int numClients = _tcpServer.getLastID();
for(auto i = 0; i < numClients; ++i){
if(_tcpServer.isClientConnected(i)){
// Notify application when new client connects
if(!_tcpConnections[i]){
ofxJSONElement json;
json["ip"] = _tcpServer.getClientIP(i);
json["port"] = _tcpServer.getClientPort(i);
json["id"] = i;
json["event"] = "connected";
ofMessage message(json.getRawString());
ofSendMessage(message);
_tcpConnections[i] = true;
}
// Receive messages
string rx = _tcpServer.receive(i);
if(rx.length() > 0){
ofxJSONElement json;
bool ok = json.parse(rx);
if(!ok){
json["ip"] = _tcpServer.getClientIP(i);
json["port"] = _tcpServer.getClientPort(i);
json["id"] = i;
json["event"] = "received";
json["data"] = rx;
}
ofMessage message(json.getRawString());
ofSendMessage(message);
}
}else{
// Notify application when client disconnects
if(_tcpConnections[i]){
ofxJSONElement json;
json["ip"] = _tcpServer.getClientIP(i);
json["port"] = _tcpServer.getClientPort(i);
json["id"] = i;
json["event"] = "disconnected";
ofMessage message(json.getRawString());
ofSendMessage(message);
_tcpConnections[i] = false;
}
}
}
}
void TCPServer::draw(){
int numClients = _tcpServer.getLastID();
int clientsConnected = 0;
for(auto i = 0; i < numClients; ++i){
if(_tcpServer.isClientConnected(i)){
ofPushMatrix();
ofTranslate(10, 10);
ofPushStyle();
ofSetColor(0, 255, 0);
ofDrawRectangle(clientsConnected * 20, 0, 10, 10);
ofPopStyle();
ofPopMatrix();
clientsConnected++;
}
}
}
void TCPServer::send(int clientID, std::string message){
_tcpServer.send(clientID, message);
}

46
example_remote-server/src/TCPServer.h

@ -1,23 +1,23 @@
#pragma once
#include "ofMain.h"
#include "ofxNetwork.h"
#include "ofxJSONElement.h"
class TCPServer {
public:
static shared_ptr<TCPServer> instance();
void setup(int port);
void update();
void draw();
void send(int clientID, std::string message);
private:
TCPServer();
static shared_ptr<TCPServer> _instance;
ofxTCPServer _tcpServer;
std::map<int, bool> _tcpConnections;
};
#pragma once
#include "ofMain.h"
#include "ofxNetwork.h"
#include "ofxJSONElement.h"
class TCPServer {
public:
static shared_ptr<TCPServer> instance();
void setup(int port);
void update();
void draw();
void send(int clientID, std::string message);
private:
TCPServer();
static shared_ptr<TCPServer> _instance;
ofxTCPServer _tcpServer;
std::map<int, bool> _tcpConnections;
};

14
example_remote-server/src/main.cpp

@ -1,7 +1,7 @@
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofSetupOpenGL(1280, 800, OF_WINDOW);
ofRunApp(new ofApp());
}
#include "ofMain.h"
#include "ofApp.h"
int main(){
ofSetupOpenGL(1280, 800, OF_WINDOW);
ofRunApp(new ofApp());
}

168
example_remote-server/src/ofApp.cpp

@ -1,84 +1,84 @@
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
mapper.setup();
TCPServer::instance()->setup(9999);
#ifdef TARGET_RASPBERRY_PI
ofSetFullscreen(true);
#endif
}
void ofApp::update(){
mapper.update();
TCPServer::instance()->update();
}
void ofApp::draw(){
mapper.draw();
TCPServer::instance()->draw();
}
// Here is where we process messages received from TCPServer instance
void ofApp::gotMessage(ofMessage m){
std::cout << m.message << std::endl;
ofxJSONElement json;
bool ok = json.parse(m.message);
if(ok){
if(json["event"].asString() == "connected"){
// Save Mapper composition and get config as string
std::cout << "Sending mapper config" << std::endl;
mapper.saveProject();
ofFile file;
file.open(ofToDataPath("ofxpimapper.xml"), ofFile::ReadOnly, false);
ofBuffer buff = file.readToBuffer();
string text = buff.getText();
TCPServer::instance()->send(json["id"].asInt(), text);
}
if(json["event"].asString() == "keyPressed"){
mapper.keyPressed(json["key"].asInt());
}
if(json["event"].asString() == "keyReleased"){
mapper.keyReleased(json["key"].asInt());
}
if(json["event"].asString() == "mousePressed"){
mapper.mousePressed(json["x"].asInt(), json["y"].asInt(), json["button"].asInt());
}
if(json["event"].asString() == "mouseReleased"){
mapper.mouseReleased(json["x"].asInt(), json["y"].asInt(), json["button"].asInt());
}
if(json["event"].asString() == "mouseDragged"){
mapper.mouseDragged(json["x"].asInt(), json["y"].asInt(), json["button"].asInt());
}
}
}
void ofApp::keyPressed(int key){
mapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
mapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
mapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
mapper.mouseReleased(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
mapper.mouseDragged(x, y, button);
}
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
mapper.setup();
TCPServer::instance()->setup(9999);
#ifdef TARGET_RASPBERRY_PI
ofSetFullscreen(true);
#endif
}
void ofApp::update(){
mapper.update();
TCPServer::instance()->update();
}
void ofApp::draw(){
mapper.draw();
TCPServer::instance()->draw();
}
// Here is where we process messages received from TCPServer instance
void ofApp::gotMessage(ofMessage m){
std::cout << m.message << std::endl;
ofxJSONElement json;
bool ok = json.parse(m.message);
if(ok){
if(json["event"].asString() == "connected"){
// Save Mapper composition and get config as string
std::cout << "Sending mapper config" << std::endl;
mapper.saveProject();
ofFile file;
file.open(ofToDataPath("ofxpimapper.xml"), ofFile::ReadOnly, false);
ofBuffer buff = file.readToBuffer();
string text = buff.getText();
TCPServer::instance()->send(json["id"].asInt(), text);
}
if(json["event"].asString() == "keyPressed"){
mapper.keyPressed(json["key"].asInt());
}
if(json["event"].asString() == "keyReleased"){
mapper.keyReleased(json["key"].asInt());
}
if(json["event"].asString() == "mousePressed"){
mapper.mousePressed(json["x"].asInt(), json["y"].asInt(), json["button"].asInt());
}
if(json["event"].asString() == "mouseReleased"){
mapper.mouseReleased(json["x"].asInt(), json["y"].asInt(), json["button"].asInt());
}
if(json["event"].asString() == "mouseDragged"){
mapper.mouseDragged(json["x"].asInt(), json["y"].asInt(), json["button"].asInt());
}
}
}
void ofApp::keyPressed(int key){
mapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
mapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
mapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
mapper.mouseReleased(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
mapper.mouseDragged(x, y, button);
}

46
example_remote-server/src/ofApp.h

@ -1,23 +1,23 @@
#pragma once
#include "ofMain.h"
#include "TCPServer.h"
#include "ofxPiMapper.h"
#include "ofxJSONElement.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void gotMessage(ofMessage m);
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper mapper;
};
#pragma once
#include "ofMain.h"
#include "TCPServer.h"
#include "ofxPiMapper.h"
#include "ofxJSONElement.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void gotMessage(ofMessage m);
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper mapper;
};

10
example_simpler/.gitignore

@ -1,5 +1,5 @@
obj
*.xcworkspace
*.xcuserdatad
*~
config.make
obj
*.xcworkspace
*.xcuserdatad
*~
config.make

26
example_simpler/Makefile

@ -1,13 +1,13 @@
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=$(realpath ../../..)
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk

8
example_simpler/addons.make

@ -1,4 +1,4 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer
ofxGui
ofxPiMapper
ofxXmlSettings
ofxOMXPlayer

6
example_simpler/addons.make.norpi

@ -1,3 +1,3 @@
ofxGui
ofxPiMapper
ofxXmlSettings
ofxGui
ofxPiMapper
ofxXmlSettings

162
example_simpler/bin/data/ofxpimapper.xml

@ -1,81 +1,81 @@
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>193.000000000</x>
<y>58.187255859</y>
</vertex>
<vertex>
<x>466.000000000</x>
<y>413.000000000</y>
</vertex>
<vertex>
<x>39.374511719</x>
<y>211.812774658</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>-0.006000000</x>
<y>-0.014000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image4.jpg</source-name>
</source>
</surface>
<surface type="1">
<vertices>
<vertex>
<x>758.067382812</x>
<y>360.033691406</y>
</vertex>
<vertex>
<x>1125.932617188</x>
<y>360.033691406</y>
</vertex>
<vertex>
<x>1129.000000000</x>
<y>719.000000000</y>
</vertex>
<vertex>
<x>759.000000000</x>
<y>721.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>fbo</source-type>
<source-name>Custom FBO Source</source-name>
</source>
<properties>
<perspectiveWarping>1</perspectiveWarping>
</properties>
</surface>
</surfaces>
<surfaces>
<surface type="0">
<vertices>
<vertex>
<x>193.000000000</x>
<y>58.187255859</y>
</vertex>
<vertex>
<x>466.000000000</x>
<y>413.000000000</y>
</vertex>
<vertex>
<x>39.374511719</x>
<y>211.812774658</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>-0.006000000</x>
<y>-0.014000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>image</source-type>
<source-name>image4.jpg</source-name>
</source>
</surface>
<surface type="1">
<vertices>
<vertex>
<x>758.067382812</x>
<y>360.033691406</y>
</vertex>
<vertex>
<x>1125.932617188</x>
<y>360.033691406</y>
</vertex>
<vertex>
<x>1129.000000000</x>
<y>719.000000000</y>
</vertex>
<vertex>
<x>759.000000000</x>
<y>721.000000000</y>
</vertex>
</vertices>
<texCoords>
<texCoord>
<x>0.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>0.000000000</y>
</texCoord>
<texCoord>
<x>1.000000000</x>
<y>1.000000000</y>
</texCoord>
<texCoord>
<x>0.000000000</x>
<y>1.000000000</y>
</texCoord>
</texCoords>
<source>
<source-type>fbo</source-type>
<source-name>Custom FBO Source</source-name>
</source>
<properties>
<perspectiveWarping>1</perspectiveWarping>
</properties>
</surface>
</surfaces>

82
example_simpler/src/CustomSource.cpp

@ -1,41 +1,41 @@
#include "CustomSource.h"
void CustomSource::setup(){
// Give our source a decent name
name = "Custom FBO Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
// Genereate rects to be rendered into the FBO
int numRects = 20; // change this to add more or less rects
for(int i = 0; i < numRects; i++){
rects.push_back(ofRectangle(0,
ofRandom(fbo->getHeight()),
fbo->getWidth(),
ofRandom(20)));
rectSpeeds.push_back((1.0f + ofRandom(5)));
}
}
// Don't do any drawing here
void CustomSource::update(){
// Move rects
for(int i = 0; i < rects.size(); i++){
rects[i].y += rectSpeeds[i];
if(rects[i].y > fbo->getHeight()){
rects[i].y = -rects[i].getHeight();
}
}
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void CustomSource::draw(){
// Fill FBO with our rects
ofClear(0);
ofSetColor(255);
for(int i = 0; i < rects.size(); i++){
ofDrawRectangle(rects[i]);
}
}
#include "CustomSource.h"
void CustomSource::setup(){
// Give our source a decent name
name = "Custom FBO Source";
// Allocate our FBO source, decide how big it should be
allocate(500, 500);
// Genereate rects to be rendered into the FBO
int numRects = 20; // change this to add more or less rects
for(int i = 0; i < numRects; i++){
rects.push_back(ofRectangle(0,
ofRandom(fbo->getHeight()),
fbo->getWidth(),
ofRandom(20)));
rectSpeeds.push_back((1.0f + ofRandom(5)));
}
}
// Don't do any drawing here
void CustomSource::update(){
// Move rects
for(int i = 0; i < rects.size(); i++){
rects[i].y += rectSpeeds[i];
if(rects[i].y > fbo->getHeight()){
rects[i].y = -rects[i].getHeight();
}
}
}
// No need to take care of fbo.begin() and fbo.end() here.
// All within draw() is being rendered into fbo;
void CustomSource::draw(){
// Fill FBO with our rects
ofClear(0);
ofSetColor(255);
for(int i = 0; i < rects.size(); i++){
ofDrawRectangle(rects[i]);
}
}

26
example_simpler/src/CustomSource.h

@ -1,14 +1,14 @@
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class CustomSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<ofRectangle> rects;
std::vector<float> rectSpeeds;
#pragma once
#include "ofMain.h"
#include "FboSource.h"
class CustomSource : public ofx::piMapper::FboSource {
public:
void setup();
void update();
void draw();
std::vector<ofRectangle> rects;
std::vector<float> rectSpeeds;
};

42
example_simpler/src/Settings.cpp

@ -1,22 +1,22 @@
#include "Settings.h"
Settings * Settings::_instance = 0;
Settings * Settings::instance(){
if(_instance == 0){
_instance = new Settings();
}
return _instance;
}
Settings::Settings(){
_fullscreen = false;
}
void Settings::setFullscreen(bool f){
_fullscreen = f;
}
bool Settings::getFullscreen(){
return _fullscreen;
#include "Settings.h"
Settings * Settings::_instance = 0;
Settings * Settings::instance(){
if(_instance == 0){
_instance = new Settings();
}
return _instance;
}
Settings::Settings(){
_fullscreen = false;
}
void Settings::setFullscreen(bool f){
_fullscreen = f;
}
bool Settings::getFullscreen(){
return _fullscreen;
}

36
example_simpler/src/Settings.h

@ -1,18 +1,18 @@
#pragma once
#include "ofMain.h"
class Settings {
public:
static Settings * instance();
void setFullscreen(bool f);
bool getFullscreen();
private:
static Settings * _instance;
Settings();
bool _fullscreen;
};
#pragma once
#include "ofMain.h"
class Settings {
public:
static Settings * instance();
void setFullscreen(bool f);
bool getFullscreen();
private:
static Settings * _instance;
Settings();
bool _fullscreen;
};

44
example_simpler/src/main.cpp

@ -1,22 +1,22 @@
#include "ofMain.h"
#include "ofApp.h"
#include <string>
#include <vector>
#include "Settings.h"
int main(int argc, char * argv[]){
bool fullscreen = false;
std::vector<std::string> arguments = std::vector<std::string>(argv, argv + argc);
for(int i = 0; i < arguments.size(); ++i){
if(arguments.at(i) == "-f"){
fullscreen = true;
break;
}
}
Settings::instance()->setFullscreen(fullscreen);
ofSetupOpenGL(800, 450, OF_WINDOW);
ofRunApp(new ofApp());
}
#include "ofMain.h"
#include "ofApp.h"
#include <string>
#include <vector>
#include "Settings.h"
int main(int argc, char * argv[]){
bool fullscreen = false;
std::vector<std::string> arguments = std::vector<std::string>(argv, argv + argc);
for(int i = 0; i < arguments.size(); ++i){
if(arguments.at(i) == "-f"){
fullscreen = true;
break;
}
}
Settings::instance()->setFullscreen(fullscreen);
ofSetupOpenGL(800, 450, OF_WINDOW);
ofRunApp(new ofApp());
}

110
example_simpler/src/ofApp.cpp

@ -1,55 +1,55 @@
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
// Enable or disable audio for video sources globally
// Set this to false to save resources on the Raspberry Pi
ofx::piMapper::VideoSource::enableAudio = true;
ofx::piMapper::VideoSource::useHDMIForAudio = false;
// Add our CustomSource to list of fbo sources of the piMapper
// FBO sources should be added before piMapper.setup() so the
// piMapper is able to load the source if it is assigned to
// a surface in XML settings.
customSource = new CustomSource();
piMapper.registerFboSource(customSource);
piMapper.setup();
// The info layer is hidden by default, press <i> to toggle
// piMapper.showInfo();
ofSetFullscreen(Settings::instance()->getFullscreen());
ofSetEscapeQuitsApp(false);
dummyObjects.load("dummy-objects.png");
}
void ofApp::update(){
piMapper.update();
}
void ofApp::draw(){
dummyObjects.draw(200,200);
piMapper.draw();
}
void ofApp::keyPressed(int key){
piMapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
piMapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
piMapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
piMapper.mouseReleased(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
piMapper.mouseDragged(x, y, button);
}
#include "ofApp.h"
void ofApp::setup(){
ofBackground(0);
// Enable or disable audio for video sources globally
// Set this to false to save resources on the Raspberry Pi
ofx::piMapper::VideoSource::enableAudio = true;
ofx::piMapper::VideoSource::useHDMIForAudio = false;
// Add our CustomSource to list of fbo sources of the piMapper
// FBO sources should be added before piMapper.setup() so the
// piMapper is able to load the source if it is assigned to
// a surface in XML settings.
customSource = new CustomSource();
piMapper.registerFboSource(customSource);
piMapper.setup();
// The info layer is hidden by default, press <i> to toggle
// piMapper.showInfo();
ofSetFullscreen(Settings::instance()->getFullscreen());
ofSetEscapeQuitsApp(false);
dummyObjects.load("dummy-objects.png");
}
void ofApp::update(){
piMapper.update();
}
void ofApp::draw(){
dummyObjects.draw(200,200);
piMapper.draw();
}
void ofApp::keyPressed(int key){
piMapper.keyPressed(key);
}
void ofApp::keyReleased(int key){
piMapper.keyReleased(key);
}
void ofApp::mousePressed(int x, int y, int button){
piMapper.mousePressed(x, y, button);
}
void ofApp::mouseReleased(int x, int y, int button){
piMapper.mouseReleased(x, y, button);
}
void ofApp::mouseDragged(int x, int y, int button){
piMapper.mouseDragged(x, y, button);
}

56
example_simpler/src/ofApp.h

@ -1,28 +1,28 @@
#pragma once
#include "ofMain.h"
#include "Settings.h"
#include "ofxPiMapper.h"
#include "CustomSource.h"
#include "VideoSource.h"
class ofApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper piMapper;
// By using a custom source that is derived from FboSource
// you will be able to see the source listed in sources editor
CustomSource * customSource;
ofImage dummyObjects;
};
#pragma once
#include "ofMain.h"
#include "Settings.h"
#include "ofxPiMapper.h"
#include "CustomSource.h"
#include "VideoSource.h"
class ofApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper piMapper;
// By using a custom source that is derived from FboSource
// you will be able to see the source listed in sources editor
CustomSource * customSource;
ofImage dummyObjects;
};

532
patches/msys2/makefileCommon/config.addons.mk

@ -1,266 +1,266 @@
########################################################################
# PROCESS VALID ADDONS IF AVAILABLE
########################################################################
# parses addons includes, in PARSED_ADDON_INCLUDES receives full PATHS to addons
define parse_addons_includes
$(eval ADDONS_INCLUDES_FILTER = $(addprefix $1/, $(ADDON_INCLUDES_EXCLUDE))) \
$(eval PARSED_ADDONS_SOURCE_PATHS = $(addsuffix /src, $1)) \
$(eval PARSED_ADDONS_SOURCE_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_SOURCE_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_SOURCE_INCLUDES))) \
$(eval PARSED_ADDONS_LIBS_SOURCE_PATHS = $(addsuffix /libs, $1)) \
$(eval PARSED_ADDONS_LIBS_SOURCE_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_SOURCE_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_LIBS_SOURCE_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_LIBS_SOURCE_INCLUDES))) \
$(eval PARSED_ADDONS_LIBS_INCLUDES_PATHS = $(addsuffix /libs/*/include, $1)) \
$(eval PARSED_ADDONS_LIBS_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_INCLUDES_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_LIBS_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_LIBS_INCLUDES))) \
$(eval PARSED_ADDONS_INCLUDES = $(PARSED_ADDONS_FILTERED_INCLUDE_PATHS)) \
$(eval PARSED_ADDONS_INCLUDES += $(PARSED_ADDONS_FILTERED_LIBS_SOURCE_INCLUDE_PATHS)) \
$(eval PARSED_ADDONS_INCLUDES += $(PARSED_ADDONS_FILTERED_LIBS_INCLUDE_PATHS))
endef
# parses addons sources, in PARSED_ADDON_SOURCES receives full PATHS to addons
define parse_addons_sources
$(eval ADDONS_SOURCES_FILTER = $(addprefix $1/, $(ADDON_SOURCES_EXCLUDE))) \
$(eval PARSED_ADDONS_SOURCE_PATHS = $(addsuffix /src, $1)) \
$(eval PARSED_ADDONS_OFX_SOURCES = $(shell $(FIND) $(PARSED_ADDONS_SOURCE_PATHS) -type f \( -name "*.cpp" -or -name "*.c" -or -name "*.cc" -or -name "*.cxx" \) 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_SOURCE_PATHS = $(filter-out $(ADDONS_SOURCES_FILTER),$(PARSED_ADDONS_OFX_SOURCES))) \
$(eval PARSED_ADDONS_LIBS_SOURCE_PATHS = $(addsuffix /libs, $1)) \
$(eval PARSED_ADDONS_LIBS_SOURCES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_SOURCE_PATHS) -type f \( -name "*.cpp" -or -name "*.c" -or -name "*.cc" -or -name "*.cxx" \) 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_LIBS_SOURCE_PATHS = $(filter-out $(ADDONS_SOURCES_FILTER),$(PARSED_ADDONS_LIBS_SOURCES))) \
$(eval PARSED_ADDONS_SOURCE_FILES = $(PARSED_ADDONS_FILTERED_SOURCE_PATHS)) \
$(eval PARSED_ADDONS_SOURCE_FILES += $(PARSED_ADDONS_FILTERED_LIBS_SOURCE_PATHS))
endef
# parses addons libraries, in PARSED_ADDON_LIBS receives full PATHS to addons and libs_exclude
define parse_addons_libraries
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIB_PATHS = $(filter-out $(ADDON_LIBS_EXCLUDE),$(addsuffix /libs/*/lib/$(ABI_LIB_SUBPATH), $1))) \
$(eval PARSED_ALL_PLATFORM_LIBS = $(shell $(FIND) $(PARSED_ADDONS_LIBS_PLATFORM_LIB_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
$(if $(PARSED_ALL_PLATFORM_LIBS), \
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_STATICS = $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.a 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED = $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.so 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED += $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.dylib 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED += $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.dll 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_LIBS = $(PARSED_ADDONS_LIBS_PLATFORM_LIBS_STATICS)) \
$(eval PARSED_ADDONS_LIBS += $(PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED)) \
)
endef
space :=
space +=
define src_to_obj
$(addsuffix .o,$(basename $(filter %.c %.cpp %.cc %.cxx %.cc %.s %.S, $(addprefix $3,$(addprefix $2,$1)))))
endef
define rwildcard
$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)$(filter $(subst *,%,$2),$d))
endef
# PARSE addon_config.mk FILES
#
# 1. read the addon_config.mk file for each adddon that has it
# 2. read each line of the addon by converting \n to \t since makefiles treat \n as spaces
# also convert spaces to ? so foreach works for each line instead of each word
# 3. unscape ? to space inside the loop
# 4. if the line matches common: or platform: set the PROCESS_NEXT flag to true
# 5. if the line matches %: but it's not common or platform: set PROCESS_NEXT to false
# 6: if PROCESS_NEXT eval the line to put the variable in the makefile space
define parse_addon
$(if $(wildcard $(PROJECT_ROOT)/$1), \
$(eval addon=$(realpath $(addprefix $(PROJECT_ROOT)/, $1))) \
$(eval addon_obj_path=$(PROJECT_ROOT)) \
$(eval ADDON_PATHS+= $(dir $(addon))) \
$(eval obj_prefix=$(OF_PROJECT_OBJ_OUTPUT_PATH)addons/) \
, \
$(eval addon=$(realpath $(addprefix $(OF_ADDONS_PATH)/, $1))) \
$(eval addon_obj_path=$(OF_ADDONS_PATH)) \
$(eval obj_prefix=$(OF_PROJECT_OBJ_OUTPUT_PATH)) \
) \
$(eval ADDON_DEPENDENCIES= ) \
$(eval ADDON_DATA= ) \
$(eval ADDON_CFLAGS= ) \
$(eval ADDON_CPPFLAGS= ) \
$(eval ADDON_LDFLAGS= ) \
$(eval ADDON_PKG_CONFIG_LIBRARIES= ) \
$(eval ADDON_FRAMEWORKS= ) \
$(eval ADDON_LIBS_EXCLUDE= ) \
$(eval ADDON_SOURCES_EXCLUDE= ) \
$(call parse_addons_includes, $(addon)) \
$(eval ADDON_INCLUDES=$(PARSED_ADDONS_INCLUDES)) \
$(call parse_addons_libraries, $(addon)) \
$(eval ADDON_LIBS=$(PARSED_ADDONS_LIBS)) \
$(call parse_addons_sources, $(addon)) \
$(eval ADDON_SOURCES=$(PARSED_ADDONS_SOURCE_FILES)) \
$(eval PROCESS_NEXT=0) \
$(if $(wildcard $(addon)/addon_config.mk), \
$(foreach var_line, $(shell cat $(addon)/addon_config.mk | tr '\n ' '\t?'), \
$(eval unscaped_var_line=$(strip $(subst ?, ,$(var_line)))) \
$(if $(filter $(PROCESS_NEXT),1), $(eval $(unscaped_var_line))) \
$(if $(filter %:,$(unscaped_var_line)), \
$(if $(filter common:,$(unscaped_var_line)), \
$(eval PROCESS_NEXT=1), \
$(if $(filter $(ABI_LIB_SUBPATH):,$(unscaped_var_line)), \
$(eval PROCESS_NEXT=1), \
$(eval PROCESS_NEXT=0) \
) \
) \
) \
) \
) \
$(if $(strip $(ADDON_INCLUDES)), \
$(eval ADDON_INCLUDES_FILTERED = $(filter-out $(addprefix $(addon)/,$(ADDON_INCLUDES_EXCLUDE)),$(ADDON_INCLUDES))) \
$(foreach addon_include, $(strip $(ADDON_INCLUDES_FILTERED)), \
$(if $(wildcard $(addon)/$(addon_include)), \
$(eval TMP_PROJECT_ADDONS_INCLUDES += $(addon)/$(addon_include)) \
) \
$(if $(wildcard $(addon_include)), \
$(eval TMP_PROJECT_ADDONS_INCLUDES += $(addon_include)) \
) \
) \
) \
$(eval TMP_PROJECT_ADDONS_CFLAGS += $(ADDON_CFLAGS)) \
$(eval TMP_PROJECT_ADDONS_CFLAGS += $(ADDON_CPPFLAGS)) \
$(if $(strip $(ADDON_LIBS)), \
$(foreach addon_lib, $(strip $(ADDON_LIBS)), \
$(if $(wildcard $(addon)/$(addon_lib)), \
$(eval TMP_PROJECT_ADDONS_LIBS += $(addon)/$(addon_lib)) \
) \
$(if $(wildcard $(addon_lib)), \
$(eval TMP_PROJECT_ADDONS_LIBS += $(addon_lib)) \
) \
) \
) \
$(eval TMP_PROJECT_ADDONS_LDFLAGS += $(ADDON_LDFLAGS)) \
$(eval TMP_PROJECT_ADDONS_PKG_CONFIG_LIBRARIES += $(ADDON_PKG_CONFIG_LIBRARIES)) \
$(eval TMP_PROJECT_ADDONS_FRAMEWORKS += $(ADDON_FRAMEWORKS)) \
$(eval PROJECT_AFTER += $(ADDON_AFTER)) \
$(if $(strip $(ADDON_SOURCES)), \
$(eval ADDON_SOURCES_FILTERED = $(filter-out $(addprefix $(addon)/,$(ADDON_SOURCES_EXCLUDE)),$(ADDON_SOURCES))) \
$(foreach addon_src, $(strip $(ADDON_SOURCES_FILTERED)), \
$(if $(filter $(addon)%, $(addon_src)), \
$(eval addon_path=$(subst %,*,$(addon_src))) \
$(if $(findstring *,$(addon_path)), \
$(eval addon_dir=$(dir $(addon_path))) \
$(eval addon_rest=$(notdir $(addon_path))) \
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
$(foreach expanded_addon_src, $(addon_files), \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(expanded_addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
, \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_src)) \
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
, \
$(if $(filter $(OF_ROOT)%, $(addon_src)), \
$(eval addon_path=$(subst %,*,$(addon_src))) \
$(if $(findstring *,$(addon_path)), \
$(eval addon_dir=$(dir $(addon_src))) \
$(eval addon_rest=$(notdir $(addon_src))) \
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
$(foreach expanded_addon_src, $(addon_files), \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
$(eval SRC_OBJ_FILE=$(strip $(call src_to_obj, $(expanded_addon_src:$(OF_ROOT)/%=%),,$(obj_prefix)))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
, \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_src)) \
$(eval SRC_OBJ_FILE=$(strip $(call src_to_obj, $(addon_src:$(OF_ROOT)/%=%),,$(obj_prefix)))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
,$(if $(filter-out /%, $(addon_src)), \
$(eval addon_path=$(addon)/$(subst %,*,$(addon_src))) \
$(if $(findstring *,$(addon_path)), \
$(eval addon_dir=$(dir $(addon_path))) \
$(eval addon_rest=$(notdir $(addon_path))) \
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
$(foreach expanded_addon_src, $(addon_files), \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(expanded_addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
, \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_path)) \
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(addon_path:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
,$(error cannot find addon source file $(addon_src))) \
) \
) \
) \
) \
$(if $(strip $(ADDON_DATA)), \
$(eval TMP_PROJECT_ADDONS_DATA += $(addprefix $(addon)/,$(ADDON_DATA))) \
) \
$(foreach addon_dep, $(strip $(ADDON_DEPENDENCIES)), \
$(if $(filter %$(addon_dep), $(PROJECT_ADDONS)), \
, \
$(eval PROJECT_ADDONS += $(addon_dep)) \
$(call parse_addon,$(addon_dep)) \
) \
)
endef
$(foreach addon_to_parse, $(PROJECT_ADDONS), \
$(call parse_addon,$(addon_to_parse)) \
)
#define uniq =
# $(eval seen :=)
# $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
# ${seen}
#endef
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
PROJECT_ADDONS_CFLAGS = $(call uniq,$(TMP_PROJECT_ADDONS_CFLAGS))
PROJECT_ADDONS_INCLUDES = $(call uniq,$(TMP_PROJECT_ADDONS_INCLUDES))
PROJECT_ADDONS_LIBS = $(call uniq,$(TMP_PROJECT_ADDONS_LIBS))
PROJECT_ADDONS_LDFLAGS = $(call uniq,$(TMP_PROJECT_ADDONS_LDFLAGS))
PROJECT_ADDONS_PKG_CONFIG_LIBRARIES = $(call uniq,$(TMP_PROJECT_ADDONS_PKG_CONFIG_LIBRARIES))
PROJECT_ADDONS_FRAMEWORKS = $(call uniq,$(TMP_PROJECT_ADDONS_FRAMEWORKS))
PROJECT_ADDONS_SOURCE_FILES = $(call uniq,$(TMP_PROJECT_ADDONS_SOURCE_FILES))
PROJECT_ADDONS_OBJ_FILES = $(call uniq,$(TMP_PROJECT_ADDONS_OBJ_FILES))
PROJECT_ADDONS_DATA = $(call uniq,$(TMP_PROJECT_ADDONS_DATA))
VPATH += $(call uniq, $(ADDON_PATHS))
OF_PROJECT_ADDONS_OBJS = $(PROJECT_ADDONS_OBJ_FILES)
OF_PROJECT_ADDONS_DEPS = $(patsubst %.o,%.d,$(PROJECT_ADDONS_OBJ_FILES))
########################################################################
# DEBUGGING
########################################################################
# print debug information if so instructed
ifdef MAKEFILE_DEBUG
$(info ---PROJECT_ADDONS_PATHS---)
$(foreach v, $(PROJECT_ADDONS_PATHS),$(info $(v)))
$(info ---PROJECT_ADDONS_WITH_CONFIG---)
$(foreach v, $(PROJECT_ADDONS_WITH_CONFIG),$(info $(v)))
$(info ---PROJECT_ADDONS_INCLUDES---)
$(foreach v, $(PROJECT_ADDONS_INCLUDES),$(info $(v)))
$(info ---PROJECT_ADDONS_SOURCE_FILES---)
$(foreach v, $(PROJECT_ADDONS_SOURCE_FILES),$(info $(v)))
$(info ---PROJECT_ADDONS_LIBS---)
$(foreach v, $(PROJECT_ADDONS_LIBS),$(info $(v)))
$(info ---PROJECT_ADDONS_OBJFILES---)
$(foreach v, $(PROJECT_ADDONS_OBJFILES),$(info $(v)))
$(info ---PROJECT_ADDONS_BASE_CFLAGS---)
$(foreach v, $(PROJECT_ADDONS_BASE_CFLAGS),$(info $(v)))
$(info ---PROJECT_ADDONS_DEFINES_CFLAGS---)
$(foreach v, $(PROJECT_ADDONS_DEFINES_CFLAGS),$(info $(v)))
$(info ---PROJECT_ADDONS_INCLUDES_CFLAGS---)
$(foreach v, $(PROJECT_ADDONS_INCLUDES_CFLAGS),$(info $(v)))
$(info ---PROJECT_ADDONS_LDFLAGS---)
$(foreach v, $(PROJECT_ADDONS_LDFLAGS),$(info $(v)))
$(info ---PROJECT_ADDONS_DATA---)
$(foreach v, $(PROJECT_ADDONS_DATA),$(info $(v)))
endif
########################################################################
# PROCESS VALID ADDONS IF AVAILABLE
########################################################################
# parses addons includes, in PARSED_ADDON_INCLUDES receives full PATHS to addons
define parse_addons_includes
$(eval ADDONS_INCLUDES_FILTER = $(addprefix $1/, $(ADDON_INCLUDES_EXCLUDE))) \
$(eval PARSED_ADDONS_SOURCE_PATHS = $(addsuffix /src, $1)) \
$(eval PARSED_ADDONS_SOURCE_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_SOURCE_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_SOURCE_INCLUDES))) \
$(eval PARSED_ADDONS_LIBS_SOURCE_PATHS = $(addsuffix /libs, $1)) \
$(eval PARSED_ADDONS_LIBS_SOURCE_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_SOURCE_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_LIBS_SOURCE_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_LIBS_SOURCE_INCLUDES))) \
$(eval PARSED_ADDONS_LIBS_INCLUDES_PATHS = $(addsuffix /libs/*/include, $1)) \
$(eval PARSED_ADDONS_LIBS_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_INCLUDES_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_LIBS_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_LIBS_INCLUDES))) \
$(eval PARSED_ADDONS_INCLUDES = $(PARSED_ADDONS_FILTERED_INCLUDE_PATHS)) \
$(eval PARSED_ADDONS_INCLUDES += $(PARSED_ADDONS_FILTERED_LIBS_SOURCE_INCLUDE_PATHS)) \
$(eval PARSED_ADDONS_INCLUDES += $(PARSED_ADDONS_FILTERED_LIBS_INCLUDE_PATHS))
endef
# parses addons sources, in PARSED_ADDON_SOURCES receives full PATHS to addons
define parse_addons_sources
$(eval ADDONS_SOURCES_FILTER = $(addprefix $1/, $(ADDON_SOURCES_EXCLUDE))) \
$(eval PARSED_ADDONS_SOURCE_PATHS = $(addsuffix /src, $1)) \
$(eval PARSED_ADDONS_OFX_SOURCES = $(shell $(FIND) $(PARSED_ADDONS_SOURCE_PATHS) -type f \( -name "*.cpp" -or -name "*.c" -or -name "*.cc" -or -name "*.cxx" \) 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_SOURCE_PATHS = $(filter-out $(ADDONS_SOURCES_FILTER),$(PARSED_ADDONS_OFX_SOURCES))) \
$(eval PARSED_ADDONS_LIBS_SOURCE_PATHS = $(addsuffix /libs, $1)) \
$(eval PARSED_ADDONS_LIBS_SOURCES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_SOURCE_PATHS) -type f \( -name "*.cpp" -or -name "*.c" -or -name "*.cc" -or -name "*.cxx" \) 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_FILTERED_LIBS_SOURCE_PATHS = $(filter-out $(ADDONS_SOURCES_FILTER),$(PARSED_ADDONS_LIBS_SOURCES))) \
$(eval PARSED_ADDONS_SOURCE_FILES = $(PARSED_ADDONS_FILTERED_SOURCE_PATHS)) \
$(eval PARSED_ADDONS_SOURCE_FILES += $(PARSED_ADDONS_FILTERED_LIBS_SOURCE_PATHS))
endef
# parses addons libraries, in PARSED_ADDON_LIBS receives full PATHS to addons and libs_exclude
define parse_addons_libraries
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIB_PATHS = $(filter-out $(ADDON_LIBS_EXCLUDE),$(addsuffix /libs/*/lib/$(ABI_LIB_SUBPATH), $1))) \
$(eval PARSED_ALL_PLATFORM_LIBS = $(shell $(FIND) $(PARSED_ADDONS_LIBS_PLATFORM_LIB_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
$(if $(PARSED_ALL_PLATFORM_LIBS), \
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_STATICS = $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.a 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED = $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.so 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED += $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.dylib 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED += $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.dll 2> /dev/null | grep -v "/\.[^\.]" )) \
$(eval PARSED_ADDONS_LIBS = $(PARSED_ADDONS_LIBS_PLATFORM_LIBS_STATICS)) \
$(eval PARSED_ADDONS_LIBS += $(PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED)) \
)
endef
space :=
space +=
define src_to_obj
$(addsuffix .o,$(basename $(filter %.c %.cpp %.cc %.cxx %.cc %.s %.S, $(addprefix $3,$(addprefix $2,$1)))))
endef
define rwildcard
$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)$(filter $(subst *,%,$2),$d))
endef
# PARSE addon_config.mk FILES
#
# 1. read the addon_config.mk file for each adddon that has it
# 2. read each line of the addon by converting \n to \t since makefiles treat \n as spaces
# also convert spaces to ? so foreach works for each line instead of each word
# 3. unscape ? to space inside the loop
# 4. if the line matches common: or platform: set the PROCESS_NEXT flag to true
# 5. if the line matches %: but it's not common or platform: set PROCESS_NEXT to false
# 6: if PROCESS_NEXT eval the line to put the variable in the makefile space
define parse_addon
$(if $(wildcard $(PROJECT_ROOT)/$1), \
$(eval addon=$(realpath $(addprefix $(PROJECT_ROOT)/, $1))) \
$(eval addon_obj_path=$(PROJECT_ROOT)) \
$(eval ADDON_PATHS+= $(dir $(addon))) \
$(eval obj_prefix=$(OF_PROJECT_OBJ_OUTPUT_PATH)addons/) \
, \
$(eval addon=$(realpath $(addprefix $(OF_ADDONS_PATH)/, $1))) \
$(eval addon_obj_path=$(OF_ADDONS_PATH)) \
$(eval obj_prefix=$(OF_PROJECT_OBJ_OUTPUT_PATH)) \
) \
$(eval ADDON_DEPENDENCIES= ) \
$(eval ADDON_DATA= ) \
$(eval ADDON_CFLAGS= ) \
$(eval ADDON_CPPFLAGS= ) \
$(eval ADDON_LDFLAGS= ) \
$(eval ADDON_PKG_CONFIG_LIBRARIES= ) \
$(eval ADDON_FRAMEWORKS= ) \
$(eval ADDON_LIBS_EXCLUDE= ) \
$(eval ADDON_SOURCES_EXCLUDE= ) \
$(call parse_addons_includes, $(addon)) \
$(eval ADDON_INCLUDES=$(PARSED_ADDONS_INCLUDES)) \
$(call parse_addons_libraries, $(addon)) \
$(eval ADDON_LIBS=$(PARSED_ADDONS_LIBS)) \
$(call parse_addons_sources, $(addon)) \
$(eval ADDON_SOURCES=$(PARSED_ADDONS_SOURCE_FILES)) \
$(eval PROCESS_NEXT=0) \
$(if $(wildcard $(addon)/addon_config.mk), \
$(foreach var_line, $(shell cat $(addon)/addon_config.mk | tr '\n ' '\t?'), \
$(eval unscaped_var_line=$(strip $(subst ?, ,$(var_line)))) \
$(if $(filter $(PROCESS_NEXT),1), $(eval $(unscaped_var_line))) \
$(if $(filter %:,$(unscaped_var_line)), \
$(if $(filter common:,$(unscaped_var_line)), \
$(eval PROCESS_NEXT=1), \
$(if $(filter $(ABI_LIB_SUBPATH):,$(unscaped_var_line)), \
$(eval PROCESS_NEXT=1), \
$(eval PROCESS_NEXT=0) \
) \
) \
) \
) \
) \
$(if $(strip $(ADDON_INCLUDES)), \
$(eval ADDON_INCLUDES_FILTERED = $(filter-out $(addprefix $(addon)/,$(ADDON_INCLUDES_EXCLUDE)),$(ADDON_INCLUDES))) \
$(foreach addon_include, $(strip $(ADDON_INCLUDES_FILTERED)), \
$(if $(wildcard $(addon)/$(addon_include)), \
$(eval TMP_PROJECT_ADDONS_INCLUDES += $(addon)/$(addon_include)) \
) \
$(if $(wildcard $(addon_include)), \
$(eval TMP_PROJECT_ADDONS_INCLUDES += $(addon_include)) \
) \
) \
) \
$(eval TMP_PROJECT_ADDONS_CFLAGS += $(ADDON_CFLAGS)) \
$(eval TMP_PROJECT_ADDONS_CFLAGS += $(ADDON_CPPFLAGS)) \
$(if $(strip $(ADDON_LIBS)), \
$(foreach addon_lib, $(strip $(ADDON_LIBS)), \
$(if $(wildcard $(addon)/$(addon_lib)), \
$(eval TMP_PROJECT_ADDONS_LIBS += $(addon)/$(addon_lib)) \
) \
$(if $(wildcard $(addon_lib)), \
$(eval TMP_PROJECT_ADDONS_LIBS += $(addon_lib)) \
) \
) \
) \
$(eval TMP_PROJECT_ADDONS_LDFLAGS += $(ADDON_LDFLAGS)) \
$(eval TMP_PROJECT_ADDONS_PKG_CONFIG_LIBRARIES += $(ADDON_PKG_CONFIG_LIBRARIES)) \
$(eval TMP_PROJECT_ADDONS_FRAMEWORKS += $(ADDON_FRAMEWORKS)) \
$(eval PROJECT_AFTER += $(ADDON_AFTER)) \
$(if $(strip $(ADDON_SOURCES)), \
$(eval ADDON_SOURCES_FILTERED = $(filter-out $(addprefix $(addon)/,$(ADDON_SOURCES_EXCLUDE)),$(ADDON_SOURCES))) \
$(foreach addon_src, $(strip $(ADDON_SOURCES_FILTERED)), \
$(if $(filter $(addon)%, $(addon_src)), \
$(eval addon_path=$(subst %,*,$(addon_src))) \
$(if $(findstring *,$(addon_path)), \
$(eval addon_dir=$(dir $(addon_path))) \
$(eval addon_rest=$(notdir $(addon_path))) \
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
$(foreach expanded_addon_src, $(addon_files), \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(expanded_addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
, \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_src)) \
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
, \
$(if $(filter $(OF_ROOT)%, $(addon_src)), \
$(eval addon_path=$(subst %,*,$(addon_src))) \
$(if $(findstring *,$(addon_path)), \
$(eval addon_dir=$(dir $(addon_src))) \
$(eval addon_rest=$(notdir $(addon_src))) \
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
$(foreach expanded_addon_src, $(addon_files), \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
$(eval SRC_OBJ_FILE=$(strip $(call src_to_obj, $(expanded_addon_src:$(OF_ROOT)/%=%),,$(obj_prefix)))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
, \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_src)) \
$(eval SRC_OBJ_FILE=$(strip $(call src_to_obj, $(addon_src:$(OF_ROOT)/%=%),,$(obj_prefix)))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
,$(if $(filter-out /%, $(addon_src)), \
$(eval addon_path=$(addon)/$(subst %,*,$(addon_src))) \
$(if $(findstring *,$(addon_path)), \
$(eval addon_dir=$(dir $(addon_path))) \
$(eval addon_rest=$(notdir $(addon_path))) \
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
$(foreach expanded_addon_src, $(addon_files), \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(expanded_addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
, \
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_path)) \
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(addon_path:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
) \
,$(error cannot find addon source file $(addon_src))) \
) \
) \
) \
) \
$(if $(strip $(ADDON_DATA)), \
$(eval TMP_PROJECT_ADDONS_DATA += $(addprefix $(addon)/,$(ADDON_DATA))) \
) \
$(foreach addon_dep, $(strip $(ADDON_DEPENDENCIES)), \
$(if $(filter %$(addon_dep), $(PROJECT_ADDONS)), \
, \
$(eval PROJECT_ADDONS += $(addon_dep)) \
$(call parse_addon,$(addon_dep)) \
) \
)
endef
$(foreach addon_to_parse, $(PROJECT_ADDONS), \
$(call parse_addon,$(addon_to_parse)) \
)
#define uniq =
# $(eval seen :=)
# $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
# ${seen}
#endef
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
PROJECT_ADDONS_CFLAGS = $(call uniq,$(TMP_PROJECT_ADDONS_CFLAGS))
PROJECT_ADDONS_INCLUDES = $(call uniq,$(TMP_PROJECT_ADDONS_INCLUDES))
PROJECT_ADDONS_LIBS = $(call uniq,$(TMP_PROJECT_ADDONS_LIBS))
PROJECT_ADDONS_LDFLAGS = $(call uniq,$(TMP_PROJECT_ADDONS_LDFLAGS))
PROJECT_ADDONS_PKG_CONFIG_LIBRARIES = $(call uniq,$(TMP_PROJECT_ADDONS_PKG_CONFIG_LIBRARIES))
PROJECT_ADDONS_FRAMEWORKS = $(call uniq,$(TMP_PROJECT_ADDONS_FRAMEWORKS))
PROJECT_ADDONS_SOURCE_FILES = $(call uniq,$(TMP_PROJECT_ADDONS_SOURCE_FILES))
PROJECT_ADDONS_OBJ_FILES = $(call uniq,$(TMP_PROJECT_ADDONS_OBJ_FILES))
PROJECT_ADDONS_DATA = $(call uniq,$(TMP_PROJECT_ADDONS_DATA))
VPATH += $(call uniq, $(ADDON_PATHS))
OF_PROJECT_ADDONS_OBJS = $(PROJECT_ADDONS_OBJ_FILES)
OF_PROJECT_ADDONS_DEPS = $(patsubst %.o,%.d,$(PROJECT_ADDONS_OBJ_FILES))
########################################################################
# DEBUGGING
########################################################################
# print debug information if so instructed
ifdef MAKEFILE_DEBUG
$(info ---PROJECT_ADDONS_PATHS---)
$(foreach v, $(PROJECT_ADDONS_PATHS),$(info $(v)))
$(info ---PROJECT_ADDONS_WITH_CONFIG---)
$(foreach v, $(PROJECT_ADDONS_WITH_CONFIG),$(info $(v)))
$(info ---PROJECT_ADDONS_INCLUDES---)
$(foreach v, $(PROJECT_ADDONS_INCLUDES),$(info $(v)))
$(info ---PROJECT_ADDONS_SOURCE_FILES---)
$(foreach v, $(PROJECT_ADDONS_SOURCE_FILES),$(info $(v)))
$(info ---PROJECT_ADDONS_LIBS---)
$(foreach v, $(PROJECT_ADDONS_LIBS),$(info $(v)))
$(info ---PROJECT_ADDONS_OBJFILES---)
$(foreach v, $(PROJECT_ADDONS_OBJFILES),$(info $(v)))
$(info ---PROJECT_ADDONS_BASE_CFLAGS---)
$(foreach v, $(PROJECT_ADDONS_BASE_CFLAGS),$(info $(v)))
$(info ---PROJECT_ADDONS_DEFINES_CFLAGS---)
$(foreach v, $(PROJECT_ADDONS_DEFINES_CFLAGS),$(info $(v)))
$(info ---PROJECT_ADDONS_INCLUDES_CFLAGS---)
$(foreach v, $(PROJECT_ADDONS_INCLUDES_CFLAGS),$(info $(v)))
$(info ---PROJECT_ADDONS_LDFLAGS---)
$(foreach v, $(PROJECT_ADDONS_LDFLAGS),$(info $(v)))
$(info ---PROJECT_ADDONS_DATA---)
$(foreach v, $(PROJECT_ADDONS_DATA),$(info $(v)))
endif

16
patches/msys2/patch.sh

@ -1,8 +1,8 @@
#!/usr/bin/bash
echo "This script should be run from the patches/msys2 directory"
cp --force ./sound/ofOpenALSoundPlayer.* ../../../../libs/openFrameworks/sound/
cp --force ./makefileCommon/config.addons.mk ../../../../libs/openFrameworksCompiled/project/makefileCommon/config.addons.mk
echo "Patch for msys2 complete"
#!/usr/bin/bash
echo "This script should be run from the patches/msys2 directory"
cp --force ./sound/ofOpenALSoundPlayer.* ../../../../libs/openFrameworks/sound/
cp --force ./makefileCommon/config.addons.mk ../../../../libs/openFrameworksCompiled/project/makefileCommon/config.addons.mk
echo "Patch for msys2 complete"

2152
patches/msys2/sound/ofOpenALSoundPlayer.cpp

File diff suppressed because it is too large

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save