├── .gitignore
├── README.md
├── addon_config.mk
├── example-singleServer
├── CMakeLists.txt
├── Info.plist
├── addons.make
├── bin
│ └── data
│ │ └── settings.xml
├── client.html
├── client.maxpat
├── client.pd
└── src
│ ├── CirclesRenderer.cpp
│ ├── CirclesRenderer.h
│ ├── main.cpp
│ ├── ofApp.cpp
│ └── ofApp.h
├── example-twoServers
├── CMakeLists.txt
├── Info.plist
├── addons.make
├── bin
│ └── data
│ │ └── settings.xml
└── src
│ ├── CirclesRenderer.cpp
│ ├── CirclesRenderer.h
│ ├── main.cpp
│ ├── ofApp.cpp
│ └── ofApp.h
├── extra
├── Demo.score
└── ReadMe.md
├── license.md
└── src
├── ofxOscQueryServer.cpp
├── ofxOscQueryServer.h
├── ofxOssiaNode.h
└── ofxOssiaTypes.h
/.gitignore:
--------------------------------------------------------------------------------
1 | #########################
2 | # general patterns
3 | #########################
4 |
5 | docs/html
6 | docs/tagfile.xml
7 |
8 | */bin/*
9 | !*/bin/data/
10 |
11 | # for bin folder in root
12 | /bin/*
13 | !/bin/data/
14 |
15 | [Bb]uild/
16 | [Oo]bj/
17 | *.o
18 | [Dd]ebug*/
19 | [Rr]elease*/
20 | *.mode*
21 | *.app/
22 | *.pyc
23 | .svn/
24 |
25 | #########################
26 | # IDE
27 | #########################
28 |
29 | # XCode
30 | *.pbxuser
31 | *.perspective
32 | *.perspectivev3
33 | *.mode1v3
34 | *.mode2v3
35 | #XCode 4
36 | xcuserdata
37 | *.xcworkspace
38 |
39 | # Code::Blocks
40 | *.depend
41 | *.layout
42 | *.cbTemp
43 |
44 | # Visual Studio
45 | *.sdf
46 | *.opensdf
47 | *.suo
48 | *.pdb
49 | *.ilk
50 | *.aps
51 | ipch/
52 |
53 | # Eclipse
54 | .metadata
55 | local.properties
56 | .externalToolBuilders
57 |
58 | # Codelite
59 | *.session
60 | *.tags
61 | *.workspace.*
62 |
63 | #########################
64 | # operating system
65 | #########################
66 |
67 | # Linux
68 | *~
69 | # KDE
70 | .directory
71 | .AppleDouble
72 |
73 | # OSX
74 | .DS_Store
75 | *.swp
76 | *~.nib
77 | # Thumbnails
78 | ._*
79 |
80 | # Windows
81 | # Windows image file caches
82 | Thumbs.db
83 | # Folder config file
84 | Desktop.ini
85 |
86 | #Android
87 | .csettings
88 |
89 | #########################
90 | # packages
91 | #########################
92 |
93 | # it's better to unpack these files and commit the raw source
94 | # git has its own built in compression methods
95 | *.7z
96 | *.dmg
97 | *.gz
98 | *.iso
99 | *.jar
100 | *.rar
101 | *.tar
102 | *.zip
103 |
104 | # Logs and databases
105 | *.log
106 | *.sql
107 | *.sqlite
108 |
109 |
110 | *.a
111 |
112 | *.make
113 | Makefile
114 | *.xcconfig
115 | /libs
116 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ofxOscQuery
2 |
3 | ## Introduction
4 |
5 | This openFrameworks addon allows to create an OSCQuery server, based on the specifications available at: https://github.com/Vidvox/OSCQueryProposal.
6 |
7 |
8 | What will this addon do ?
9 |
10 | It will expose all of your `ofParameter`s (and `ofPArameterGroup`s) as a tree of OSC nodes, create OSC senders and receivers, and implement an OSCQuery server in order to manage queries and replies.
11 |
12 |
13 | Basically it is a wrapper for [libossia](https://github.com/OSSIA/libossia) ([safeC++ API](https://ossia.github.io/?cpp--98)) but it follows OSC Query’s dialect instead of ossia’s. Though, as does ossia, it covers all the features from the OSCQuery specifications (including listening, and notification for path changes).
14 |
15 | Here is [a video showing the addon in use with two other apps (VDMX and Vezér)](https://vimeo.com/288203374)
16 |
17 |
18 |
19 | This addon works in a similar way to ofxOscParameterSync from the ofxOsc addon:
20 | * declare an ofxOscQueryServer in your ofApp,
21 | * set it up by attaching it to an *ofParameterGroup*, and declaring OSC and WS ports.
22 | * All children *ofParameter*s and *ofParameterGroup*s will then be scanned recursively, exposed to the OSCQuery protocol
23 | * libossia will manage all network communication and queries from then on.
24 | * supplementary OSCQuery attributes can be set to the OSCQuery nodes attached to *ofParameter*s and *ofParameterGroup*s
25 |
26 | Here is [a video showing how to add OSCQuery support to one of of's "vanilla" examples](https://vimeo.com/288202877)
27 |
28 | This is all demonstrated in **example-singleServer** - further documentation is included in the source, and in particular in ofxOssiaNode, which is the core of it all.
29 |
30 | Several Servers can be set up in the same ofApp by attaching them to several *ofParameterGroup*s (see **example-twoServers**). As mentioned in the Roadmap below, another option will soon be added (without breaking the current usage) for managing this better: by using one pool object for holding several servers. Stay tuned!
31 |
32 | ## Installation
33 |
34 | 1. Download the latest .zip from the [releases](https://github.com/bltzr/ofxOscQuery/releases).
35 | 2. Unzip and move the directory to the openFrameworks addon directory.
36 |
37 | ## OSCQuery Clients
38 |
39 | Several client examples are provided in the **example-singleServer** folder: for pure-data, Max, and with a simple html example.
40 |
41 | It's also possible to view the ofApp's namespace as JSON by opening a browser (preferably FireFox for pretty formatting), by opening the URL: [http://yourServersIP:port/](http://localhost:5678/) - the default port (e.g. in **example-singleServer** being 5678).
42 |
43 | One can also download mrRay's (from VidVox) nice [OSCQueryBrowser](https://docs.vidvox.net/freebies_oscquery_browser.html) for more advanced browsing.
44 |
45 | Of course it really gets interesting when trying to control your ofApp, which you can do with those OSCQuery-supporting sequencers:
46 | - [ossia score](https://ossia.io)
47 | - [Vezér](https://imimot.com/vezer/)
48 |
49 | ## Compatibility
50 |
51 | * Works with of 0.10 - for 0.9.8, see specific legacy release
52 | * 0.9.8 version works with ofNode (aka with cmake), 1.0.0 doesn't since ofNode hasn't been ported to 0.10 (yet)
53 | * Available for:
54 | - macOS,
55 | - Linux (tested on Ubuntu and archlinux, should work on other distros with gcc >= 6)
56 | - Windows (32 and 64 bits)
57 | * ARM (aka raspberry Pi) should come soon
58 | * CodeBlocks support for Win should be doable if one wants to investigate on that - Please feel free to ask for help and guidance in the issue, and as always, PRs are welcome!
59 |
60 | ## Dependencies
61 |
62 | A compiled version of [libossia](https://ossia.github.io/?cpp--98#introduction) is included in the release.
63 |
64 | ## Roadmap
65 |
66 | - add a, more generic, ofxOscQuery object, that acts as a pool of servers, and allows to add them dynamically
67 | - make the OSC Query namespace dynamic (i.e. adding OSC nodes when adding `ofParameter`s and `ofParameterGroup`s)
68 | - first manually by adding a method to add specific nodes (should come soon)
69 | - then automatically by adding some listener to `ofParameterGroup` when a new child `ofParameter` is created
70 |
71 | ## Version history
72 |
73 | ### Version 1.0 (09/2018):
74 | Operational version, complying with the official OSC Query specs.
75 | - updated with the final 1.0 version of the OSC Query specifications
76 | - updated for of 0.10
77 | - methods have been added to manage OSC Query Attributes
78 | - the `findNode` method has been replaced by subscripting
79 |
80 | ## version 0.9.8 (09/2018)
81 | Legacy release for openframworks 0.9.8 - Same as version 1.0, except that it will build in 0.9.8
82 |
83 | ### Version 0.1 (04/2018):
84 | Initial version of the addon, with only basic functionality
85 |
86 |
--------------------------------------------------------------------------------
/addon_config.mk:
--------------------------------------------------------------------------------
1 | # All variables and this file are optional, if they are not present the PG and the
2 | # makefiles will try to parse the correct values from the file system.
3 | #
4 | # Variables that specify exclusions can use % as a wildcard to specify that anything in
5 | # that position will match. A partial path can also be specified to, for example, exclude
6 | # a whole folder from the parsed paths from the file system
7 | #
8 | # Variables can be specified using = or +=
9 | # = will clear the contents of that variable both specified from the file or the ones parsed
10 | # from the file system
11 | # += will add the values to the previous ones in the file or the ones parsed from the file
12 | # system
13 | #
14 | # The PG can be used to detect errors in this file, just create a new project with this addon
15 | # and the PG will write to the console the kind of error and in which line it is
16 |
17 | meta:
18 | ADDON_NAME = ofxOscQuery
19 | ADDON_DESCRIPTION = Addon for exposing parameters to the OSCQuery protocol
20 | ADDON_AUTHOR = Pascal Baltazar
21 | ADDON_TAGS = "bridge" "utilities" "networking"
22 | ADDON_URL = http://github.com/bltzr/ofxOscQuery
23 |
24 | common:
25 | ADDON_INCLUDES += libs/ossia/include
26 | # dependencies with other addons, a list of them separated by spaces
27 | # or use += in several lines
28 | # ADDON_DEPENDENCIES =
29 |
30 | # include search paths, this will be usually parsed from the file system
31 | # but if the addon or addon libraries need special search paths they can be
32 | # specified here separated by spaces or one per line using +=
33 | # ADDON_INCLUDES =
34 |
35 | # any special flag that should be passed to the compiler when using this
36 | # addon
37 | # ADDON_CFLAGS =
38 |
39 | # any special flag that should be passed to the linker when using this
40 | # addon, also used for system libraries with -lname
41 | # ADDON_LDFLAGS =
42 |
43 | # linux only, any library that should be included in the project using
44 | # pkg-config
45 | # ADDON_PKG_CONFIG_LIBRARIES =
46 |
47 | # osx/iOS only, any framework that should be included in the project
48 | # ADDON_FRAMEWORKS =
49 |
50 | # source files, these will be usually parsed from the file system looking
51 | # in the src folders in libs and the root of the addon. if your addon needs
52 | # to include files in different places or a different set of files per platform
53 | # they can be specified here
54 | # ADDON_SOURCES =
55 |
56 | # some addons need resources to be copied to the bin/data folder of the project
57 | # specify here any files that need to be copied, you can use wildcards like * and ?
58 | # ADDON_DATA =
59 |
60 | # when parsing the file system looking for libraries exclude this for all or
61 | # a specific platform
62 | # ADDON_LIBS_EXCLUDE =
63 |
64 | # when parsing the file system looking for sources exclude this for all or
65 | # a specific platform
66 |
67 |
68 | # when parsing the file system looking for include paths exclude this for all or
69 | # a specific platform
70 |
71 |
72 | linux64:
73 | ADDON_LIBS += libs/ossia/lib/linux64/libossia.a
74 | ADDON_LDFLAGS += -lavahi-client -lavahi-common
75 |
76 | linux:
77 | ADDON_LDFLAGS += -lavahi-client -lavahi-common
78 |
79 | msys2:
80 | ADDON_CPPFLAGS += NOMINMAX
81 | ADDON_CPPFLAGS += _CRT_SECURE_NO_WARNINGS
82 | ADDON_CPPFLAGS += WIN32_LEAN_AND_MEAN
83 |
84 | ADDON_LIBS += Ws2_32
85 | ADDON_LIBS += winmm
86 |
87 | vs:
88 | ADDON_CPPFLAGS += -DNOMINMAX
89 | ADDON_CPPFLAGS += -D_CRT_SECURE_NO_WARNINGS
90 | ADDON_CPPFLAGS += -DWIN32_LEAN_AND_MEAN
91 |
92 | ADDON_LIBS += libs/ossia/lib/vs/ossia.lib
93 | ADDON_LIBS += libs/ossia/lib/vs/ossia_x64.lib
94 |
95 | linuxarmv6l:
96 |
97 |
98 | linuxarmv7l:
99 |
100 | android/armeabi:
101 |
102 | android/armeabi-v7a:
103 |
104 | osx:
105 | ADDON_LIBS += libs/ossia/lib/osx/libossia.a
106 |
107 | ios:
108 |
109 |
--------------------------------------------------------------------------------
/example-singleServer/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This CMakeLists.txt is intended to be used with ofnode CMake build system for openFrameworks
2 | # see https://github.com/ofnode/of
3 |
4 | project(ofxOSCquery-singleServer)
5 | set(APP ${PROJECT_NAME})
6 |
7 | cmake_minimum_required(VERSION 3.1)
8 |
9 | set(OF_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../of/" CACHE PATH "The root directory of ofnode/of project.")
10 | include(${OF_ROOT}/openFrameworks.cmake)
11 |
12 | ofxaddon(ofxOscQuery)
13 | # ofxaddon(ofxOsc)
14 | ofxaddon(ofxGui)
15 |
16 | option(COTIRE "Use cotire" ON)
17 |
18 | set(SOURCES
19 | src/main.cpp
20 | src/ofApp.cpp
21 | src/CirclesRenderer.h
22 | src/CirclesRenderer.cpp
23 | ../src/ofxOssiaTypes.h
24 | ../src/ofxOscQueryServer.h
25 | ../src/ofxOssiaNode.h
26 | ../libs/ossia/include/ossia-cpp98.hpp
27 | )
28 |
29 | add_executable(
30 | ${APP}
31 | MACOSX_BUNDLE
32 | ${SOURCES}
33 | ${OFXADDONS_SOURCES}
34 | )
35 |
36 | target_link_libraries(
37 | ${APP}
38 | ${OPENFRAMEWORKS_LIBRARIES}
39 | )
40 |
41 | if(UNIX AND NOT APPLE)
42 | target_link_libraries(
43 | ${APP}
44 | avahi-client
45 | avahi-common
46 | )
47 | endif()
48 |
49 | set_target_properties(
50 | ${APP} PROPERTIES
51 | MACOSX_BUNDLE_INFO_PLIST
52 | "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
53 | )
54 |
55 | if(CMAKE_BUILD_TYPE MATCHES Debug)
56 | set_target_properties( ${APP} PROPERTIES OUTPUT_NAME "${APP}-Debug")
57 | endif()
58 |
59 | if (CMAKE_CROSSCOMPILING)
60 | set_target_properties( ${APP} PROPERTIES OUTPUT_NAME
61 | "${APP}-${OF_PLATFORM}-${CMAKE_BUILD_TYPE}")
62 | endif()
63 |
64 | if (COTIRE)
65 | cotire(${APP})
66 | endif()
67 |
--------------------------------------------------------------------------------
/example-singleServer/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | cc.openFrameworks.ofapp
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | APPL
15 | CFBundleSignature
16 | ????
17 | CFBundleVersion
18 | 1.0
19 | CFBundleIconFile
20 | ${ICON}
21 |
22 |
23 |
--------------------------------------------------------------------------------
/example-singleServer/addons.make:
--------------------------------------------------------------------------------
1 | ofxGui
2 | ofxOscQuery
3 |
--------------------------------------------------------------------------------
/example-singleServer/bin/data/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 0
4 |
5 | 17.807
6 | 17
7 | 645.491, 480.12
8 | 37, 9, 255, 255
9 | 59459
10 |
11 |
12 | 57.5432
13 | 6
14 | 608.173, 86.3177
15 | 125, 0, 2, 255
16 | 59459
17 |
18 |
19 |
--------------------------------------------------------------------------------
/example-singleServer/client.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | OSCQuery Remote example
6 |
7 |
12 |
63 |
64 |
65 | An HTML example interface using websocket
66 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/example-singleServer/client.maxpat:
--------------------------------------------------------------------------------
1 | {
2 | "patcher" : {
3 | "fileversion" : 1,
4 | "appversion" : {
5 | "major" : 7,
6 | "minor" : 3,
7 | "revision" : 5,
8 | "architecture" : "x64",
9 | "modernui" : 1
10 | }
11 | ,
12 | "rect" : [ 103.0, 79.0, 734.0, 351.0 ],
13 | "bglocked" : 0,
14 | "openinpresentation" : 0,
15 | "default_fontsize" : 12.0,
16 | "default_fontface" : 0,
17 | "default_fontname" : "Arial",
18 | "gridonopen" : 1,
19 | "gridsize" : [ 15.0, 15.0 ],
20 | "gridsnaponopen" : 1,
21 | "objectsnaponopen" : 1,
22 | "statusbarvisible" : 2,
23 | "toolbarvisible" : 1,
24 | "lefttoolbarpinned" : 0,
25 | "toptoolbarpinned" : 0,
26 | "righttoolbarpinned" : 0,
27 | "bottomtoolbarpinned" : 0,
28 | "toolbars_unpinned_last_save" : 0,
29 | "tallnewobj" : 0,
30 | "boxanimatetime" : 200,
31 | "enablehscroll" : 1,
32 | "enablevscroll" : 1,
33 | "devicewidth" : 0.0,
34 | "description" : "",
35 | "digest" : "",
36 | "tags" : "",
37 | "style" : "",
38 | "subpatcher_template" : "",
39 | "boxes" : [ {
40 | "box" : {
41 | "id" : "obj-20",
42 | "maxclass" : "number",
43 | "numinlets" : 1,
44 | "numoutlets" : 2,
45 | "outlettype" : [ "", "bang" ],
46 | "parameter_enable" : 0,
47 | "patching_rect" : [ 454.5, 286.0, 50.0, 22.0 ],
48 | "style" : ""
49 | }
50 |
51 | }
52 | , {
53 | "box" : {
54 | "fontname" : "Arial",
55 | "fontsize" : 12.0,
56 | "id" : "obj-18",
57 | "maxclass" : "newobj",
58 | "numinlets" : 1,
59 | "numoutlets" : 3,
60 | "outlettype" : [ "", "", "" ],
61 | "patching_rect" : [ 337.5, 314.0, 175.0, 22.0 ],
62 | "style" : "",
63 | "text" : "ossia.remote renderer!/number"
64 | }
65 |
66 | }
67 | , {
68 | "box" : {
69 | "fontname" : "Arial",
70 | "fontsize" : 12.0,
71 | "id" : "obj-16",
72 | "maxclass" : "comment",
73 | "numinlets" : 1,
74 | "numoutlets" : 0,
75 | "patching_rect" : [ 179.0, 286.0, 272.0, 20.0 ],
76 | "presentation_rect" : [ 177.0, 285.0, 0.0, 0.0 ],
77 | "style" : "",
78 | "text" : "there is much more available, such as wildcards: "
79 | }
80 |
81 | }
82 | , {
83 | "box" : {
84 | "fontname" : "Arial",
85 | "fontsize" : 12.0,
86 | "id" : "obj-1",
87 | "maxclass" : "newobj",
88 | "numinlets" : 1,
89 | "numoutlets" : 1,
90 | "outlettype" : [ "" ],
91 | "patching_rect" : [ 26.0, 146.0, 71.0, 22.0 ],
92 | "style" : "",
93 | "text" : "ossia.client"
94 | }
95 |
96 | }
97 | , {
98 | "box" : {
99 | "fontname" : "Arial",
100 | "fontsize" : 12.0,
101 | "id" : "obj-2",
102 | "maxclass" : "message",
103 | "numinlets" : 2,
104 | "numoutlets" : 1,
105 | "outlettype" : [ "" ],
106 | "patching_rect" : [ 26.0, 72.0, 106.0, 22.0 ],
107 | "style" : "",
108 | "text" : "connect oscquery"
109 | }
110 |
111 | }
112 | , {
113 | "box" : {
114 | "fontname" : "Arial",
115 | "fontsize" : 12.0,
116 | "id" : "obj-3",
117 | "maxclass" : "newobj",
118 | "numinlets" : 1,
119 | "numoutlets" : 0,
120 | "patching_rect" : [ 26.0, 178.0, 35.0, 22.0 ],
121 | "style" : "",
122 | "text" : "print"
123 | }
124 |
125 | }
126 | , {
127 | "box" : {
128 | "fontname" : "Arial",
129 | "fontsize" : 12.0,
130 | "id" : "obj-4",
131 | "maxclass" : "newobj",
132 | "numinlets" : 1,
133 | "numoutlets" : 1,
134 | "outlettype" : [ "bang" ],
135 | "patching_rect" : [ 26.0, 42.0, 61.0, 22.0 ],
136 | "style" : "",
137 | "text" : "loadbang"
138 | }
139 |
140 | }
141 | , {
142 | "box" : {
143 | "id" : "obj-5",
144 | "maxclass" : "toggle",
145 | "numinlets" : 1,
146 | "numoutlets" : 1,
147 | "outlettype" : [ "int" ],
148 | "parameter_enable" : 0,
149 | "patching_rect" : [ 424.0, 203.0, 15.0, 15.0 ],
150 | "style" : ""
151 | }
152 |
153 | }
154 | , {
155 | "box" : {
156 | "fontname" : "Arial",
157 | "fontsize" : 12.0,
158 | "id" : "obj-6",
159 | "maxclass" : "newobj",
160 | "numinlets" : 1,
161 | "numoutlets" : 3,
162 | "outlettype" : [ "", "", "" ],
163 | "patching_rect" : [ 442.0, 201.0, 118.0, 22.0 ],
164 | "style" : "",
165 | "text" : "ossia.remote vSync"
166 | }
167 |
168 | }
169 | , {
170 | "box" : {
171 | "fontname" : "Arial",
172 | "fontsize" : 12.0,
173 | "id" : "obj-7",
174 | "maxclass" : "message",
175 | "numinlets" : 2,
176 | "numoutlets" : 1,
177 | "outlettype" : [ "" ],
178 | "patching_rect" : [ 60.0, 114.0, 74.0, 22.0 ],
179 | "style" : "",
180 | "text" : "namespace"
181 | }
182 |
183 | }
184 | , {
185 | "box" : {
186 | "fontname" : "Arial",
187 | "fontsize" : 12.0,
188 | "id" : "obj-8",
189 | "maxclass" : "comment",
190 | "numinlets" : 1,
191 | "numoutlets" : 0,
192 | "patching_rect" : [ 144.0, 72.0, 497.0, 20.0 ],
193 | "style" : "",
194 | "text" : "since we are using the default ports we don't need to specify them for the connect message"
195 | }
196 |
197 | }
198 | , {
199 | "box" : {
200 | "fontname" : "Arial",
201 | "fontsize" : 12.0,
202 | "id" : "obj-9",
203 | "maxclass" : "comment",
204 | "numinlets" : 1,
205 | "numoutlets" : 0,
206 | "patching_rect" : [ 168.0, 19.0, 351.0, 20.0 ],
207 | "style" : "",
208 | "text" : "To make this patcher work, install the ossia package"
209 | }
210 |
211 | }
212 | , {
213 | "box" : {
214 | "fontname" : "Arial",
215 | "fontsize" : 12.0,
216 | "id" : "obj-10",
217 | "maxclass" : "comment",
218 | "numinlets" : 1,
219 | "numoutlets" : 0,
220 | "patching_rect" : [ 168.0, 36.0, 527.0, 20.0 ],
221 | "style" : "",
222 | "text" : "Then build and run the example singleserver, then click the connect message or relaod this patch"
223 | }
224 |
225 | }
226 | , {
227 | "box" : {
228 | "fontname" : "Arial",
229 | "fontsize" : 12.0,
230 | "id" : "obj-11",
231 | "maxclass" : "comment",
232 | "numinlets" : 1,
233 | "numoutlets" : 0,
234 | "patching_rect" : [ 144.0, 114.0, 534.0, 20.0 ],
235 | "style" : "",
236 | "text" : "this message dumps the whole namespace of our ofApp, ie. the list of Parameters and their values"
237 | }
238 |
239 | }
240 | , {
241 | "box" : {
242 | "fontname" : "Arial",
243 | "fontsize" : 12.0,
244 | "id" : "obj-12",
245 | "maxclass" : "comment",
246 | "numinlets" : 1,
247 | "numoutlets" : 0,
248 | "patching_rect" : [ 179.0, 170.0, 478.0, 20.0 ],
249 | "style" : "",
250 | "text" : "ossia.remote objects allow to remotely control and monitor the Parameters of our ofApp:"
251 | }
252 |
253 | }
254 | , {
255 | "box" : {
256 | "fontname" : "Arial",
257 | "fontsize" : 12.0,
258 | "id" : "obj-13",
259 | "linecount" : 2,
260 | "maxclass" : "comment",
261 | "numinlets" : 1,
262 | "numoutlets" : 0,
263 | "patching_rect" : [ 179.0, 194.5, 225.0, 33.0 ],
264 | "style" : "",
265 | "text" : "try to toggle the vSync here or from your ofApp, they should always stay in sync"
266 | }
267 |
268 | }
269 | , {
270 | "box" : {
271 | "fontname" : "Arial",
272 | "fontsize" : 12.0,
273 | "id" : "obj-14",
274 | "maxclass" : "newobj",
275 | "numinlets" : 0,
276 | "numoutlets" : 0,
277 | "patcher" : {
278 | "fileversion" : 1,
279 | "appversion" : {
280 | "major" : 7,
281 | "minor" : 3,
282 | "revision" : 5,
283 | "architecture" : "x64",
284 | "modernui" : 1
285 | }
286 | ,
287 | "rect" : [ 105.0, 521.0, 732.0, 326.0 ],
288 | "bglocked" : 0,
289 | "openinpresentation" : 0,
290 | "default_fontsize" : 12.0,
291 | "default_fontface" : 0,
292 | "default_fontname" : "Arial",
293 | "gridonopen" : 1,
294 | "gridsize" : [ 15.0, 15.0 ],
295 | "gridsnaponopen" : 1,
296 | "objectsnaponopen" : 1,
297 | "statusbarvisible" : 2,
298 | "toolbarvisible" : 1,
299 | "lefttoolbarpinned" : 0,
300 | "toptoolbarpinned" : 0,
301 | "righttoolbarpinned" : 0,
302 | "bottomtoolbarpinned" : 0,
303 | "toolbars_unpinned_last_save" : 0,
304 | "tallnewobj" : 0,
305 | "boxanimatetime" : 200,
306 | "enablehscroll" : 1,
307 | "enablevscroll" : 1,
308 | "devicewidth" : 0.0,
309 | "description" : "",
310 | "digest" : "",
311 | "tags" : "",
312 | "style" : "",
313 | "subpatcher_template" : "",
314 | "visible" : 1,
315 | "boxes" : [ {
316 | "box" : {
317 | "bottomvalue" : 768,
318 | "id" : "obj-42",
319 | "maxclass" : "pictslider",
320 | "numinlets" : 2,
321 | "numoutlets" : 2,
322 | "outlettype" : [ "int", "int" ],
323 | "parameter_enable" : 0,
324 | "patching_rect" : [ 225.5, 184.0, 100.0, 100.0 ],
325 | "rightvalue" : 1024,
326 | "style" : "",
327 | "topvalue" : 0
328 | }
329 |
330 | }
331 | , {
332 | "box" : {
333 | "attr" : "saturation",
334 | "fontface" : 0,
335 | "fontname" : "Arial",
336 | "fontsize" : 13.0,
337 | "id" : "obj-41",
338 | "maxclass" : "attrui",
339 | "numinlets" : 1,
340 | "numoutlets" : 1,
341 | "outlettype" : [ "" ],
342 | "patching_rect" : [ 478.0, 194.0, 150.0, 23.0 ],
343 | "style" : ""
344 | }
345 |
346 | }
347 | , {
348 | "box" : {
349 | "id" : "obj-38",
350 | "maxclass" : "swatch",
351 | "numinlets" : 3,
352 | "numoutlets" : 2,
353 | "outlettype" : [ "", "float" ],
354 | "parameter_enable" : 0,
355 | "patching_rect" : [ 441.0, 225.5, 205.0, 67.0 ],
356 | "saturation" : 0.992157
357 | }
358 |
359 | }
360 | , {
361 | "box" : {
362 | "id" : "obj-25",
363 | "maxclass" : "newobj",
364 | "numinlets" : 2,
365 | "numoutlets" : 1,
366 | "outlettype" : [ "" ],
367 | "patching_rect" : [ 225.5, 294.0, 100.0, 22.0 ],
368 | "style" : "",
369 | "text" : "pak 0. 0."
370 | }
371 |
372 | }
373 | , {
374 | "box" : {
375 | "fontname" : "Arial",
376 | "fontsize" : 12.0,
377 | "id" : "obj-1",
378 | "maxclass" : "newobj",
379 | "numinlets" : 1,
380 | "numoutlets" : 1,
381 | "outlettype" : [ "" ],
382 | "patching_rect" : [ 50.0, 116.0, 119.0, 22.0 ],
383 | "style" : "",
384 | "text" : "ossia.view renderer"
385 | }
386 |
387 | }
388 | , {
389 | "box" : {
390 | "fontname" : "Arial",
391 | "fontsize" : 12.0,
392 | "id" : "obj-2",
393 | "maxclass" : "newobj",
394 | "numinlets" : 1,
395 | "numoutlets" : 3,
396 | "outlettype" : [ "", "", "" ],
397 | "patching_rect" : [ 45.0, 189.0, 119.0, 22.0 ],
398 | "style" : "",
399 | "text" : "ossia.remote size"
400 | }
401 |
402 | }
403 | , {
404 | "box" : {
405 | "fontsize" : 12.0,
406 | "format" : 6,
407 | "id" : "obj-3",
408 | "maxclass" : "flonum",
409 | "numinlets" : 1,
410 | "numoutlets" : 2,
411 | "outlettype" : [ "", "bang" ],
412 | "parameter_enable" : 0,
413 | "patching_rect" : [ 61.0, 168.0, 50.0, 22.0 ],
414 | "style" : "",
415 | "triscale" : 0.9
416 | }
417 |
418 | }
419 | , {
420 | "box" : {
421 | "fontsize" : 12.0,
422 | "id" : "obj-4",
423 | "maxclass" : "number",
424 | "numinlets" : 1,
425 | "numoutlets" : 2,
426 | "outlettype" : [ "", "bang" ],
427 | "parameter_enable" : 0,
428 | "patching_rect" : [ 58.0, 236.0, 50.0, 22.0 ],
429 | "style" : "",
430 | "triscale" : 0.9
431 | }
432 |
433 | }
434 | , {
435 | "box" : {
436 | "fontname" : "Arial",
437 | "fontsize" : 12.0,
438 | "id" : "obj-5",
439 | "maxclass" : "newobj",
440 | "numinlets" : 1,
441 | "numoutlets" : 3,
442 | "outlettype" : [ "", "", "" ],
443 | "patching_rect" : [ 44.0, 259.0, 124.0, 22.0 ],
444 | "style" : "",
445 | "text" : "ossia.remote number"
446 | }
447 |
448 | }
449 | , {
450 | "box" : {
451 | "fontname" : "Arial",
452 | "fontsize" : 12.0,
453 | "id" : "obj-10",
454 | "maxclass" : "newobj",
455 | "numinlets" : 1,
456 | "numoutlets" : 3,
457 | "outlettype" : [ "", "", "" ],
458 | "patching_rect" : [ 225.5, 155.0, 125.0, 22.0 ],
459 | "style" : "",
460 | "text" : "ossia.remote position"
461 | }
462 |
463 | }
464 | , {
465 | "box" : {
466 | "fontname" : "Arial",
467 | "fontsize" : 12.0,
468 | "id" : "obj-17",
469 | "maxclass" : "newobj",
470 | "numinlets" : 1,
471 | "numoutlets" : 3,
472 | "outlettype" : [ "", "", "" ],
473 | "patching_rect" : [ 441.0, 165.0, 110.0, 22.0 ],
474 | "style" : "",
475 | "text" : "ossia.remote color"
476 | }
477 |
478 | }
479 | , {
480 | "box" : {
481 | "fontname" : "Arial",
482 | "fontsize" : 12.0,
483 | "id" : "obj-18",
484 | "maxclass" : "message",
485 | "numinlets" : 2,
486 | "numoutlets" : 1,
487 | "outlettype" : [ "" ],
488 | "patching_rect" : [ 50.0, 31.0, 119.0, 22.0 ],
489 | "style" : "",
490 | "text" : "address renderer.1"
491 | }
492 |
493 | }
494 | , {
495 | "box" : {
496 | "fontname" : "Arial",
497 | "fontsize" : 12.0,
498 | "id" : "obj-19",
499 | "maxclass" : "message",
500 | "numinlets" : 2,
501 | "numoutlets" : 1,
502 | "outlettype" : [ "" ],
503 | "patching_rect" : [ 78.0, 82.0, 118.0, 22.0 ],
504 | "style" : "",
505 | "text" : "address renderer"
506 | }
507 |
508 | }
509 | , {
510 | "box" : {
511 | "fontname" : "Arial",
512 | "fontsize" : 12.0,
513 | "id" : "obj-20",
514 | "maxclass" : "comment",
515 | "numinlets" : 1,
516 | "numoutlets" : 0,
517 | "patching_rect" : [ 208.0, 82.0, 362.0, 20.0 ],
518 | "style" : "",
519 | "text" : "of course, we can switch back to the original view set as argument"
520 | }
521 |
522 | }
523 | , {
524 | "box" : {
525 | "fontname" : "Arial",
526 | "fontsize" : 12.0,
527 | "id" : "obj-21",
528 | "maxclass" : "comment",
529 | "numinlets" : 1,
530 | "numoutlets" : 0,
531 | "patching_rect" : [ 209.0, 114.0, 447.0, 20.0 ],
532 | "style" : "",
533 | "text" : "when a valid address is set as an argument to ossia.view, it will bind to it at startup"
534 | }
535 |
536 | }
537 | , {
538 | "box" : {
539 | "fontname" : "Arial",
540 | "fontsize" : 12.0,
541 | "id" : "obj-22",
542 | "linecount" : 3,
543 | "maxclass" : "comment",
544 | "numinlets" : 1,
545 | "numoutlets" : 0,
546 | "patching_rect" : [ 209.0, 18.5, 401.0, 47.0 ],
547 | "style" : "",
548 | "text" : "we can \"bind\" the view to the adress of another similar object, \nhere for instance renderer.1 \nthis will update all values from ossia.remotes and allow us to control them"
549 | }
550 |
551 | }
552 | ],
553 | "lines" : [ {
554 | "patchline" : {
555 | "destination" : [ "obj-42", 0 ],
556 | "source" : [ "obj-10", 0 ]
557 | }
558 |
559 | }
560 | , {
561 | "patchline" : {
562 | "destination" : [ "obj-38", 0 ],
563 | "source" : [ "obj-17", 0 ]
564 | }
565 |
566 | }
567 | , {
568 | "patchline" : {
569 | "destination" : [ "obj-1", 0 ],
570 | "source" : [ "obj-18", 0 ]
571 | }
572 |
573 | }
574 | , {
575 | "patchline" : {
576 | "destination" : [ "obj-1", 0 ],
577 | "source" : [ "obj-19", 0 ]
578 | }
579 |
580 | }
581 | , {
582 | "patchline" : {
583 | "destination" : [ "obj-3", 0 ],
584 | "source" : [ "obj-2", 0 ]
585 | }
586 |
587 | }
588 | , {
589 | "patchline" : {
590 | "destination" : [ "obj-10", 0 ],
591 | "midpoints" : [ 235.0, 321.0, 202.0, 321.0, 202.0, 144.0, 235.0, 144.0 ],
592 | "source" : [ "obj-25", 0 ]
593 | }
594 |
595 | }
596 | , {
597 | "patchline" : {
598 | "destination" : [ "obj-2", 0 ],
599 | "source" : [ "obj-3", 0 ]
600 | }
601 |
602 | }
603 | , {
604 | "patchline" : {
605 | "destination" : [ "obj-17", 0 ],
606 | "midpoints" : [ 450.5, 303.0, 427.0, 303.0, 427.0, 160.0, 450.5, 160.0 ],
607 | "source" : [ "obj-38", 0 ]
608 | }
609 |
610 | }
611 | , {
612 | "patchline" : {
613 | "destination" : [ "obj-5", 0 ],
614 | "source" : [ "obj-4", 0 ]
615 | }
616 |
617 | }
618 | , {
619 | "patchline" : {
620 | "destination" : [ "obj-38", 0 ],
621 | "source" : [ "obj-41", 0 ]
622 | }
623 |
624 | }
625 | , {
626 | "patchline" : {
627 | "destination" : [ "obj-25", 1 ],
628 | "source" : [ "obj-42", 1 ]
629 | }
630 |
631 | }
632 | , {
633 | "patchline" : {
634 | "destination" : [ "obj-25", 0 ],
635 | "source" : [ "obj-42", 0 ]
636 | }
637 |
638 | }
639 | , {
640 | "patchline" : {
641 | "destination" : [ "obj-4", 0 ],
642 | "source" : [ "obj-5", 0 ]
643 | }
644 |
645 | }
646 | ]
647 | }
648 | ,
649 | "patching_rect" : [ 492.0, 253.5, 59.0, 22.0 ],
650 | "saved_object_attributes" : {
651 | "description" : "",
652 | "digest" : "",
653 | "globalpatchername" : "",
654 | "style" : "",
655 | "tags" : ""
656 | }
657 | ,
658 | "style" : "",
659 | "text" : "p view"
660 | }
661 |
662 | }
663 | , {
664 | "box" : {
665 | "fontname" : "Arial",
666 | "fontsize" : 12.0,
667 | "id" : "obj-15",
668 | "linecount" : 2,
669 | "maxclass" : "comment",
670 | "numinlets" : 1,
671 | "numoutlets" : 0,
672 | "patching_rect" : [ 179.0, 247.0, 310.0, 33.0 ],
673 | "style" : "",
674 | "text" : "when we have several instances of the same object we can control them with ossia.views, to see that, open:"
675 | }
676 |
677 | }
678 | ],
679 | "lines" : [ {
680 | "patchline" : {
681 | "destination" : [ "obj-3", 0 ],
682 | "source" : [ "obj-1", 0 ]
683 | }
684 |
685 | }
686 | , {
687 | "patchline" : {
688 | "destination" : [ "obj-20", 0 ],
689 | "midpoints" : [ 347.0, 339.0, 518.5, 339.0, 518.5, 282.0, 464.0, 282.0 ],
690 | "source" : [ "obj-18", 0 ]
691 | }
692 |
693 | }
694 | , {
695 | "patchline" : {
696 | "destination" : [ "obj-1", 0 ],
697 | "source" : [ "obj-2", 0 ]
698 | }
699 |
700 | }
701 | , {
702 | "patchline" : {
703 | "destination" : [ "obj-18", 0 ],
704 | "midpoints" : [ 464.0, 310.0, 347.0, 310.0 ],
705 | "source" : [ "obj-20", 0 ]
706 | }
707 |
708 | }
709 | , {
710 | "patchline" : {
711 | "destination" : [ "obj-2", 0 ],
712 | "source" : [ "obj-4", 0 ]
713 | }
714 |
715 | }
716 | , {
717 | "patchline" : {
718 | "destination" : [ "obj-6", 0 ],
719 | "source" : [ "obj-5", 0 ]
720 | }
721 |
722 | }
723 | , {
724 | "patchline" : {
725 | "destination" : [ "obj-5", 0 ],
726 | "source" : [ "obj-6", 0 ]
727 | }
728 |
729 | }
730 | , {
731 | "patchline" : {
732 | "destination" : [ "obj-1", 0 ],
733 | "source" : [ "obj-7", 0 ]
734 | }
735 |
736 | }
737 | ],
738 | "dependency_cache" : [ {
739 | "name" : "ossia.remote.mxo",
740 | "type" : "iLaX"
741 | }
742 | , {
743 | "name" : "ossia.view.mxo",
744 | "type" : "iLaX"
745 | }
746 | , {
747 | "name" : "ossia.client.mxo",
748 | "type" : "iLaX"
749 | }
750 | ],
751 | "autosave" : 0
752 | }
753 |
754 | }
755 |
--------------------------------------------------------------------------------
/example-singleServer/client.pd:
--------------------------------------------------------------------------------
1 | #N canvas 111 95 778 310 10;
2 | #X obj 29 146 ossia.client;
3 | #X msg 28 82 connect oscquery;
4 | #X obj 29 168 print;
5 | #X obj 28 61 loadbang;
6 | #X obj 493 203 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
7 | 1;
8 | #X obj 511 201 ossia.remote vSync;
9 | #X msg 63 114 namespace;
10 | #X text 143 84 since we are using the default ports we don't need to
11 | specify them for the connect message, f 93;
12 | #X text 167 19 To make this patcher work \, install the ossia package
13 | from deken, f 93;
14 | #X text 167 36 Then build and run the example singleserver \, then
15 | click the connect message or relaod this patch, f 96;
16 | #X text 137 114 this message dumps the whole namespace of our ofApp
17 | \, ie. the list of Parameters and their values, f 102;
18 | #X text 156 157 ossia.remote objects allow to remotely control and
19 | monitor the Parameters of our ofApp:, f 102;
20 | #X text 178 195 try to toggle the vSync here or from your ofApp \,
21 | they should always stay in sync, f 51;
22 | #N canvas 107 428 782 295 view 1;
23 | #X obj 45 89 ossia.view renderer;
24 | #X obj 41 167 ossia.remote size;
25 | #X floatatom 57 146 5 0 0 0 - - -, f 5;
26 | #X floatatom 54 214 5 0 0 0 - - -, f 5;
27 | #X obj 40 237 ossia.remote number;
28 | #X floatatom 268 256 5 0 0 0 - - -, f 5;
29 | #X floatatom 311 255 5 0 0 0 - - -, f 5;
30 | #N canvas 0 151 450 300 set 0;
31 | #X floatatom 161 105 5 0 0 0 - - -, f 5;
32 | #X floatatom 195 105 5 0 0 0 - - -, f 5;
33 | #X obj 195 133 t b f;
34 | #X obj 161 185 outlet;
35 | #X obj 161 163 pack 0 0;
36 | #X connect 0 0 4 0;
37 | #X connect 1 0 2 0;
38 | #X connect 2 0 0 0;
39 | #X connect 2 1 4 1;
40 | #X connect 4 0 3 0;
41 | #X coords 0 -1 1 1 130 25 1 100 100;
42 | #X restore 226 153 pd set;
43 | #N canvas 0 151 450 300 set 0;
44 | #X obj 161 163 pack 0 0 0 0;
45 | #X floatatom 161 105 5 0 0 0 - - -, f 5;
46 | #X floatatom 201 105 5 0 0 0 - - -, f 5;
47 | #X floatatom 241 105 5 0 0 0 - - -, f 5;
48 | #X floatatom 281 105 5 0 0 0 - - -, f 5;
49 | #X obj 281 133 t b f;
50 | #X obj 241 133 t b f;
51 | #X obj 201 133 t b f;
52 | #X obj 161 185 outlet;
53 | #X connect 0 0 8 0;
54 | #X connect 1 0 0 0;
55 | #X connect 2 0 7 0;
56 | #X connect 3 0 6 0;
57 | #X connect 4 0 5 0;
58 | #X connect 5 0 1 0;
59 | #X connect 5 1 0 3;
60 | #X connect 6 0 1 0;
61 | #X connect 6 1 0 2;
62 | #X connect 7 0 1 0;
63 | #X connect 7 1 0 1;
64 | #X coords 0 -1 1 1 220 25 1 100 100;
65 | #X restore 434 156 pd set;
66 | #X obj 227 186 ossia.remote position;
67 | #X floatatom 457 263 5 0 0 0 - - -, f 5;
68 | #X floatatom 500 262 5 0 0 0 - - -, f 5;
69 | #X floatatom 543 262 5 0 0 0 - - -, f 5;
70 | #X floatatom 586 263 5 0 0 0 - - -, f 5;
71 | #X obj 459 222 unpack set 0 0 0 0, f 22;
72 | #X obj 228 211 unpack set 0 0, f 15;
73 | #X obj 436 191 ossia.remote color;
74 | #X msg 44 25 address renderer.1;
75 | #X msg 74 60 address renderer;
76 | #X text 204 60 of course \, we can switch back to the original view
77 | set as argument, f 90;
78 | #X text 204 87 when a valid address is set as an argument to ossia.view
79 | \, it will bind to it at startup, f 90;
80 | #X text 203 11 we can "bind" the view to the adress of another similar
81 | object \, here for instance renderer.1 this will update all values
82 | from ossia.remotes and allow us to control them, f 90;
83 | #X connect 1 0 2 0;
84 | #X connect 2 0 1 0;
85 | #X connect 3 0 4 0;
86 | #X connect 4 0 3 0;
87 | #X connect 7 0 9 0;
88 | #X connect 8 0 16 0;
89 | #X connect 9 0 15 0;
90 | #X connect 14 1 10 0;
91 | #X connect 14 2 11 0;
92 | #X connect 14 3 12 0;
93 | #X connect 14 4 13 0;
94 | #X connect 15 1 5 0;
95 | #X connect 15 2 6 0;
96 | #X connect 16 0 14 0;
97 | #X connect 17 0 0 0;
98 | #X connect 18 0 0 0;
99 | #X restore 503 258 pd view;
100 | #X text 178 247 when we have several instances of the same object we
101 | can control them with ossia.views \, to see that \, open:, f 53;
102 | #X connect 0 0 2 0;
103 | #X connect 1 0 0 0;
104 | #X connect 3 0 1 0;
105 | #X connect 4 0 5 0;
106 | #X connect 5 0 4 0;
107 | #X connect 6 0 0 0;
108 |
--------------------------------------------------------------------------------
/example-singleServer/src/CirclesRenderer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * CirclesRenderer.cpp
3 | *
4 | * Created on: 11/07/2012
5 | * Author: arturo
6 | */
7 |
8 | #include "CirclesRenderer.h"
9 |
10 | CirclesRenderer::CirclesRenderer() {
11 | // TODO Auto-generated constructor stub
12 |
13 | }
14 |
15 |
16 | void CirclesRenderer::setup(string name){
17 | parameters.setName(name);
18 | parameters.add(size.set("size",10,0,100));
19 | parameters.add(number.set("number",2,1,20));
20 | parameters.add(position.set("position",ofVec2f(ofGetWidth()*.5,ofGetHeight()*.5),ofVec2f(0,0),ofVec2f(ofGetWidth(),ofGetHeight())));
21 |
22 | color.set("color",ofColor(127),ofColor(0,0),ofColor(255));
23 |
24 | parameters.add(color);
25 | parameters.add(frameNum.set("frameNum",0));
26 | }
27 |
28 | void CirclesRenderer::draw(){
29 | // this will work only inside CirclesRenderer class
30 | // since it's a readonly property
31 | frameNum ++;
32 | ofSetColor(color);
33 | for(int i=0;i
18 | class ofCirclesRendererParam: public ofReadOnlyParameter{
19 | friend class CirclesRenderer;
20 | };
21 |
22 | class CirclesRenderer {
23 | public:
24 | CirclesRenderer();
25 |
26 | void setup(string name);
27 | void draw();
28 |
29 | ofParameterGroup parameters;
30 | ofParameter size;
31 | ofParameter number;
32 | ofParameter position;
33 |
34 | ofParameter color;
35 |
36 | ofCirclesRendererParam frameNum;
37 | };
38 |
39 | #endif /* CIRCLESRENDERER_H_ */
40 |
--------------------------------------------------------------------------------
/example-singleServer/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "ofMain.h"
2 | #include "ofApp.h"
3 |
4 | //========================================================================
5 | int main( ){
6 |
7 | ofSetupOpenGL(1024,768, OF_WINDOW); // <-------- setup the GL context
8 |
9 | // this kicks off the running of my app
10 | // can be OF_WINDOW or OF_FULLSCREEN
11 | // pass in width and height too:
12 | ofRunApp( new ofApp());
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/example-singleServer/src/ofApp.cpp:
--------------------------------------------------------------------------------
1 | #include "ofApp.h"
2 |
3 | //--------------------------------------------------------------
4 | void ofApp::setup(){
5 | renderer1.setup("renderer");
6 | renderer2.setup("renderer");
7 | // Note that both Groups are named the same, in order to demonstrate
8 | // ossia's behavior in the case of duplicated nodes (adds .1 to the name)
9 |
10 | //parameters.setName("myOfxOscQueryApp"); // we remove this one so we get the default name
11 | // uncommenting it will name both the ofParameterGroup and the device with the provided string
12 | parameters.add(vSync.set("vSync",true));
13 | vSync.addListener(this, &ofApp::vSyncChanged);
14 | parameters.add(renderer1.parameters);
15 | parameters.add(renderer2.parameters);
16 |
17 | gui.setup(parameters);
18 |
19 | // ^ All this above is just the same that we have in of's gui/ParameterGroupExample
20 | // i.e. one does not have to change their ofApp structure to use ofxOscQuery,
21 | // as long as it uses ofParameters and ofParameterGroups
22 | //*********************************************************************************//
23 |
24 |
25 |
26 | //******************************************************************************************//
27 | // This is where we setup our OSCQuery server: //
28 | // NB this is the only change from of's gui/ParameterGroupExample //
29 | //
30 | oscQuery.setup(parameters); //
31 | //
32 | // i.e. this will attach our OSCquery oscQuery to the 'parameters' ParameterGroup //
33 | // scan all sub-ParameterGroups and children Parameters recursively //
34 | // and expose the whole thing to default ports 1234 for OSC and 4567 for Websocket //
35 | // //
36 | // Should we want to set specific ports and name, we could add them as arguments, e.g.: //
37 | //
38 | //oscQuery.setup(parameters, 4321, 8765, "ofxOSCQuery"); //
39 | //
40 | // All network communication (sending, receving, listening, queries and replies) //
41 | // will then be managed by the internal implementation of libossia //
42 | //******************************************************************************************//
43 |
44 |
45 |
46 | //*********************************************************************************//
47 | // Some extra OSCQuery/ossia-specific attributes can be set later on
48 | // They requires that we find the node for which we want to set those attributes
49 | // This can be achieved with the findNode method, which accepts as argument:
50 | // - the object name ofParameter(Group) to which the ossia node is attached
51 | // - the OSC path of the node we want to access
52 | // Then we have just to use the appropriate set(Attribute) methods
53 | //
54 |
55 | // As they return a ofxOssiaNode&, the set(Attribute) methods
56 | // can be "cascaded" as demonstrated below:
57 | oscQuery[renderer2.position].setDescription("A circle renderer position")
58 | .setTags({"a little tag", "some other tag", "another tag"})
59 | .setRangeMin(ofVec2f{2,10})
60 | .setClipMode("both");
61 |
62 |
63 | // Bound values (aka Min or Max can be set, and we can decide what happens at the bounds:
64 | oscQuery[renderer2.number].setRangeMin(5).setRangeMax(15)
65 | .setClipMode("fold");
66 | // possible values are: none, low, high, both, wrap and fold,
67 | // see: https://ossia.github.io/?cpp--98#bounding-mode
68 |
69 | // Retrieve the value of the minimum bound for a node
70 | ofLogNotice() << "Renderer2's number's min: " << oscQuery[renderer2.number].getRangeMin();
71 | // Notice that we need to pass the node's type as a template argument to getMin()
72 |
73 | // We can also provide a set of accepted values:
74 | oscQuery[renderer1.number].setRangeValues(std::vector{1,3,5,7,9,11,13,15,17,19})
75 | .setClipMode("both");
76 | // and restrict the parameter's value to those with the CLIP boundmode
77 |
78 | // Add a description of this node
79 | oscQuery["/renderer/color/"].setDescription("El Color maravilloso!!");
80 |
81 | // The cannonnical way to set the unit for a 2D position
82 | oscQuery["/renderer/position"].setUnit("position.cart2D");
83 | // A shorthand way to do the same:
84 | oscQuery[renderer2.position].setUnit("point2d");
85 | // Orher units are available:
86 | oscQuery[renderer1.size].setUnit("distance.m");
87 | // For a list of all available units and their shorthand "nicknmames", see:
88 | // http://ossia.github.io/libossia/html/classopp_1_1node.html#a5b06de6a111af5996d4216ee8c8392c1
89 |
90 |
91 |
92 | //*********************************************************************************//
93 |
94 |
95 |
96 | //*********************************************************************************//
97 | // v The rest below is the usual stuff from the example
98 |
99 |
100 | gui.loadFromFile("settings.xml");
101 |
102 | font.load( OF_TTF_SANS,9,true,true);
103 | ofEnableAlphaBlending();
104 | }
105 |
106 | void ofApp::vSyncChanged(bool & vSync){
107 | ofSetVerticalSync(vSync);
108 | ofLogNotice() << "vSync changed: " << vSync;
109 | }
110 |
111 |
112 | //--------------------------------------------------------------
113 | void ofApp::update(){
114 | // frameNum is a readonly parameter so this will fail to compile
115 | // unless we are inside the CirclesRenderer class
116 | // renderer.frameNum = 5;
117 | }
118 |
119 | //--------------------------------------------------------------
120 | void ofApp::draw(){
121 | ofBackgroundGradient(ofColor::white, ofColor::gray);
122 | renderer1.draw();
123 | renderer2.draw();
124 | ofSetColor(255);
125 | gui.draw();
126 | font.drawString("frame: " + ofToString(renderer1.frameNum),ofGetWidth()-150,20);
127 | font.drawString("fps: " + ofToString((int)ofGetFrameRate()),ofGetWidth()-150,40);
128 | }
129 |
130 | void ofApp::exit(){
131 |
132 | }
133 | //--------------------------------------------------------------
134 | void ofApp::keyPressed(int key){
135 | if(key=='s'){
136 | ofSerialize(settings, parameters);
137 | settings.save("settings.xml");
138 | }
139 | if(key=='l'){
140 | settings.load("settings.xml");
141 | ofDeserialize(settings, parameters);
142 | }
143 | if(key=='o'){
144 | cout << renderer1.parameters;
145 | cout << renderer2.parameters;
146 | }
147 | if(key=='r'){
148 | renderer1.color = ofColor(127);
149 | renderer2.color = ofColor(127);
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/example-singleServer/src/ofApp.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ofMain.h"
4 | #include "ofxGui.h"
5 | #include "ofxOscQueryServer.h"
6 | #include "CirclesRenderer.h"
7 |
8 | class ofApp : public ofBaseApp{
9 |
10 | public:
11 | void setup();
12 | void update();
13 | void draw();
14 | void exit();
15 |
16 | void keyPressed (int key);
17 |
18 | void vSyncChanged(bool & vSync);
19 |
20 | ofxPanel gui;
21 | ofParameter vSync;
22 | ofParameterGroup parameters;
23 | ofXml settings;
24 | CirclesRenderer renderer1,renderer2;
25 | ofTrueTypeFont font;
26 |
27 | //***********************************************************//
28 | // This is where we declare our OSCQuery Server: //
29 | //
30 | ofxOscQueryServer oscQuery; //
31 | //
32 | // Here, we use the default name and ports, but we could //
33 | // specify them (see example-twoservers for that) //
34 | //***********************************************************//
35 | };
36 |
--------------------------------------------------------------------------------
/example-twoServers/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This CMakeLists.txt is intended to be used with ofnode CMake build system for openFrameworks
2 | # see https://github.com/ofnode/of
3 |
4 | project(ofxOSCquery-twoServers)
5 | set(APP ${PROJECT_NAME})
6 |
7 | cmake_minimum_required(VERSION 3.1)
8 |
9 | set(OF_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../of/" CACHE PATH "The root directory of ofnode/of project.")
10 | include(${OF_ROOT}/openFrameworks.cmake)
11 |
12 | ofxaddon(ofxOscQuery)
13 | # ofxaddon(ofxOsc)
14 | ofxaddon(ofxGui)
15 |
16 | option(COTIRE "Use cotire" ON)
17 |
18 | set(SOURCES
19 | src/main.cpp
20 | src/ofApp.cpp
21 | src/CirclesRenderer.h
22 | src/CirclesRenderer.cpp
23 | ../src/ofxOssiaTypes.h
24 | ../src/ofxOscQueryServer.h
25 | ../src/ofxOssiaNode.h
26 | ../libs/ossia/include/ossia-cpp98.hpp
27 | )
28 |
29 | add_executable(
30 | ${APP}
31 | MACOSX_BUNDLE
32 | ${SOURCES}
33 | ${OFXADDONS_SOURCES}
34 | )
35 |
36 | target_link_libraries(
37 | ${APP}
38 | ${OPENFRAMEWORKS_LIBRARIES}
39 | )
40 |
41 | if(UNIX AND NOT APPLE)
42 | target_link_libraries(
43 | ${APP}
44 | avahi-client
45 | avahi-common
46 | )
47 | endif()
48 |
49 | set_target_properties(
50 | ${APP} PROPERTIES
51 | MACOSX_BUNDLE_INFO_PLIST
52 | "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
53 | )
54 |
55 | if(CMAKE_BUILD_TYPE MATCHES Debug)
56 | set_target_properties( ${APP} PROPERTIES OUTPUT_NAME "${APP}-Debug")
57 | endif()
58 |
59 | if (CMAKE_CROSSCOMPILING)
60 | set_target_properties( ${APP} PROPERTIES OUTPUT_NAME
61 | "${APP}-${OF_PLATFORM}-${CMAKE_BUILD_TYPE}")
62 | endif()
63 |
64 | if (COTIRE)
65 | cotire(${APP})
66 | endif()
67 |
--------------------------------------------------------------------------------
/example-twoServers/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | cc.openFrameworks.ofapp
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | APPL
15 | CFBundleSignature
16 | ????
17 | CFBundleVersion
18 | 1.0
19 | CFBundleIconFile
20 | ${ICON}
21 |
22 |
23 |
--------------------------------------------------------------------------------
/example-twoServers/addons.make:
--------------------------------------------------------------------------------
1 | ofxGui
2 | ofxOscQuery
3 |
--------------------------------------------------------------------------------
/example-twoServers/bin/data/settings.xml:
--------------------------------------------------------------------------------
1 |
2 | 1
3 |
4 | 10
5 | 2
6 | 512, 384
7 | 127, 127, 127, 255
8 | 0
9 |
10 |
11 | 10
12 | 2
13 | 512, 384
14 | 127, 127, 127, 255
15 | 0
16 |
17 |
18 |
--------------------------------------------------------------------------------
/example-twoServers/src/CirclesRenderer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * CirclesRenderer.cpp
3 | *
4 | * Created on: 11/07/2012
5 | * Author: arturo
6 | */
7 |
8 | #include "CirclesRenderer.h"
9 |
10 | CirclesRenderer::CirclesRenderer() {
11 | // TODO Auto-generated constructor stub
12 |
13 | }
14 |
15 |
16 | void CirclesRenderer::setup(string name){
17 | parameters.setName(name);
18 | parameters.add(size.set("size",10,0,100));
19 | parameters.add(number.set("number",2,1,20));
20 | parameters.add(position.set("position",ofVec2f(ofGetWidth()*.5,ofGetHeight()*.5),ofVec2f(0,0),ofVec2f(ofGetWidth(),ofGetHeight())));
21 |
22 | color.set("color",ofColor(127),ofColor(0,0),ofColor(255));
23 |
24 | parameters.add(color);
25 | parameters.add(frameNum.set("frameNum",0));
26 | }
27 |
28 | void CirclesRenderer::draw(){
29 | // this will work only inside CirclesRenderer class
30 | // since it's a readonly property
31 | frameNum ++;
32 | ofSetColor(color);
33 | for(int i=0;i
18 | class ofCirclesRendererParam: public ofReadOnlyParameter{
19 | friend class CirclesRenderer;
20 | };
21 |
22 | class CirclesRenderer {
23 | public:
24 | CirclesRenderer();
25 |
26 | void setup(string name);
27 | void draw();
28 |
29 | ofParameterGroup parameters;
30 | ofParameter size;
31 | ofParameter number;
32 | ofParameter position;
33 |
34 | ofParameter color;
35 |
36 | ofCirclesRendererParam frameNum;
37 | };
38 |
39 | #endif /* CIRCLESRENDERER_H_ */
40 |
--------------------------------------------------------------------------------
/example-twoServers/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "ofMain.h"
2 | #include "ofApp.h"
3 |
4 | //========================================================================
5 | int main( ){
6 |
7 | ofSetupOpenGL(1024,768, OF_WINDOW); // <-------- setup the GL context
8 |
9 | // this kicks off the running of my app
10 | // can be OF_WINDOW or OF_FULLSCREEN
11 | // pass in width and height too:
12 | ofRunApp( new ofApp());
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/example-twoServers/src/ofApp.cpp:
--------------------------------------------------------------------------------
1 | #include "ofApp.h"
2 |
3 | //--------------------------------------------------------------
4 | void ofApp::setup(){
5 | renderer1.setup("renderer1");
6 | renderer2.setup("renderer2");
7 |
8 | parameters.setName("settings");
9 | parameters.add(vSync.set("vSync",true));
10 | parameters.add(renderer1.parameters);
11 | parameters.add(renderer2.parameters);
12 |
13 | gui.setup(parameters);
14 |
15 | std::cout << "group names: " << renderer1.parameters.getName() << " / " << renderer2.parameters.getName() << std::endl;
16 |
17 |
18 | //*************************************************//
19 | // This is where we setup our OSCQuery Servers: //
20 | server1.setup(renderer1.parameters);
21 | server2.setup(renderer2.parameters);
22 | // by attaching them to ofParaemeterGroups
23 | //*************************************************//
24 | // NB this is the only change with of's ParameterGroupExample
25 | //
26 |
27 | cout << server1["/position/"].getName();
28 | cout << server1["/position"].getName();
29 | cout << server2["/color"].getName();
30 |
31 |
32 |
33 | gui.loadFromFile("settings.xml");
34 |
35 | font.load( OF_TTF_SANS,9,true,true);
36 | ofEnableAlphaBlending();
37 | }
38 |
39 | void ofApp::vSyncChanged(bool & vSync){
40 | ofSetVerticalSync(vSync);
41 | }
42 |
43 |
44 | //--------------------------------------------------------------
45 | void ofApp::update(){
46 | // frameNum is a readonly parameter so this will fail to compile
47 | // unless we are inside the CirclesRenderer class
48 | // renderer.frameNum = 5;
49 | }
50 |
51 | //--------------------------------------------------------------
52 | void ofApp::draw(){
53 | ofBackgroundGradient(ofColor::white, ofColor::gray);
54 | renderer1.draw();
55 | renderer2.draw();
56 | ofSetColor(255);
57 | gui.draw();
58 | font.drawString("frame: " + ofToString(renderer1.frameNum),ofGetWidth()-150,20);
59 | font.drawString("fps: " + ofToString((int)ofGetFrameRate()),ofGetWidth()-150,40);
60 | }
61 |
62 | //--------------------------------------------------------------
63 | void ofApp::keyPressed(int key){
64 | if(key=='s'){
65 | ofSerialize(settings, parameters);
66 | settings.save("settings.xml");
67 | }
68 | if(key=='l'){
69 | settings.load("settings.xml");
70 | ofSerialize(settings, parameters);
71 | }
72 | if(key=='o'){
73 | cout << renderer1.parameters;
74 | cout << renderer2.parameters;
75 | }
76 | if(key=='r'){
77 | renderer1.color = ofColor(127);
78 | renderer2.color = ofColor(127);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/example-twoServers/src/ofApp.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ofMain.h"
4 | #include "ofxGui.h"
5 | #include "ofxOscQueryServer.h"
6 | #include "CirclesRenderer.h"
7 |
8 | class ofApp : public ofBaseApp{
9 |
10 | public:
11 | void setup();
12 | void update();
13 | void draw();
14 |
15 | void keyPressed (int key);
16 |
17 | void vSyncChanged(bool & vSync);
18 |
19 | ofxPanel gui;
20 | ofParameter vSync;
21 | ofParameterGroup parameters;
22 | ofXml settings;
23 | CirclesRenderer renderer1,renderer2;
24 | ofTrueTypeFont font;
25 |
26 | //*****************************************************//
27 | // This is where we declare our OSCQuery Servers //
28 |
29 | ofxOscQueryServer server1{1221, 4617};
30 | ofxOscQueryServer server2{1222, 4616};
31 |
32 | // Notice that we need to declare ports to our servers //
33 | // or they would get the same default ports //
34 | // and would conflict with each other. //
35 | // We will attach them to ofParameterGroups in ofApp.cpp
36 | //*****************************************************//
37 | };
38 |
--------------------------------------------------------------------------------
/extra/ReadMe.md:
--------------------------------------------------------------------------------
1 | This is a demo score (to be used with https://github.com/OSSIA/score) controlling both *example-singleServer* and *example-twoServers* ofApps.
2 |
3 | Just open the file and press spacebar to play.
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | The code in this repository is available under the [MIT License](https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license).
2 |
3 | Copyright (c) [09/01/2018] [Pascal Baltazar]
4 |
5 | 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:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | 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.
--------------------------------------------------------------------------------
/src/ofxOscQueryServer.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // ofxOssiaServer.cpp
3 | // ofxOSSIA
4 | //
5 | // Created by Pascal Baltazar in 04/2018
6 | //
7 | //
8 |
9 | #include "ofxOscQueryServer.h"
10 |
11 | void ofxOscQueryServer::setup(ofParameterGroup& group, int localportOSC, int localPortWS, std::string localname)
12 | {
13 | if (localportOSC != DEFAULT_OSC) OSCport = localportOSC;
14 | if (localPortWS != DEFAULT_WS) WSport = localPortWS;
15 | if (localname == "" && serverName == DEFAULT_NAME && group.getName() != "")
16 | {serverName = group.getName();}
17 | else if (localname != "" ) {serverName = localname;}
18 |
19 | std::cout << "servername: " << serverName << std::endl;
20 |
21 | // set ports and name of the OSCQuery device
22 | device.setup(serverName, OSCport, WSport);
23 | nodes.emplace_back(device, group);
24 |
25 | // This will echo the controls from clients to the output
26 | device.set_echo(true);
27 |
28 | // Then build ossia tree up from the chosen parameterGroup
29 | buildTreeFrom(group, nodes.front());
30 |
31 | }
32 |
33 | void ofxOscQueryServer::buildTreeFrom(ofParameterGroup& group, ofxOssiaNode& node)
34 | {
35 |
36 | // Traverse all children recursively and create Nodes for each of them
37 | for(std::size_t i = 0; i < group.size(); i++){
38 | std::string type = group.get(i).type();
39 |
40 | if(type==typeid(ofParameterGroup).name()){
41 |
42 | // Create a Node for this Group at the end of the list
43 | nodes.emplace_back(node, group.getGroup(i));
44 |
45 | // Create sub-tree for Group
46 | buildTreeFrom(group.getGroup(i), nodes.back());
47 |
48 | } else { // This is a Parameter
49 |
50 | // Check parameter type, and create Node accordingly:
51 | if(type == typeid(ofParameter ).name())
52 | nodes.emplace_back(node, group.get(i));
53 | else if(type == typeid(ofParameter ).name())
54 | nodes.emplace_back(node, group.get(i));
55 | else if(type == typeid(ofParameter ).name())
56 | nodes.emplace_back(node, group.get(i));
57 | else if(type == typeid(ofParameter ).name())
58 | nodes.emplace_back(node, group.get(i));
59 | else if(type == typeid(ofParameter ).name())
60 | nodes.emplace_back(node, group.get(i));
61 | else if(type == typeid(ofParameter ).name())
62 | nodes.emplace_back(node, group.get(i));
63 | else if(type == typeid(ofParameter ).name())
64 | nodes.emplace_back(node, group.get(i));
65 | else if(type == typeid(ofParameter ).name())
66 | nodes.emplace_back(node, group.get(i));
67 | else if(type == typeid(ofParameter ).name())
68 | nodes.emplace_back(node, group.get(i));
69 | else if(type == typeid(ofParameter ).name())
70 | nodes.emplace_back(node, group.get(i));
71 | else if(type == typeid(ofParameter ).name())
72 | nodes.emplace_back(node, group.get(i));
73 | else{ ofLogWarning() << "ofxBaseGroup; no support for parameter of type " << type; break; }
74 |
75 | }
76 |
77 | }
78 |
79 | }
80 |
81 |
82 | ofxOssiaNode& ofxOscQueryServer::operator[](std::string targetPath)
83 | {
84 | std::string tPath = targetPath;
85 | if (targetPath.back()!='/') tPath=tPath+'/';
86 | if (targetPath.front()!='/') tPath='/'+tPath;
87 | auto found = find_if(nodes.begin(), nodes.end(),
88 | [&](ofxOssiaNode& n){return n.getPath()==tPath;});
89 | if (found!=nodes.end()) return *found;
90 | return getRootNode();
91 | }
92 |
93 | ofxOssiaNode& ofxOscQueryServer::operator[](ofAbstractParameter& targetParam)
94 | {
95 | auto found = find_if(nodes.begin(), nodes.end(),
96 | [&](ofxOssiaNode& n) {return (n.getParam()->isReferenceTo(targetParam));});
97 | if (found!=nodes.end()) return *found;
98 | return getRootNode();
99 | }
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/src/ofxOscQueryServer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #undef Status
3 | #undef Bool
4 | #undef bool
5 | #undef False
6 | #undef status
7 | #undef None
8 | #include
9 | #include "ofxOssiaNode.h"
10 | #include "ofxOssiaTypes.h"
11 | #include
12 | #include
13 | #include
14 |
15 | #define DEFAULT_OSC 1234
16 | #define DEFAULT_WS 5678
17 | #define DEFAULT_NAME "ofxOscQuery"
18 |
19 | class ofxOscQueryServer {
20 |
21 | public:
22 |
23 | ofxOscQueryServer(int localportOSC = DEFAULT_OSC,
24 | int localPortWS = DEFAULT_WS,
25 | std::string name = DEFAULT_NAME):
26 | OSCport(localportOSC), WSport(localPortWS), serverName(name),
27 | device(name, localportOSC, localPortWS){
28 | }
29 |
30 | ~ofxOscQueryServer() = default;
31 |
32 | /**
33 | * setup for ossia Device:
34 | * Create a root node at the specified ParameterGroup
35 | * with optional specific ports for OSC and WS (default 1234 & 5678)
36 | * and optionnal device name (defaults to the ParameterGroup's name)
37 | **/
38 | void setup(ofParameterGroup & group, int localportOSC = DEFAULT_OSC, int localPortWS = DEFAULT_WS, std::string localname = "");
39 |
40 | /**
41 | * Build tree from a specific ofParameterGroup/ossia::node pair
42 | * scans for children and create subnodes accordingly
43 | **/
44 | void buildTreeFrom(ofParameterGroup& group, ofxOssiaNode& node);
45 |
46 | /**
47 | * Address-space utilities:
48 | **/
49 | opp::oscquery_server& getDevice(){return device;}
50 |
51 | ofxOssiaNode& getRootNode(){ return nodes.front();}
52 |
53 | // Find a specific node by:
54 | // - path (ossia, relative to the server)
55 | ofxOssiaNode& operator[](std::string targetPath);
56 | // - or ofParameter reference
57 | ofxOssiaNode& operator[](ofAbstractParameter& targetParam);
58 | // When no corresponding node is found, the reference to the root node
59 | // (aka serverName.getRootNode()) is returned
60 |
61 | private:
62 | opp::oscquery_server device;
63 | std::string serverName;
64 | int OSCport, WSport;
65 | std::list nodes;
66 |
67 | friend class ofxOssiaNode;
68 |
69 | };
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/ofxOssiaNode.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "ofParameterGroup.h"
5 | #include "ofxOssiaTypes.h"
6 | #include "ofxOscQueryServer.h"
7 |
8 | /*
9 | * Class encapsulating ossia node, parent_node and ofAbstractParameter*
10 | * Largely inspired from https://github.com/OSSIA/ofxOssia/blob/master/src/ParamNode.h
11 | * */
12 |
13 | class ofxOssiaNode {
14 |
15 | public:
16 |
17 | //************************************//
18 | // General utilities //
19 | //************************************//
20 |
21 | /**
22 | @brief get this node's name
23 | @return this node's name as a string
24 | */
25 | std::string getName()
26 | {return ofParam->getName();}
27 |
28 | /**
29 | @brief get this node's OSC address, relative to the server
30 | @return this node's OSC address as a string
31 | */
32 | std::string getPath()
33 | {return path;}
34 |
35 | /**
36 | @brief get this node's ofParameter object
37 | @return a pointer to this node's ofAbstractParameter object
38 | */
39 | ofAbstractParameter* getParam()
40 | {return ofParam;}
41 |
42 | //************************************//
43 | // Manage attributes //
44 | //************************************//
45 |
46 | //********* ************//
47 | //********* Standard OSCQuery atrributes : ************//
48 | //********* ************//
49 |
50 |
51 | // The following methods allow to set and get most of the standard OSCQuery attributes, as defined in:
52 | // https://github.com/Vidvox/OSCQueryProposal
53 |
54 | // The libossia libraryther underlying this of addon allowing for more, non-standard attributes, they are made accessible by a extended set of appropraite methods below
55 |
56 |
57 |
58 | //********* Access mode: ************//
59 |
60 | /**Access mode is a metadata that categorizes parameters between:
61 | *
62 | * - 0 : no parameter (or value)
63 | * - 1 (GET / RO) : read-only
64 | * - 2 (SET / WO) : write-only
65 | * - 3 ( BI / RW) : read-write
66 | *
67 | * For instance:
68 | *
69 | * - The value of a vu-meter should be GET
70 | * - A "play" button should be SET.
71 | * - The cutoff of a filter or a controllable color should be BI.
72 | * @brief sets the access_mode attribute of this node's parameter
73 | * @param v an int corresponding to the chosen mode
74 | * @return a reference to this node
75 | */
76 | ofxOssiaNode& setAccess(int m){
77 | opp::access_mode mode;
78 | if (m == 1) mode = opp::access_mode::Get;
79 | else if (m == 2) mode = opp::access_mode::Set;
80 | else if (m == 3) mode = opp::access_mode::Bi;
81 | getNode().set_access(mode);
82 | return *this;
83 | }
84 |
85 | /**
86 | * A more descriptive way to define access modes with strings is give here
87 | * @brief sets the access_mode attribute of this node's parameter
88 | * @param v a string describing the chosen mode
89 | * @return a reference to this node
90 | */
91 | ofxOssiaNode& setAccess(std::string m){
92 | opp::access_mode mode;
93 | if (m == "GET" || m == "RO") mode = opp::access_mode::Get;
94 | else if (m == "SET" || m == "WO") mode = opp::access_mode::Set;
95 | else if (m == "BI" || m == "RW") mode = opp::access_mode::Bi;
96 | getNode().set_access(mode);
97 | return *this;
98 | }
99 | /**
100 | * @brief gets the access_mode attribute of this node's parameter
101 | * @return an opp::access_mode with this node's parameter's access mode
102 | * @see opp::node::set_acess
103 | */
104 | int getAccess() {
105 | opp::access_mode mode = getNode().get_access();
106 | int m;
107 | if ( mode == opp::access_mode::Get ) (m = 1 );
108 | else if ( mode == opp::access_mode::Set ) (m = 2 );
109 | else if ( mode == opp::access_mode::Bi ) (m = 3 );
110 | return m;
111 | }
112 |
113 | //********* Range (domain): ************//
114 |
115 |
116 | /**Domains allow to set a range of accepted values for a given parameter.
117 | * This range can be continuous (between a min and max), or discrete: a set of accepted values.
118 | * This function defines the minimum of a continuous range.
119 | * This is only meaningful for nodes with parameters of numerical types (ie ints, floats, vecnfs and some lists)
120 | * @brief sets the 'min' attribute of this node's parameter (minimum value)
121 | * @param min a value with the desired minimum value
122 | * @return a reference to this node
123 | * @see setBound
124 | */
125 | template
126 | ofxOssiaNode& setRangeMin(const DataValue& attrVal) {
127 | getNode().set_min(ossia::MatchingType::convert(attrVal));
128 | static_cast*>(ofParam)->setMin(attrVal);
129 | return *this;
130 | }
131 |
132 | /**
133 | * @brief gets the 'min' attribute of this node's parameter (minimum value)
134 | * @return a value with this node's parameter's minimum value
135 | * @see setRangeMin
136 | * @see getBound
137 | */
138 | template DataValue getRangeMin() {
139 | return ossia::MatchingType::convertFromOssia(getNode().get_min());
140 | }
141 |
142 | /**
143 | * This function defines the minimum of a continuous range.
144 | * This is only meaningful for nodes with parameters of numerical types (ie ints, floats, vecnfs and some lists)
145 | * @brief sets the 'max' attribute of this node's parameter (maximum value)
146 | * @param min a value with the desired mmaximum value
147 | * @return a reference to this node
148 | * @see opp::node::set_bounding
149 | */
150 | template
151 | ofxOssiaNode& setRangeMax(const DataValue& attrVal) {
152 | getNode().set_max(ossia::MatchingType::convert(attrVal));
153 | static_cast*>(ofParam)->setMax(attrVal);
154 | return *this;
155 | }
156 |
157 | /**
158 | * @brief gets the 'max' attribute of this node's parameter (maximum value)
159 | * @return a value with this node's parameter's maximum value
160 | * @see setRangeMax
161 | * @see getBound
162 | */
163 | template DataValue getRangeMax() {
164 | return ossia::MatchingType::convertFromOssia(getNode().get_max());
165 | }
166 |
167 | /**Domains allow to set a range of accepted values for a given parameter.
168 | * This function defines a set of accepted values.
169 | * This is only meaningful for nodes with parameters of about any types except Impulse
170 | * @brief sets a list of the values accepted by this node's parameter ("values" attribute)
171 | * @param v a std::vector of values with the desired list of accepted values
172 | * @return a reference to this node
173 | * @see opp::node::set_bounding
174 | */
175 | template
176 | ofxOssiaNode& setRangeValues(const std::vector& attrVals) {
177 | using ossia_type = ossia::MatchingType;
178 | std::vector res;
179 | for (const auto & v : attrVals) { res.push_back(ossia_type::convert(v)); }
180 | getNode().set_accepted_values(res);
181 | return *this;
182 | }
183 | /**
184 | * @brief gets a list of the values accepted by this node's parameter ("values" attribute)
185 | * @return a vector of values with the list of this node's parameter's accepted values
186 | * @see setRangeValues
187 | * @see setBound
188 | */
189 | template std::vector getRangeValues() {
190 | using ossia_type = ossia::MatchingType;
191 | auto vals = getNode().get_accepted_values();
192 | std::vector res;
193 | for (auto& v : vals) res.push_back(ossia_type::convertFromOssia(v));
194 | return res;
195 | }
196 |
197 |
198 | //********* ClipMode: ************//
199 |
200 |
201 | /**The clipmode determines what happens when a value is outside of the min / max:
202 | *
203 | * * **none** : no clipping; domain is only indicative.
204 | * * **both** : clipped to the closest value in the range.
205 | * * **low** : only clips values lower than the min.
206 | * * **high** : only clips values higher than the max.
207 | * The next two modes are not part of the OSCQuery Specs, but are supported by libossia:
208 | * * **wrap** : wraps values around the range
209 | * * **fold** : folds back values into the range
210 | *
211 | * The default is **none**.
212 | * @brief sets the clipmode attribute of this node's parameter
213 | * @param v a string describing the chosen mode
214 | * @return a reference to this node
215 | * @see setRangeMin
216 | * @see setRangeMax
217 | */
218 | ofxOssiaNode& setClipMode(const std::string& attrVal) {
219 | std::string a = attrVal;
220 | opp::bounding_mode mode;
221 | if (a == "both") mode = opp::bounding_mode::Clip;
222 | else if (a == "low" ) mode = opp::bounding_mode::Low;
223 | else if (a == "high") mode = opp::bounding_mode::High;
224 | else if (a == "wrap") mode = opp::bounding_mode::Wrap;
225 | else if (a == "fold") mode = opp::bounding_mode::Fold;
226 | else mode = opp::bounding_mode::Free;
227 | getNode().set_bounding(mode);
228 | return *this;
229 | }
230 |
231 | /**
232 | * @brief gets the bounding_mode attribute of this node's parameter
233 | * @return a std::string with this node's parameter's access mode
234 | */
235 | std::string getClipMode() {
236 | auto mode = getNode().get_bounding();
237 | std::string res;
238 | if (mode == opp::bounding_mode::Clip) res = "both" ;
239 | else if (mode == opp::bounding_mode::Low) res = "low" ;
240 | else if (mode == opp::bounding_mode::High) res = "high" ;
241 | else if (mode == opp::bounding_mode::Wrap) res = "wrap" ;
242 | else if (mode == opp::bounding_mode::Fold) res = "fold" ;
243 | else if (mode == opp::bounding_mode::Free) res = "none" ;
244 | return res;
245 | }
246 |
247 |
248 | //********* Units: ************//
249 |
250 |
251 | /**Units give a semantic meaning to the value of a parameter.
252 | * Units are sorted by categories (coined "dataspace" ): every unit in a category is convertible to the other units in the same category.
253 | * Every category has a neutral unit to/from which conversions are made.
254 | *
255 | * An unit, when setting it as a parameter's attribute, can be expressed as a string in the form:
256 | * - "category.unit" (such as "position.cart2D"),
257 | * - only with the unit name (such as "cart2D", those being all unique),
258 | * - or with "nicknames", that are indicated in parentheses, after the unit name
259 | * A list of all supported units is given below.
260 | *
261 | * @brief sets the unit attribute of this node's parameter
262 | * @param v a string with this unit's name
263 | * @return a reference to this node
264 | */
265 | ofxOssiaNode& setUnit(const std::string& attrVal) {getNode().set_unit(attrVal); return *this;}
266 | /**< @details
267 | *
268 | * - **Position**
269 | *
270 | * + **cart3D** (*xyz*, *pos*, *point*, *point3d*, *3d*, *cartesian3d*, *coord*, *coordinate*, *coordinates*, *pvector* *, *vertex*):
271 | * Cartesian 3-dimensional position (ie. X, Y, Z) in the OpenGL coordinate reference system
272 | * + **cart2D** (*xy*, *complex*, *point2d*, *2d*, *cartesian2d*):
273 | * Cartesian 2-dimensional position (i.e. X, Y)
274 | * + **opengl** (*gl*, *position.gl*):
275 | * Cartesian 3-dimensional position (ie. X, Y, Z) in the OpenGL coordinate reference system
276 | * + **spherical** (*aed*):
277 | * Polar 3-dimensional position (ie. aed: azimuth, elevation, distance)
278 | * + **polar** (*ad*):
279 | * Polar 2-dimensional position (ie. ad: azimuth, distance)
280 | * + **cylindrical** (*daz*):
281 | * Mixed 3-dimensional position (ie. daz: distance, azimuth, Z)
282 | *
283 | *
284 | *
285 | * - **Orientation**
286 | *
287 | * + **quaternion**:
288 | * An extension of the complex numbers for 3D orientation, in the form a+bi+cj+dk
289 | * + **euler**:
290 | * A triplet of angles (in degrees) describing the orientation of a rigid body with respect to a fixed coordinate system
291 | * + **axis**:
292 | * An angle (a, in degrees) relative to a 3-dimensional vector, expressed in the order X, Y, Z, a
293 | *
294 | *
295 | *
296 | * - **Color**
297 | *
298 | * + **argb** (*col*):
299 | * 4 float numbers between 0. and 1. describing respectively Alpha, Red, Green and Blue color values
300 | * + **rgba**:
301 | * 4 float numbers between 0. and 1. describing respectively Red, Green, Blue and Alpha color values
302 | * + **rgb**:
303 | * 3 float numbers between 0. and 1. describing respectively Red, Green and Blue color values
304 | * + **bgr**:
305 | * 3 float numbers between 0. and 1. describing respectively Blue, Green and Red color values
306 | * + **argb8**:
307 | * 4 int numbers between 0 and 255 describing respectively Alpha, Red, Green and Blue color values
308 | * + **hsv**:
309 | * 3 float numbers between 0. and 1. describing respectively Hue, Saturation and Value (Luminosity) color values in the * HSV colorspace
310 | * + **cmy8**:
311 | * 3 int numbers between 0 and 255 describing respectively Cyan, Magenta, and Yellow color values
312 | * + **cmyk8**:
313 | * 4 int numbers between 0 and 255 describing respectively Cyan, Magenta, Yellow and Black color values
314 | *
315 | * - **Angle**
316 | *
317 | * + **radian**
318 | * + **degree**
319 | *
320 | *
321 | * - **Distance**
322 | *
323 | * + **meter**
324 | * + **kilometer**
325 | * + **decimeter**
326 | * + **centimeter**
327 | * + **millimeter**
328 | * + **micrometer**
329 | * + **nanometer**
330 | * + **picometer**
331 | * + **inch**
332 | * + **foot**
333 | * + **mile**
334 | *
335 | * - **Time**
336 | *
337 | * + **second**
338 | * + **bark**
339 | * + **bpm**
340 | * + **cent**
341 | * + **frequency** (*freq*, *frequence*, *Hz*, *hz*, *Hertz*):
342 | * + **mel**
343 | * + **midi_pitch** (*midinote*):
344 | * + **millisecond** (*ms*)
345 | * + **playback_speed**
346 | * + **sample** (the length of a sample, for a sample_rate of 44100Hz)
347 | *
348 | * - **Gain**
349 | *
350 | * + **linear**:
351 | * A linear gain in the [0. 1.] range, with 1. being the nominal level
352 | * + **midigain**:
353 | * A value in the [0 127] range mimicing a MIDI gain controller. 100 for the nominal level, 127 for +12dB
354 | * + **decibel** (*db*, *dB*):
355 | * A single float value expressed in a logarithmic scale, typically to describe an audio gain (0dB being the nominal * gain, < 0dB describing a signal attenuation, clipped at -96dB)
356 | * + **decibel_raw**
357 | * Same as deciBel, but unclipped.
358 | *
359 | * - **Speed**
360 | *
361 | * + **meter_per_second**
362 | * + **miles_per_hour**
363 | * + **kilometer_per_hour**
364 | * + **knot**
365 | * + **foot_per_second**
366 | * + **foot_per_hour**
367 | */
368 |
369 | /**
370 | * @brief gets the unit of this node's parameter
371 | * @return a string with this node's parameter's unit name
372 | * @see ossia::unit_t
373 | */
374 | std::string getUnit() {
375 | return getNode().get_unit();
376 | }
377 |
378 | /**This attribute informs the network protocol that the value has a particular importance
379 | * and should if possible use a protocol not subject to message loss, eg TCP instead of UDP.
380 | * This is useful for instance for "play" messages.
381 | * @brief sets the critical attribute of this node's parameter
382 | * @param v a bool: true to mark this node's parameter as critical
383 | * @return a reference to this node
384 | */
385 | ofxOssiaNode& setCritical(bool v) {
386 | getNode().set_critical( v );
387 | return *this;
388 | }
389 | /**
390 | * @brief gets the critical attribute of this node's parameter
391 | * @return a bool: true if the node's parameter is critical
392 | */
393 | bool getCritical()
394 | { return getNode().get_critical();}
395 |
396 |
397 |
398 | //********* Other informative attributes: ************//
399 |
400 |
401 | /**An optional textual description.
402 | * @brief sets this node's description attribute
403 | * @param v a string with the textual description of this node
404 | * @return a reference to this node
405 | */
406 | ofxOssiaNode& setDescription(const std::string& attrVal)
407 | {getNode().set_description(attrVal); return *this;}
408 |
409 | /**
410 | * @brief gets this node's description attribute
411 | * @return a string with the textual description of this node
412 | */
413 | std::string getDescription()
414 | { return getNode().get_description();}
415 |
416 | /**An optional array of tags for nodes, expressed as one string per tag.
417 | * @brief sets his node's tags attribute
418 | * @param v a vector of strings with the desired tags of this node'
419 | * @return a reference to this node
420 | */
421 | ofxOssiaNode& setTags(std::vector attrVal)
422 | {getNode().set_tags(attrVal); return *this; }
423 | /**
424 | * @brief gets this node's tags attribute
425 | * @return a string with this node's tags
426 | */
427 | std::vector getTags()
428 | { return getNode().get_tags();}
429 |
430 |
431 | //********* ************//
432 | //********* Non-Standard (libossia-specific) atrributes : ************//
433 | //********* ************//
434 |
435 | // As explained abobe, libossia allows for more attributes than OSCQuery specifies.
436 | // Those can be useful for a number of situations, in particular when connecting
437 | // two (or more) libossia-powered applications/devices
438 |
439 |
440 |
441 | //********* Other value management attributes: ************//
442 |
443 |
444 | /**A default value for a given node. Useful for resetting to a default state.
445 | * @brief sets the default_value attribute of this node's parameter
446 | * @param v a value with this node's parameter's default value
447 | * @return a reference to this node
448 | */
449 | template
450 | ofxOssiaNode& setDefault(DataValue v){
451 | getNode().set_default_value(ossia::MatchingType::convert(v));
452 | return *this;
453 | }
454 | /**
455 | * @brief gets the default_value attribute of this node's parameter
456 | * @return a value with this node's parameter's default value
457 | */
458 | template
459 | DataValue getDefault()
460 | { return ossia::MatchingType::convertFromOssia(getNode().get_default_value()); }
461 |
462 | /**When the repetition filter is enabled, if the same value is sent twice, the second time will be filtered out.
463 | * @brief sets the repetition_filter attribute of this node's parameter
464 | * @param v a bool: true to filter out this node's parameter's value repetitions
465 | * @return a reference to this node
466 | */
467 | ofxOssiaNode& setRepetitionFilter(bool v){
468 | getNode().set_repetition_filter( v );
469 | return *this;
470 | }
471 | /**
472 | * @brief gets the repetition_filter attribute of this node's parameter
473 | * @return a bool: true if this node's parameter's value repetitions are filtered out
474 | */
475 | bool getRepetitionFilter()
476 | { return getNode().get_repetition_filter();}
477 |
478 | /**An optional value that says how often a value should be updated.
479 | * @brief sets the refresh_rate attribute of this node's parameter
480 | * @param v an int with this node's parameter's refresh_rate value
481 | * @return a reference to this node
482 | */
483 | ofxOssiaNode& setRefreshRate(int v){
484 | getNode().set_refresh_rate( v );
485 | return *this;
486 | }
487 | /**
488 | * @brief unsets the refresh_rate attribute of this node's parameter
489 | * @return a reference to this node
490 | */
491 | ofxOssiaNode& unsetRefreshRate(){
492 | getNode().unset_refresh_rate();
493 | return *this;
494 | }
495 | /**
496 | * @brief gets the refresh_rate attribute of this node's parameter
497 | * @return a float with this node's parameter's refresh_rate value
498 | */
499 | int getRefreshRate()
500 | { return getNode().get_refresh_rate();}
501 |
502 | /**An optional value that says by which increment a value should change, for instance in a value editor.
503 | * @brief sets the value_step_size attribute of this node's parameter
504 | * @param v the increment size
505 | * @return a reference to this node
506 | */
507 | ofxOssiaNode& setValueStepSize(double v){
508 | getNode().set_value_step_size( v );
509 | return *this;
510 | }
511 | /**
512 | * @brief unsets the value_step_size attribute of this node's parameter
513 | * @return a reference to this node
514 | */
515 | ofxOssiaNode& unsetValueStepSize(){
516 | getNode().unset_value_step_size();
517 | return *this;
518 | }
519 | /**
520 | * @brief gets the value_step_size attribute of this node's parameter
521 | * @return a float with this node's parameter's refresh_rate value
522 | */
523 | double getValueStepSize()
524 | { return getNode().get_value_step_size();}
525 |
526 | /**Nodes with the highest priority should execute first.
527 | * @brief sets the priority attribute of this node's parameter
528 | * @param v a float with this node's parameter's priority value (higher numbers for higher priorities)
529 | * @return a reference to this node
530 | */
531 | ofxOssiaNode& setPriority(float v){
532 | getNode().set_priority( v );
533 | return *this;
534 | }
535 | /**
536 | * @brief unsets the priority attribute of this node's parameter
537 | * @return a reference to this node
538 | */
539 | ofxOssiaNode& unsetPriority(){
540 | getNode().unset_priority();
541 | return *this;
542 | }
543 | /**
544 | * @brief gets the priority attribute of this node's parameter
545 | * @return a float with this node's parameter's priority value (higher numbers for higher priorities)
546 | */
547 | float getPriority()
548 | { return getNode().get_priority();}
549 |
550 | /**This attribute will disable a node: it will stop receiving and sending messages from/to the network.
551 | * @brief sets the disabled attribute of this node's parameter
552 | * @param v a bool: true to disable this node's parameter
553 | * @return a reference to this node
554 | */
555 | ofxOssiaNode& setDisabled(bool v){
556 | getNode().set_disabled( v );
557 | return *this;
558 | }
559 | /**
560 | * @brief gets the disabled attribute of this node's parameter
561 | * @return a bool: true if the node's parameter is disabled
562 | */
563 | bool getDisabled()
564 | { return getNode().get_disabled();}
565 |
566 | /**This attribute will disable a node: it will stop sending messages to the network.
567 | * Unlike the "disabled" attribute, it won't propagate to other mirrored servers.
568 | * @brief sets the muted attribute of this node's parameter
569 | * @param v a bool: true to mute this node's parameter
570 | * @return a reference to this node
571 | */
572 | ofxOssiaNode& setMuted(bool v){
573 | getNode().set_muted( v );
574 | return *this;
575 | }
576 | /**
577 | * @brief gets the muted attribute of this node's parameter
578 | * @return a bool: true if the node's parameter is muted
579 | */
580 | bool getMuted()
581 | { return getNode().get_muted();}
582 |
583 |
584 | /**For nodes that can have instantiatable children, this sets the minimum and maximum number of children that can exist.
585 | * This is an optional attribute: it is not enforced and is only to be relied upon as a metadata.
586 | * @brief sets how many instances this node can have
587 | * @param min the minimum number of instances this node can have
588 | * @param max the maximum number of instances this node can have
589 | * @return a reference to this node
590 | */
591 | ofxOssiaNode& setInstanceBounds(int min, int max)
592 | {getNode().set_instance_bounds(min, max); return *this;}
593 | /**
594 | * @brief unset how many instances this node can have
595 | * @return a reference to this node
596 | */
597 | ofxOssiaNode& unsetInstanceBounds()
598 | {getNode().unset_instance_bounds(); return *this;}
599 | /**
600 | * @brief gets how many instances this node can have
601 | * @return a std::pair with the minimum and maxium number sof instances this node can have
602 | */
603 | std::pair getInstanceBounds()
604 | { return getNode().get_instance_bounds();}
605 |
606 | /**This attribute is to use for nodes that are not to be exposed to the network.
607 | * @brief sets this node's hidden attribute
608 | * @param v a bool: true to hide this node
609 | * @return a reference to this node
610 | */
611 | ofxOssiaNode& setHidden(bool v)
612 | {getNode().set_hidden(v); return *this;}
613 | /**
614 | * @brief gets this node's hidden attribute
615 | * @return a bool: true if the node is hidden
616 | */
617 | bool getHidden()
618 | { return getNode().get_hidden();}
619 |
620 | /**This is a read-only attribute: it informs of whether a node is in a zombie state.
621 | * A zombie node is an node in a remote device, whose source has been removed.
622 | * It is kept in the mirrors but marked as such.
623 | * @brief gets the zombie attribute of this node's parameter
624 | * @return a bool: true if the node has been zombified
625 | */
626 | bool getZombie()
627 | { return getNode().get_zombie();}
628 |
629 |
630 |
631 | //*********************//
632 | // Constructors //
633 | //*********************//
634 |
635 |
636 | /*
637 | * Constructors for the Root Node
638 | */
639 |
640 |
641 | ofxOssiaNode() = default;
642 |
643 | /*
644 | *Constructor for the Root Node
645 | */
646 |
647 | ofxOssiaNode(opp::oscquery_server& dev, ofParameterGroup& group):
648 | currentNode{dev.get_root_node()},
649 | ofParam{&group},
650 | path{"/"}
651 | {}
652 |
653 | /*
654 | *Constructor for ParameterGroup Nodes
655 | */
656 |
657 | ofxOssiaNode(ofxOssiaNode& parentNode, ofParameterGroup& group):
658 | currentNode{parentNode.getNode().create_child(group.getName())},
659 | ofParam{&group},
660 | path{parentNode.getPath()+currentNode.get_name()+"/"}
661 | {
662 | ofParam->setName(currentNode.get_name());
663 | }
664 |
665 | /*
666 | *Constructor for all Parameter Nodes
667 | * */
668 | template
669 | ofxOssiaNode(ofxOssiaNode& parentNode, ofParameter& param):
670 | currentNode{ossia::MatchingType::create_parameter(param.getName(), parentNode.getNode())},
671 | ofParam{¶m},
672 | path{parentNode.getPath()+currentNode.get_name()+"/"}
673 | {
674 | using ossia_type = ossia::MatchingType;
675 |
676 | ofParam->setName(currentNode.get_name());
677 |
678 | //sets value
679 | currentNode.set_value(ossia_type::convert(param.get()));
680 | currentNode.set_default_value(ossia_type::convert(param.get()));
681 |
682 | //sets domain
683 | // cout << getName() << ": " << param.getRangeMin() << " / " << param.getRangeMax() << endl;
684 | currentNode.set_min(ossia_type::convert(param.getMin())); // TODO: fix this in ossia-cpp
685 | currentNode.set_max(ossia_type::convert(param.getMax())); // TODO: fix this in ossia-cpp
686 |
687 | //adds callback from ossia Node to ofParameter
688 | callbackIt = currentNode.set_value_callback([](void* context, const opp::value& val)
689 | {
690 | ofParameter* self = reinterpret_cast*>(context);
691 |
692 | if(ossia_type::is_valid(val))
693 | {
694 | DataValue data = ossia_type::convertFromOssia(val);
695 | if(data != self->get())
696 | {
697 | self->set(data);
698 | }
699 | }
700 | else
701 | {
702 | std::cerr << "error [ofxOscQuery::enableRemoteUpdate()] : of and ossia types do not match \n" ;
703 | return;
704 | }
705 | }, ofParam);
706 |
707 | //adds callback from ofParameter to ossia Node
708 | param.addListener(this, &ofxOssiaNode::listen);
709 |
710 |
711 | }
712 |
713 | template
714 | void listen(DataValue &data)
715 | {
716 | // check if the value to be published is not already published
717 | if(pullNodeValue() != data)
718 | { // i-score->GUI OK
719 | publishValue(data);
720 | }
721 | }
722 |
723 | /*
724 | * Copy operations
725 | * */
726 | ofxOssiaNode(const ofxOssiaNode&) = default;
727 | ofxOssiaNode(ofxOssiaNode&&) = default;
728 | ofxOssiaNode& operator=(const ofxOssiaNode&) = default;
729 | ofxOssiaNode& operator=(ofxOssiaNode&&) = default;
730 |
731 | /*
732 | * Destructor
733 | * */
734 | ~ofxOssiaNode () {
735 | if (callbackIt) currentNode.remove_value_callback(callbackIt);
736 |
737 | auto type = ofParam->type();
738 | if(type == typeid(ofParameter ).name())
739 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
740 | else if(type == typeid(ofParameter ).name())
741 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
742 | else if(type == typeid(ofParameter ).name())
743 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
744 | else if(type == typeid(ofParameter ).name())
745 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
746 | else if(type == typeid(ofParameter ).name())
747 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
748 | else if(type == typeid(ofParameter ).name())
749 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
750 | else if(type == typeid(ofParameter ).name())
751 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
752 | else if(type == typeid(ofParameter ).name())
753 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
754 | else if(type == typeid(ofParameter ).name())
755 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
756 | else if(type == typeid(ofParameter ).name())
757 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
758 | else if(type == typeid(ofParameter ).name())
759 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
760 | else if(type == typeid(ofParameter ).name())
761 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
762 | else if(type == typeid(ofParameter ).name())
763 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
764 | else if(type == typeid(ofParameter ).name())
765 | static_cast*>(ofParam)->removeListener(this, &ofxOssiaNode::listen);
766 | }
767 |
768 |
769 | private:
770 |
771 | opp::node currentNode;
772 | ofAbstractParameter* ofParam = nullptr;
773 | std::string path;
774 | opp::callback_index callbackIt;
775 | friend class ofxOscQueryServer;
776 |
777 |
778 |
779 | //////////////////////////////////////////////
780 | // Private Methods //
781 | //////////////////////////////////////////////
782 |
783 | opp::node& getNode() {return currentNode;}
784 |
785 | template
786 | void publishValue(DataValue val){
787 | using ossia_type = ossia::MatchingType;
788 | currentNode.set_value(ossia_type::convert(val));
789 | }
790 |
791 | template
792 | DataValue pullNodeValue()
793 | {
794 | using ossia_type = ossia::MatchingType;
795 |
796 | try
797 | {
798 | auto val = currentNode.get_value();
799 | if(ossia_type::is_valid(val)){
800 | return ossia_type::convertFromOssia(val);
801 | }
802 | else
803 | std::cerr << "error [ofxOssia::pullNodeValue()] : of and ossia types do not match \n" ;
804 | return {};
805 | }
806 | catch(std::exception& e)
807 | {
808 | std::cerr << "error [ofxOssia::pullNodeValue()] : " << e.what() << "\n" ;
809 | return {};
810 | }
811 |
812 | catch(...)
813 | {
814 | auto val = currentNode.get_value();
815 | std::cerr << "error [ofxOssia::pullNodeValue()] : : of and ossia types do not match \n" ;
816 | return {};
817 | }
818 | }
819 |
820 | };
821 |
--------------------------------------------------------------------------------
/src/ofxOssiaTypes.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include