├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── Info.plist.in ├── PkgInfo ├── README.md ├── jit.realsense.cpp ├── jit.realsense.hpp ├── max.jit.realsense.cpp ├── max.jit.realsense.hpp ├── max_utils.hpp └── patch └── example.maxpat /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.user 3 | build 4 | jit.realsense/externals -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "max-sdk"] 2 | path = max-sdk 3 | url = https://github.com/jcelerier/max-sdk 4 | [submodule "librealsense"] 5 | path = librealsense 6 | url = https://github.com/IntelRealSense/librealsense 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_OSX_ARCHITECTURES "x86_64") 2 | 3 | cmake_minimum_required(VERSION 3.11) 4 | 5 | if (WIN32) 6 | # These must be prior to the "project" command 7 | # https://stackoverflow.com/questions/14172856/compile-with-mt-instead-of-md-using-cmake 8 | 9 | set(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1") 10 | set(CMAKE_C_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG") 11 | set(CMAKE_C_FLAGS_RELEASE "/MT /O2 /Ob2 /D NDEBUG") 12 | set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG") 13 | 14 | set(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1") 15 | set(CMAKE_CXX_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG") 16 | set(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /D NDEBUG") 17 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG") 18 | endif () 19 | 20 | 21 | project(jit.realsense) 22 | 23 | 24 | set(LibUSB_FIND_STATIC ON) 25 | set(BUILD_EXAMPLES OFF) 26 | set(BUILD_UNIT_TESTS OFF) 27 | set(BUILD_SHARED_LIBS OFF CACHE "" INTERNAL) 28 | if(APPLE) 29 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pipe -Ofast -march=broadwell") 30 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe -Ofast -march=broadwell") 31 | else() 32 | add_definitions(/D_HAS_AUTO_PTR_ETC=1 /D_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING /D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) 33 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /std:c++latest /Ox /MT /arch:AVX2") 34 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /std:c++latest /MTd") 35 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest") 36 | endif() 37 | 38 | if(WIN32) 39 | if(CMAKE_SIZEOF_VOID_P MATCHES 8) 40 | set(WIN64 1) 41 | endif() 42 | endif() 43 | 44 | set(BUILD_EXAMPLES 0) 45 | add_subdirectory(librealsense) 46 | set(CMAKE_POSITION_INDEPENDENT_CODE True) 47 | 48 | ### C74 stuff 49 | 50 | set(C74SUPPORT ${CMAKE_CURRENT_SOURCE_DIR}/max-sdk/source/c74support) 51 | set(MAX_ROOT ${C74SUPPORT}/max-includes) 52 | set(MSP_ROOT ${C74SUPPORT}/msp-includes) 53 | set(JIT_ROOT ${C74SUPPORT}/jit-includes) 54 | 55 | add_library(MaxAPI INTERFACE IMPORTED) 56 | add_library(MaxAudio INTERFACE IMPORTED) 57 | add_library(Jitter INTERFACE IMPORTED) 58 | 59 | # Includes 60 | set_target_properties(MaxAPI PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${MAX_ROOT}) 61 | set_target_properties(MaxAudio PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${MSP_ROOT}) 62 | set_target_properties(Jitter PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${JIT_ROOT}) 63 | if(WIN32) 64 | set_target_properties(MaxAPI PROPERTIES INTERFACE_LINK_LIBRARIES ${MAX_ROOT}/x64/MaxAPI.lib) 65 | set_target_properties(MaxAudio PROPERTIES INTERFACE_LINK_LIBRARIES ${MSP_ROOT}/x64/MaxAudio.lib) 66 | set_target_properties(Jitter PROPERTIES INTERFACE_LINK_LIBRARIES ${JIT_ROOT}/x64/jitlib.lib) 67 | 68 | set_target_properties(MaxAPI PROPERTIES 69 | INTERFACE_COMPILE_DEFINITIONS 70 | "WIN_VERSION;_CRT_SECURE_NO_WARNINGS;VER_TARGETNAME=\"jit.realsense\"") 71 | 72 | elseif(APPLE) 73 | 74 | file (STRINGS "${MAX_ROOT}/c74_linker_flags.txt" C74_SYM_MAX_LINKER_FLAGS) 75 | 76 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${C74_SYM_MAX_LINKER_FLAGS}") 77 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${C74_SYM_MAX_LINKER_FLAGS}") 78 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${C74_SYM_MAX_LINKER_FLAGS}") 79 | 80 | #set_target_properties(MaxAPI PROPERTIES INTERFACE_LINK_LIBRARIES ${MAX_ROOT}/MaxAPI.framework) 81 | #set_target_properties(MaxAudio PROPERTIES INTERFACE_LINK_LIBRARIES ${MSP_ROOT}/MaxAudioAPI.framework) 82 | set_target_properties(Jitter PROPERTIES INTERFACE_LINK_LIBRARIES ${JIT_ROOT}/JitterAPI.framework) 83 | 84 | # #include is incompatbile with CMake framework handling 85 | find_path(FILE_H_DIR Files.h 86 | HINTS 87 | /System/Library/Frameworks/ 88 | /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers/ 89 | /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers/ 90 | /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers 91 | /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers 92 | /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers 93 | /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers) 94 | 95 | # Rpath handling to be able to copy the built external in max folder 96 | set(CMAKE_INSTALL_NAME_DIR @rpath) 97 | set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) 98 | set(CMAKE_INSTALL_RPATH "@loader_path/") 99 | endif() 100 | 101 | ### jit.realsense stuff 102 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/jit.realsense/externals") 103 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") 104 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") 105 | 106 | add_library(${PROJECT_NAME} MODULE jit.realsense.cpp max.jit.realsense.cpp ${C74SUPPORT}/max-includes/common/commonsyms.c) 107 | target_link_libraries(${PROJECT_NAME} PRIVATE MaxAPI Jitter realsense2) 108 | set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 17) 109 | 110 | if(APPLE) 111 | find_library(coreFoundation CoreFoundation) 112 | find_library(iokit IOKit) 113 | target_link_libraries(${PROJECT_NAME} PUBLIC ${coreFoundation} ${iokit} objc) 114 | target_compile_options(${PROJECT_NAME} PUBLIC 115 | -pipe 116 | -Weverything 117 | -Wno-old-style-cast 118 | -Wno-c++98-compat 119 | -Wno-c++98-compat-pedantic 120 | -Wno-sign-conversion 121 | -Wno-vla-extension 122 | -Wno-exit-time-destructors 123 | -Wno-cast-align 124 | -Wno-weak-vtables 125 | -Wno-vla 126 | -Wno-four-char-constants 127 | -Wno-missing-prototypes 128 | -Wno-gnu-zero-variadic-macro-arguments 129 | -Wno-float-equal) 130 | 131 | target_include_directories(${PROJECT_NAME} PRIVATE ${FILE_H_DIR}) 132 | endif() 133 | 134 | ### C74 stuff 135 | 136 | set(EXTERN_OUTPUT_NAME "${PROJECT_NAME}") 137 | set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${EXTERN_OUTPUT_NAME}") 138 | ### Output ### 139 | if (APPLE) 140 | set_property(TARGET ${PROJECT_NAME} 141 | PROPERTY BUNDLE True) 142 | set_property(TARGET ${PROJECT_NAME} 143 | PROPERTY BUNDLE_EXTENSION "mxo") 144 | set_target_properties(${PROJECT_NAME} PROPERTIES XCODE_ATTRIBUTE_WRAPPER_EXTENSION "mxo") 145 | set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE_BUNDLE_VERSION "${GIT_VERSION_TAG}") 146 | set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in) 147 | elseif (WIN32) 148 | add_definitions( 149 | -DMAXAPI_USE_MSCRT 150 | -DWIN_VERSION 151 | -D_USE_MATH_DEFINES 152 | ) 153 | set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".mxe64") 154 | # warning about constexpr not being const in c++14 155 | set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/wd4814") 156 | # do not generate ILK files 157 | set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/INCREMENTAL:NO") 158 | endif () 159 | 160 | ### Post Build ### 161 | 162 | if (APPLE) 163 | add_custom_command( 164 | TARGET ${PROJECT_NAME} 165 | POST_BUILD 166 | COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/PkgInfo" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${EXTERN_OUTPUT_NAME}.mxo/Contents/PkgInfo" 167 | COMMENT "Copy PkgInfo" 168 | ) 169 | endif () 170 | -------------------------------------------------------------------------------- /Info.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${MACOSX_BUNDLE_EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | @AUTHOR_DOMAIN@.@BUNDLE_IDENTIFIER@ 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | 16 | CFBundlePackageType 17 | iLaX 18 | CFBundleSignature 19 | max2 20 | 21 | C74ObjectProperties 22 | 23 | c74excludefromcollectives 24 | @EXCLUDE_FROM_COLLECTIVES@ 25 | 26 | 27 | CFBundleVersion 28 | @GIT_VERSION_MAJ@.@GIT_VERSION_MIN@.@GIT_VERSION_SUB@ 29 | CFBundleShortVersionString 30 | @GIT_VERSION_MAJ@.@GIT_VERSION_MIN@.@GIT_VERSION_SUB@ 31 | CFBundleLongVersionString 32 | ${MACOSX_BUNDLE_EXECUTABLE_NAME} @GIT_VERSION_MAJ@.@GIT_VERSION_MIN@.@GIT_VERSION_SUB@ - @COPYRIGHT_STRING@ 33 | NSHumanReadableCopyright 34 | @COPYRIGHT_STRING@ 35 | 36 | CSResourcesFileMapped 37 | 38 | LSRequiresCarbon 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /PkgInfo: -------------------------------------------------------------------------------- 1 | iLaX???? -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jit.realsense 2 | RealSense external for Max/MSP 3 | 4 | ### Building for Windows 5 | 6 | #### Required tools: 7 | 8 | * Last tested with Visual Studio 2017 9 | * CMake 3.8+ 10 | 11 | #### Building 12 | 13 | * Open a shell and run : 14 | 15 | ``` 16 | mkdir build 17 | cd build 18 | cmake path/to/jit.realsense 19 | cmake --build . --config Release 20 | ``` 21 | 22 | This will build the 32-bit version; for building the 64 bit version, run cmake with the following command instead: 23 | 24 | ``` 25 | cmake -G "Visual Studio 15 2017 Win64" path/to/jit.realsense 26 | ``` 27 | 28 | The `jit.realsense.mxe` and `jit.realsense.mxe64` externals will be in the `Release` folder created during build. 29 | 30 | ### Building for macOS 31 | 32 | #### Required tools: 33 | 34 | * Last tested with Xcode 8 35 | * CMake >= 3.8 36 | 37 | #### Building 38 | 39 | * Open a shell, go to folder where you want to download the repo and run : 40 | 41 | ``` 42 | git clone --recursive https://github.com/tecartlab/jit.realsense.git 43 | mkdir build 44 | cd build 45 | ``` 46 | 47 | ##### if you want to create a release build without opening XCode: 48 | 49 | ``` 50 | cmake path/to/jit.realsense -DCMAKE_BUILD_TYPE=Release 51 | ``` 52 | 53 | for some strange reason you might have error messages. just do it again: 54 | ``` 55 | cmake path/to/jit.realsense -DCMAKE_BUILD_TYPE=Release 56 | ``` 57 | 58 | ``` 59 | cmake --build . 60 | ``` 61 | 62 | Note that the build is optimized for CPUs with at least AVX instructions (basically, any Sandy Bridge i7 or more recent); 63 | this can be tweaked on CMakeLists.txt:9. The produced external will be a fat library working with both 32 and 64 bit Max. 64 | 65 | ##### If you want to build and debug with XCode, run instead 66 | 67 | ``` 68 | cmake -G Xcode .. 69 | ``` 70 | for some strange reason you might have error messages. just do it again: 71 | ``` 72 | cmake -G Xcode .. 73 | ``` 74 | 75 | for some reason the xcode project Debug configuration has optimizations enabled, so if you want to debug you'll have to manually disable the optimizations setting (Optimization Level setting) 76 | -------------------------------------------------------------------------------- /jit.realsense.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "jit.realsense.hpp" 3 | #include "max_utils.hpp" 4 | 5 | static rs2_stream stream_from_long(long stream) { 6 | return static_cast(stream); 7 | } 8 | 9 | static 10 | rs2_format best_format(rs2_stream other) 11 | { 12 | using namespace std; 13 | switch(other) 14 | { 15 | case RS2_STREAM_DEPTH: return RS2_FORMAT_Z16; 16 | case RS2_STREAM_INFRARED: return RS2_FORMAT_Y8; 17 | case RS2_STREAM_COLOR: return RS2_FORMAT_RGB8; 18 | default: 19 | break; 20 | } 21 | throw std::runtime_error("Invalid stream requested"); 22 | } 23 | 24 | 25 | struct jit_rs_streaminfo 26 | { 27 | long stream = RS2_STREAM_INFRARED; 28 | long stream_index = 1; 29 | long rate = 60; 30 | long dimensions_size = 2; // do not remove, Max uses it. 31 | std::array dimensions{{640, 480}}; 32 | 33 | friend bool operator!=(const jit_rs_streaminfo& lhs, const jit_rs_streaminfo& rhs) 34 | { 35 | return lhs.stream != rhs.stream 36 | || lhs.stream_index != rhs.stream_index 37 | || lhs.rate != rhs.rate 38 | || lhs.dimensions != rhs.dimensions; 39 | } 40 | friend bool operator==(const jit_rs_streaminfo& lhs, const jit_rs_streaminfo& rhs) 41 | { 42 | return !(lhs != rhs); 43 | } 44 | }; 45 | 46 | // Our Jitter object instance data 47 | struct t_jit_realsense 48 | { 49 | t_object ob; 50 | rs2::device dev; 51 | rs2::config cfg; 52 | rs2::pipeline pipe; 53 | rs2::pipeline_profile profile; 54 | bool streaming{false}; 55 | 56 | long device = 0; 57 | long out_count = 1; 58 | 59 | std::array outputs; 60 | 61 | std::size_t device_cache = 0; 62 | std::array outputs_cache; 63 | 64 | void construct() 65 | { 66 | device = 0; 67 | out_count = 1; 68 | outputs = std::array{}; 69 | 70 | device_cache = 0; 71 | outputs_cache = outputs; 72 | } 73 | 74 | void rebuild() 75 | try 76 | { 77 | auto& ctx = t_jit_realsense::context(); 78 | // First cleanup if device is changing 79 | cleanup(); 80 | dev = nullptr; 81 | 82 | // Try to get the new device 83 | auto devs = ctx.query_devices(); 84 | auto n_dev = devs.size(); 85 | post("There are %d connected RealSense devices.\n", n_dev); 86 | 87 | if(n_dev <= device) 88 | { 89 | post("Device %d is not connected.", device); 90 | return; 91 | } 92 | 93 | dev = devs[device]; 94 | 95 | 96 | post("\nUsing device %d, an %s\n", device, dev.get_info(rs2_camera_info::RS2_CAMERA_INFO_NAME)); 97 | post(" Serial number: %s\n", dev.get_info(rs2_camera_info::RS2_CAMERA_INFO_SERIAL_NUMBER)); 98 | post(" Firmware version: %s\n", dev.get_info(rs2_camera_info::RS2_CAMERA_INFO_FIRMWARE_VERSION)); 99 | 100 | rebuild_streams(); 101 | 102 | device_cache = device; 103 | } 104 | catch(const std::exception & e) 105 | { 106 | error("realsense: %s\n", e.what()); 107 | if(dev) 108 | dev = nullptr; 109 | } 110 | 111 | void rebuild_streams() 112 | try 113 | { 114 | cleanup(); 115 | 116 | // First enable all native streams 117 | for(long i = 0; i < out_count; i++) 118 | { 119 | const jit_rs_streaminfo& out = outputs[(std::size_t)i]; 120 | auto format = best_format(stream_from_long(out.stream)); 121 | //auto si = out.stream == RS2_STREAM_INFRARED ? std::clamp(out.stream_index, 1, 2) : -1; 122 | 123 | cfg.enable_device(dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER)); 124 | cfg.enable_stream(stream_from_long(out.stream), /*si,*/ out.dimensions[0], out.dimensions[1], format, out.rate); 125 | } 126 | 127 | outputs_cache = outputs; 128 | if(out_count > 0) 129 | { 130 | profile = pipe.start(cfg); 131 | streaming = true; 132 | } 133 | } 134 | catch(const std::exception & e) 135 | { 136 | error("realsense: %s\n", e.what()); 137 | } 138 | 139 | static rs2::context& context() 140 | { 141 | static rs2::context ctx; 142 | return ctx; 143 | } 144 | 145 | void cleanup() 146 | try 147 | { 148 | if(!dev) 149 | return; 150 | 151 | if(streaming) 152 | pipe.stop(); 153 | profile = {}; 154 | streaming = false; 155 | 156 | cfg.disable_all_streams(); 157 | } 158 | catch(const std::exception & e) 159 | { 160 | error("realsense: %s\n", e.what()); 161 | } 162 | 163 | static inline t_class* max_class{}; 164 | }; 165 | 166 | 167 | 168 | t_jit_realsense *jit_realsense_new(long outcount) 169 | { 170 | auto obj = jit_new(t_jit_realsense::max_class); 171 | 172 | for(int i = 1; i < outcount; i++) { 173 | const std::string num_str = std::to_string(i + 1); 174 | const std::string out_str = "out" + num_str; 175 | const std::string out_maj_str = "Out" + num_str + " "; 176 | 177 | { 178 | auto attrstr = out_str + "_rs_stream"; 179 | auto pretty = "\"" + out_maj_str + "Stream\""; 180 | add_dynamic_attribute((t_object*)obj, attrstr, i, 1, &jit_rs_streaminfo::stream); 181 | object_attr_addattr_parse((t_object*)obj, attrstr.c_str(), "label", _sym_symbol, 0, pretty.c_str()); 182 | object_attr_addattr_parse((t_object*)obj, attrstr.c_str(), "style", _sym_symbol, 0, "enumindex"); 183 | object_attr_addattr_parse((t_object*)obj, attrstr.c_str(), "enumvals", _sym_atom, 0, "Any Depth Color Infrared"); 184 | } 185 | 186 | /*{ 187 | auto attr = out_str + "_rs_rate"; 188 | auto pretty = out_maj_str + "Rate"; 189 | add_output_attribute(attr, i, &jit_rs_streaminfo::rate); 190 | CLASS_ATTR_LABEL(t_jit_realsense::max_class, attr.c_str(), 0, pretty.c_str()); 191 | CLASS_ATTR_FILTER_CLIP(t_jit_realsense::max_class, "rs_rate", 0, 120); 192 | } 193 | 194 | { 195 | auto attr = out_str + "_rs_index"; 196 | auto pretty = out_maj_str + "Index"; 197 | add_output_attribute(attr, i, &jit_rs_streaminfo::stream_index); 198 | CLASS_ATTR_LABEL(t_jit_realsense::max_class, attr.c_str(), 0, pretty.c_str()); 199 | CLASS_ATTR_FILTER_CLIP(t_jit_realsense::max_class, "rs_index", 0, 2); 200 | } 201 | 202 | { 203 | auto attr = out_str + "_rs_dim"; 204 | auto pretty = out_maj_str + "Dims"; 205 | add_array_output_attribute(attr, i, &jit_rs_streaminfo::dimensions); 206 | CLASS_ATTR_LABEL(t_jit_realsense::max_class, attr.c_str(), 0, pretty.c_str()); 207 | }*/ 208 | } 209 | 210 | obj->out_count = outcount; 211 | obj->rebuild(); 212 | return obj; 213 | } 214 | 215 | void jit_realsense_free(t_jit_realsense *x) 216 | { 217 | if(x->streaming) 218 | { 219 | x->pipe.stop(); 220 | } 221 | } 222 | 223 | static 224 | bool compare_matrix_info(t_jit_matrix_info& current, t_jit_matrix_info expected) 225 | { 226 | bool res = true; 227 | res &= current.planecount == expected.planecount; 228 | res &= current.dimcount == expected.dimcount; 229 | res &= current.type == expected.type; 230 | if(!res) 231 | return false; 232 | 233 | for(int i = 0; i < current.dimcount; i++) 234 | { 235 | res &= current.dim[i] == expected.dim[i]; 236 | } 237 | 238 | return res; 239 | } 240 | 241 | static 242 | char* make_n_plane_matrix( 243 | t_jit_matrix_info& out_minfo, 244 | void* out_matrix, 245 | const rs2::video_stream_profile& intrin, 246 | int n_plane, 247 | t_symbol* type) 248 | { 249 | // First fill a matrix_info with the values we want 250 | t_jit_matrix_info expected = out_minfo; 251 | 252 | expected.planecount = n_plane; 253 | expected.dimcount = 2; 254 | expected.dim[0] = intrin.width(); 255 | expected.dim[1] = intrin.height(); 256 | expected.type = type; 257 | 258 | // not sure if this is true yet 259 | expected.flags = JIT_MATRIX_DATA_PACK_TIGHT; 260 | 261 | // Compare this matrix with the one in out_minfo 262 | if(!compare_matrix_info(out_minfo, expected)) 263 | { 264 | // Change the matrix if it is different 265 | 266 | // use setinfo_ex to preserve the flags 267 | jit_object_method(out_matrix, _jit_sym_setinfo_ex, &expected); 268 | auto old = expected; 269 | 270 | jit_object_method(out_matrix, _jit_sym_getinfo, &expected); 271 | //post("%d %d", old.dim[0], old.dim[1]); 272 | } 273 | 274 | // Return a pointer to the data 275 | char* out_bp{}; 276 | jit_object_method(out_matrix, _jit_sym_getdata, &out_bp); 277 | return out_bp; 278 | } 279 | 280 | static 281 | int num_planes_from_stream(rs2_stream other) 282 | { 283 | using namespace std; 284 | switch(other) 285 | { 286 | case RS2_STREAM_DEPTH: return 1; 287 | case RS2_STREAM_COLOR: return 3; 288 | case RS2_STREAM_INFRARED: return 1; 289 | default: 290 | break; 291 | } 292 | throw std::runtime_error("Invalid stream"); 293 | } 294 | 295 | static 296 | int num_planes_from_format(rs2_format format) 297 | { 298 | switch(format) 299 | { 300 | case RS2_FORMAT_ANY: 301 | throw std::logic_error{"any unhandled"}; 302 | case RS2_FORMAT_Z16: 303 | case RS2_FORMAT_DISPARITY16: 304 | case RS2_FORMAT_Y8: 305 | case RS2_FORMAT_Y16: 306 | case RS2_FORMAT_YUYV: 307 | return 1; 308 | case RS2_FORMAT_RGB8: 309 | case RS2_FORMAT_BGR8: 310 | case RS2_FORMAT_XYZ32F: 311 | return 3; 312 | case RS2_FORMAT_RGBA8: 313 | case RS2_FORMAT_BGRA8: 314 | case RS2_FORMAT_RAW10: 315 | return 4; 316 | } 317 | throw std::logic_error{"num_planes_from_format unhandled"}; 318 | } 319 | 320 | static 321 | t_symbol * symbol_from_format(rs2_format format) 322 | { 323 | switch(format) 324 | { 325 | case RS2_FORMAT_Z16: 326 | case RS2_FORMAT_Y16: 327 | case RS2_FORMAT_DISPARITY16: 328 | return _jit_sym_long; 329 | case RS2_FORMAT_Y8: 330 | case RS2_FORMAT_RGB8: 331 | case RS2_FORMAT_BGR8: 332 | case RS2_FORMAT_RGBA8: 333 | case RS2_FORMAT_BGRA8: 334 | case RS2_FORMAT_YUYV: 335 | return _jit_sym_char; 336 | case RS2_FORMAT_XYZ32F: 337 | return _jit_sym_float32; 338 | // Weird cases : 339 | case RS2_FORMAT_RAW10: 340 | case RS2_FORMAT_ANY: 341 | throw std::logic_error{"raw10, any unhandled"}; 342 | } 343 | throw std::logic_error{"symbol_from_format unhandled"}; 344 | } 345 | 346 | static 347 | t_symbol * symbol_from_stream(rs2_stream stream) 348 | { 349 | switch(stream) 350 | { 351 | case RS2_STREAM_DEPTH: 352 | return _jit_sym_long; 353 | 354 | case RS2_STREAM_INFRARED: 355 | case RS2_STREAM_COLOR: 356 | return _jit_sym_char; 357 | } 358 | throw std::logic_error{"symbol_from_stream unhandled"}; 359 | } 360 | 361 | template 362 | struct copier; 363 | 364 | // 16 bit case 365 | template<> 366 | struct copier 367 | { 368 | void operator()(int size, const rs2::frame& rs_matrix, char* max_matrix) 369 | { 370 | const auto image = (const uint16_t *)(rs_matrix.get_data()); 371 | auto matrix_out = (t_int32*)(max_matrix); 372 | 373 | std::copy(image, image + size, matrix_out); 374 | } 375 | }; 376 | 377 | // 8 bit case 378 | template<> 379 | struct copier 380 | { 381 | void operator()(int size, const rs2::frame& rs_matrix, char* max_matrix) 382 | { 383 | const auto image = (const uint8_t *)(rs_matrix.get_data()); 384 | auto matrix_out = (char*)(max_matrix); 385 | 386 | std::copy(image, image + size, matrix_out); 387 | } 388 | }; 389 | 390 | static 391 | void do_copy(rs2_format str, int size, const rs2::frame& rs_matrix, char* max_matrix) 392 | { 393 | switch(str) 394 | { 395 | case RS2_FORMAT_Z16: return copier{}(size, rs_matrix, max_matrix); 396 | case RS2_FORMAT_Y8: return copier{}(size, rs_matrix, max_matrix); 397 | case RS2_FORMAT_RGB8: return copier{}(size, rs_matrix, max_matrix); 398 | } 399 | } 400 | 401 | static 402 | void compute_output(t_jit_realsense *x, void *matrix, const jit_rs_streaminfo& info, const rs2::frameset& frames) 403 | { 404 | const auto num_planes = num_planes_from_stream(stream_from_long(info.stream)); 405 | const auto sym = symbol_from_stream(stream_from_long(info.stream)); 406 | const rs2_stream stream = stream_from_long(info.stream); 407 | 408 | auto lock = jit_object_method(matrix, _jit_sym_lock, 1); 409 | 410 | t_jit_matrix_info out_minfo{}; 411 | jit_object_method(matrix, _jit_sym_getinfo, &out_minfo); 412 | 413 | // Get the realsense informations and compare them 414 | // with the current matrix. 415 | const auto stream_profile = x->profile.get_stream(stream).as(); 416 | char* out_bp = make_n_plane_matrix(out_minfo, matrix, stream_profile, 417 | num_planes, 418 | sym); 419 | 420 | // Copy the data in the Max Matrix 421 | int size = stream_profile.height() * stream_profile.width() * num_planes; 422 | //post("FORMAT: %d", info.format); 423 | do_copy(best_format(stream_from_long(info.stream)), size, frames.first(stream), out_bp); 424 | 425 | jit_object_method(matrix, _jit_sym_lock, lock); 426 | } 427 | 428 | static 429 | t_jit_err jit_realsense_matrix_calc(t_jit_realsense* x, void *, void *outputs) 430 | try 431 | { 432 | // Get and check the data. 433 | if(!x || !x->dev) 434 | { 435 | error("No device"); 436 | return JIT_ERR_INVALID_PTR; 437 | } 438 | 439 | if(x->device != (long)x->device_cache) 440 | { 441 | x->rebuild(); 442 | } 443 | else if(x->outputs != x->outputs_cache) 444 | { 445 | x->rebuild_streams(); 446 | } 447 | 448 | if(x->out_count == 0) 449 | return JIT_ERR_NONE; 450 | 451 | // Fetch new frame from the realsense 452 | auto frameset = x->pipe.wait_for_frames(); 453 | 454 | for(int i = 0; i < (int)x->out_count; i++) 455 | { 456 | if (auto matrix = jit_object_method(outputs, _jit_sym_getindex, i)) 457 | { 458 | compute_output(x, matrix, x->outputs[i], frameset); 459 | } 460 | } 461 | 462 | return JIT_ERR_NONE; 463 | } 464 | catch(const std::exception & e) 465 | { 466 | if(typeid(e) == typeid(rs2::recoverable_error)) { 467 | post("%s", e.what()); 468 | return JIT_ERR_NONE; 469 | } 470 | 471 | error("%s\n", e.what()); 472 | x->cleanup(); 473 | return JIT_ERR_GENERIC; 474 | } 475 | 476 | t_jit_err jit_realsense_init() 477 | { 478 | common_symbols_init(); 479 | 480 | t_jit_object *mop; 481 | 482 | t_jit_realsense::max_class = (t_class*)jit_class_new("jit_realsense", (method)jit_realsense_new, (method)jit_realsense_free, sizeof(t_jit_realsense), A_DEFLONG, 0); 483 | 484 | // add matrix operator (mop) 485 | mop = (t_jit_object *)jit_object_new(_jit_sym_jit_mop, 0, -1); //no matrix inputs, and variable number of outputs 486 | jit_class_addadornment(t_jit_realsense::max_class, mop); 487 | 488 | // add method(s) 489 | jit_class_addmethod(t_jit_realsense::max_class, (method)jit_realsense_matrix_calc, "matrix_calc", A_CANT, 0); 490 | 491 | // Add attributes : 492 | 493 | add_attribute("rs_device", &t_jit_realsense::device); 494 | add_attribute_flags("rs_out_count", &t_jit_realsense::out_count, JIT_ATTR_GET_DEFER_LOW | JIT_ATTR_SET_OPAQUE_USER); 495 | 496 | add_output_attribute("rs_stream", 0, &jit_rs_streaminfo::stream); 497 | CLASS_ATTR_LABEL(t_jit_realsense::max_class, "rs_stream", 0, "Out 1 Stream"); 498 | class_attr_enumindex(t_jit_realsense::max_class, "rs_stream", 499 | "Any", "Depth", "Color", "Infrared"); 500 | 501 | add_output_attribute("rs_rate", 0, &jit_rs_streaminfo::rate); 502 | CLASS_ATTR_LABEL(t_jit_realsense::max_class, "rs_rate", 0, "Out 1 Rate"); 503 | CLASS_ATTR_FILTER_CLIP(t_jit_realsense::max_class, "rs_rate", 0, 120); 504 | 505 | add_output_attribute("rs_index", 0, &jit_rs_streaminfo::stream_index); 506 | CLASS_ATTR_LABEL(t_jit_realsense::max_class, "rs_index", 0, "Out 1 Index"); 507 | CLASS_ATTR_FILTER_CLIP(t_jit_realsense::max_class, "rs_index", 1, 2); 508 | 509 | add_array_output_attribute("rs_dim", 0, &jit_rs_streaminfo::dimensions); 510 | CLASS_ATTR_LABEL(t_jit_realsense::max_class, "rs_dim", 0, "Out 1 Dims"); 511 | 512 | // finalize class 513 | jit_class_register(t_jit_realsense::max_class); 514 | return JIT_ERR_NONE; 515 | } 516 | -------------------------------------------------------------------------------- /jit.realsense.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | static const constexpr int jit_realsense_max_num_outlets = 6; 5 | 6 | t_jit_err jit_realsense_init(); 7 | -------------------------------------------------------------------------------- /max.jit.realsense.cpp: -------------------------------------------------------------------------------- 1 | #include "jit.realsense.hpp" 2 | #include 3 | #include 4 | 5 | struct t_max_jit_realsense 6 | { 7 | static inline void* max_class = nullptr; 8 | t_object ob; 9 | void *obex; 10 | }; 11 | 12 | // Taken from jit.noise example 13 | void max_jit_realsense_outputmatrix(t_max_jit_realsense *x) 14 | { 15 | long outputmode = max_jit_mop_getoutputmode(x); 16 | void *mop = max_jit_obex_adornment_get(x,_jit_sym_jit_mop); 17 | 18 | if(!outputmode || !mop) 19 | return; 20 | 21 | if(outputmode != 1) 22 | { 23 | max_jit_mop_outputmatrix(x); 24 | return; 25 | } 26 | 27 | auto err = (t_jit_err)jit_object_method( 28 | max_jit_obex_jitob_get(x), 29 | _jit_sym_matrix_calc, 30 | jit_object_method(mop,_jit_sym_getinputlist), 31 | jit_object_method(mop,_jit_sym_getoutputlist)); 32 | 33 | if (err) 34 | { 35 | jit_error_code(x,err); 36 | } 37 | else 38 | { 39 | max_jit_mop_outputmatrix(x); 40 | } 41 | } 42 | 43 | // only for dynamic attrs 44 | void max_jit_realsense_anything(t_max_jit_realsense *x, t_symbol *message, long argc, t_atom *argv) { 45 | void *o = max_jit_obex_jitob_get(x); 46 | void *attr = nullptr; 47 | 48 | if(strncmp(message->s_name, "get", 3) == 0) { 49 | t_symbol *name = gensym(message->s_name+3); 50 | attr = jit_object_attr_get(o, name); 51 | if(attr) { 52 | long ac = 0; 53 | t_atom *av = nullptr; 54 | jit_object_method(attr, gensym("get"), o, &ac, &av); 55 | if(ac && av) { 56 | outlet_anything(max_jit_obex_dumpout_get(x), name, ac, av); 57 | } 58 | jit_freebytes(av, sizeof(t_atom)*ac); 59 | } 60 | } 61 | else { 62 | attr = jit_object_attr_get(o, message); 63 | if(attr) { 64 | if(object_attr_usercanset(o, message)) { 65 | jit_object_method(attr, gensym("set"), o, argc, argv); 66 | } 67 | else { 68 | object_error((t_object *)x,"attribute %s is not settable",message->s_name); 69 | } 70 | } 71 | else { 72 | object_error((t_object *)x,"invalid message %s",message->s_name); 73 | } 74 | } 75 | } 76 | 77 | void *max_jit_realsense_new(t_symbol *, long argc, t_atom *argv) 78 | { 79 | auto x = max_jit_object_alloc((maxclass*)t_max_jit_realsense::max_class, gensym("jit_realsense")); 80 | if (x) 81 | { 82 | long outcount; 83 | if (argc && (outcount = atom_getlong(argv))) { 84 | CLIP_ASSIGN(outcount, 1, jit_realsense_max_num_outlets); 85 | } 86 | else { 87 | outcount = 1; 88 | } 89 | 90 | auto o = jit_object_new(gensym("jit_realsense"), outcount); 91 | if (o) 92 | { 93 | max_jit_obex_jitob_set(x,o); 94 | max_jit_obex_dumpout_set(x, outlet_new(x, nullptr)); 95 | max_jit_mop_setup(x); 96 | max_jit_mop_inputs(x); 97 | 98 | max_jit_mop_variable_addoutputs(x, outcount); 99 | 100 | max_jit_mop_outputs(x); 101 | max_jit_mop_matrix_args(x, argc, argv); 102 | max_jit_attr_args(x, argc, argv); 103 | } 104 | else 105 | { 106 | jit_object_error((t_object *)x, (char*)"jit.realsense: could not allocate object"); 107 | object_free((t_object *)x); 108 | x = nullptr; 109 | } 110 | } 111 | return x; 112 | } 113 | 114 | void max_jit_realsense_free(t_max_jit_realsense *x) 115 | { 116 | max_jit_mop_free(x); 117 | jit_object_free(max_jit_obex_jitob_get(x)); 118 | max_jit_object_free(x); 119 | } 120 | 121 | void ext_main(void *) 122 | { 123 | jit_realsense_init(); 124 | 125 | auto max_class = class_new("jit.realsense", (method)max_jit_realsense_new, (method)max_jit_realsense_free, sizeof(t_max_jit_realsense), nullptr, A_GIMME, 0); 126 | max_jit_class_obex_setup(max_class, calcoffset(t_max_jit_realsense, obex)); 127 | 128 | auto jit_class = (maxclass*)jit_class_findbyname(gensym("jit_realsense")); 129 | max_jit_class_mop_wrap(max_class, jit_class, MAX_JIT_MOP_FLAGS_OWN_OUTPUTMATRIX|MAX_JIT_MOP_FLAGS_OWN_JIT_MATRIX); 130 | max_jit_class_wrap_standard(max_class, jit_class, 0); 131 | 132 | max_jit_class_addmethod_usurp_low(max_class, (method) max_jit_realsense_outputmatrix, (char*)"outputmatrix"); 133 | class_addmethod(max_class, (method)max_jit_realsense_anything, "anything", A_GIMME, 0); 134 | class_addmethod(max_class, (method)max_jit_mop_assist, "assist", A_CANT, 0); 135 | class_register(CLASS_BOX, max_class); 136 | t_max_jit_realsense::max_class = max_class; 137 | } 138 | -------------------------------------------------------------------------------- /max.jit.realsense.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robtherich/jit.realsense/2130d3f52ef04ea8d00e102bab88d3ebe37f42fa/max.jit.realsense.hpp -------------------------------------------------------------------------------- /max_utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | template 8 | intptr_t get_offset(T U::*member) 9 | { 10 | return reinterpret_cast(&(((U*) nullptr)->*member)); 11 | } 12 | template 13 | intptr_t get_offset(T U::*member, int N) 14 | { 15 | return reinterpret_cast(&((((U*) nullptr)->*member)[N])); 16 | } 17 | 18 | 19 | template 20 | static void add_attribute_flags(std::string name, T Type::*member, long flags) 21 | { 22 | jit_class_addattr(Type::max_class, 23 | (t_jit_object*) jit_object_new( 24 | _jit_sym_jit_attr_offset, 25 | name.c_str(), 26 | _jit_sym_long, 27 | flags, 28 | (method)nullptr, 29 | (method)nullptr, 30 | get_offset(member))); 31 | } 32 | 33 | template 34 | static void add_attribute(std::string name, T Type::*member) 35 | { 36 | add_attribute_flags(name, member, JIT_ATTR_GET_DEFER_LOW | JIT_ATTR_SET_USURP_LOW); 37 | } 38 | 39 | template 40 | static void add_output_attribute(std::string name, int num, T Gadget::*member) 41 | { 42 | const auto flags = JIT_ATTR_GET_DEFER_LOW | JIT_ATTR_SET_USURP_LOW; 43 | const auto outputs_offset = get_offset(&Type::outputs, num); 44 | 45 | jit_class_addattr(Type::max_class, 46 | (t_jit_object*) jit_object_new( 47 | _jit_sym_jit_attr_offset, 48 | name.c_str(), 49 | _jit_sym_long, 50 | flags, 51 | (method)nullptr, 52 | (method)nullptr, 53 | outputs_offset + get_offset(member))); 54 | } 55 | 56 | template 57 | static void add_array_output_attribute(std::string name, int num, T Gadget::*member) 58 | { 59 | const auto flags = JIT_ATTR_GET_DEFER_LOW | JIT_ATTR_SET_USURP_LOW; 60 | const auto outputs_offset = get_offset(&Type::outputs, num); 61 | 62 | jit_class_addattr(Type::max_class, 63 | (t_jit_object*) jit_object_new( 64 | _jit_sym_jit_attr_offset_array, 65 | name.c_str(), 66 | _jit_sym_long, 67 | 2, 68 | flags, 69 | (method)nullptr, 70 | (method)nullptr, 71 | outputs_offset + get_offset(member) - sizeof(long), 72 | outputs_offset + get_offset(member))); 73 | } 74 | 75 | template 76 | static void add_dynamic_attribute(t_object *ob, std::string name, int num, int size, T Gadget::*member) 77 | { 78 | const auto outputs_offset = get_offset(&Type::outputs, num); 79 | t_object *attr = nullptr; 80 | if(size == 1) { 81 | attr = attr_offset_new(name.c_str(), _jit_sym_long, 0, (method)nullptr, (method)nullptr, outputs_offset + get_offset(member)); 82 | } 83 | else { 84 | attr = attr_offset_array_new(name.c_str(), _jit_sym_long, size, 0, (method)nullptr, (method)nullptr, outputs_offset + get_offset(member) - sizeof(long), outputs_offset + get_offset(member)); 85 | } 86 | if(attr) { 87 | jit_object_addattr(ob, attr); 88 | object_attr_addattr_parse(ob, name.c_str(), "dynamicattr", gensym("long"), 0, "1"); 89 | } 90 | } 91 | 92 | void class_attr_enumindex_rec(t_atom*) 93 | { 94 | 95 | } 96 | 97 | template 98 | void class_attr_enumindex_rec(t_atom* aaa, Arg&& arg, Args&&... args) 99 | { 100 | atom_setsym(aaa, gensym_tr(arg)); 101 | class_attr_enumindex_rec(aaa + 1, std::forward(args)...); 102 | } 103 | 104 | template 105 | void class_attr_enumindex(t_class* theclass, std::string attrname, Args&&... args) 106 | { 107 | constexpr int num = sizeof...(Args); 108 | t_atom aaa[num]; 109 | CLASS_ATTR_STYLE(theclass, attrname.c_str(), 0, "enumindex"); 110 | class_attr_enumindex_rec(aaa, std::forward(args)...); 111 | CLASS_ATTR_ATTR_ATOMS(theclass, attrname.c_str(), "enumvals", USESYM(atom), 1, num, aaa); 112 | } 113 | 114 | template 115 | T* jit_new(t_class* cls, Args&&... args) 116 | { 117 | auto obj = jit_object_alloc(cls); 118 | if(obj) 119 | { 120 | t_object tmp; 121 | memcpy(&tmp, obj, sizeof(t_object)); 122 | auto x = new(obj) T{std::forward(args)...}; 123 | memcpy(x, &tmp, sizeof(t_object)); 124 | 125 | return x; 126 | } 127 | return nullptr; 128 | } 129 | -------------------------------------------------------------------------------- /patch/example.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 7, 6 | "minor" : 3, 7 | "revision" : 4, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "rect" : [ 352.0, 155.0, 958.0, 727.0 ], 13 | "bglocked" : 0, 14 | "openinpresentation" : 1, 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-37", 42 | "maxclass" : "comment", 43 | "numinlets" : 1, 44 | "numoutlets" : 0, 45 | "patching_rect" : [ 37.0, 78.0, 150.0, 20.0 ], 46 | "presentation" : 1, 47 | "presentation_rect" : [ 373.0, 17.0, 150.0, 20.0 ], 48 | "style" : "", 49 | "text" : "Toggle me ! " 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "id" : "obj-40", 56 | "maxclass" : "newobj", 57 | "numinlets" : 1, 58 | "numoutlets" : 1, 59 | "outlettype" : [ "" ], 60 | "patching_rect" : [ 631.0, 47.0, 72.0, 22.0 ], 61 | "style" : "", 62 | "text" : "loadmess 1" 63 | } 64 | 65 | } 66 | , { 67 | "box" : { 68 | "id" : "obj-39", 69 | "maxclass" : "newobj", 70 | "numinlets" : 1, 71 | "numoutlets" : 1, 72 | "outlettype" : [ "" ], 73 | "patching_rect" : [ 300.0, 47.0, 72.0, 22.0 ], 74 | "style" : "", 75 | "text" : "loadmess 3" 76 | } 77 | 78 | } 79 | , { 80 | "box" : { 81 | "id" : "obj-25", 82 | "maxclass" : "newobj", 83 | "numinlets" : 1, 84 | "numoutlets" : 1, 85 | "outlettype" : [ "" ], 86 | "patching_rect" : [ 76.0, 10.0, 72.0, 22.0 ], 87 | "style" : "", 88 | "text" : "loadmess 2" 89 | } 90 | 91 | } 92 | , { 93 | "box" : { 94 | "id" : "obj-36", 95 | "linecount" : 3, 96 | "maxclass" : "comment", 97 | "numinlets" : 1, 98 | "numoutlets" : 0, 99 | "patching_rect" : [ 745.0, 423.0, 305.0, 48.0 ], 100 | "presentation" : 1, 101 | "presentation_linecount" : 3, 102 | "presentation_rect" : [ 519.0, 310.0, 305.0, 48.0 ], 103 | "style" : "", 104 | "text" : "Depth values are integers between 0 and 5000 - 10000 depending on the camera. A depth of 0 means that the camera wasn't able to compute a depth precisely." 105 | } 106 | 107 | } 108 | , { 109 | "box" : { 110 | "id" : "obj-35", 111 | "maxclass" : "newobj", 112 | "numinlets" : 2, 113 | "numoutlets" : 2, 114 | "outlettype" : [ "jit_matrix", "" ], 115 | "patching_rect" : [ 631.0, 453.0, 98.0, 22.0 ], 116 | "style" : "", 117 | "text" : "jit.* @val 0.0005" 118 | } 119 | 120 | } 121 | , { 122 | "box" : { 123 | "id" : "obj-32", 124 | "maxclass" : "message", 125 | "numinlets" : 2, 126 | "numoutlets" : 1, 127 | "outlettype" : [ "" ], 128 | "patching_rect" : [ 786.333313, 387.0, 63.0, 22.0 ], 129 | "style" : "", 130 | "text" : "dim $1 $2" 131 | } 132 | 133 | } 134 | , { 135 | "box" : { 136 | "id" : "obj-20", 137 | "maxclass" : "newobj", 138 | "numinlets" : 1, 139 | "numoutlets" : 2, 140 | "outlettype" : [ "jit_matrix", "" ], 141 | "patching_rect" : [ 631.0, 419.0, 105.0, 22.0 ], 142 | "style" : "", 143 | "text" : "jit.matrix 1 float32" 144 | } 145 | 146 | } 147 | , { 148 | "box" : { 149 | "id" : "obj-19", 150 | "maxclass" : "comment", 151 | "numinlets" : 1, 152 | "numoutlets" : 0, 153 | "patching_rect" : [ 835.0, 143.666656, 220.0, 20.0 ], 154 | "presentation" : 1, 155 | "presentation_rect" : [ 340.0, 195.666656, 220.0, 20.0 ], 156 | "style" : "", 157 | "text" : "For infrared, controls left / right camera" 158 | } 159 | 160 | } 161 | , { 162 | "box" : { 163 | "id" : "obj-18", 164 | "maxclass" : "comment", 165 | "numinlets" : 1, 166 | "numoutlets" : 0, 167 | "patching_rect" : [ 631.0, 20.0, 150.0, 20.0 ], 168 | "presentation" : 1, 169 | "presentation_rect" : [ 603.0, 78.0, 150.0, 20.0 ], 170 | "style" : "", 171 | "text" : "Properties for output 2" 172 | } 173 | 174 | } 175 | , { 176 | "box" : { 177 | "id" : "obj-17", 178 | "maxclass" : "comment", 179 | "numinlets" : 1, 180 | "numoutlets" : 0, 181 | "patching_rect" : [ 300.0, 20.0, 150.0, 20.0 ], 182 | "presentation" : 1, 183 | "presentation_rect" : [ 150.5, 91.0, 150.0, 20.0 ], 184 | "style" : "", 185 | "text" : "Properties for output 1" 186 | } 187 | 188 | } 189 | , { 190 | "box" : { 191 | "id" : "obj-16", 192 | "maxclass" : "comment", 193 | "numinlets" : 1, 194 | "numoutlets" : 0, 195 | "patching_rect" : [ 76.0, 10.0, 150.0, 20.0 ], 196 | "presentation" : 1, 197 | "presentation_rect" : [ 76.0, 10.0, 150.0, 20.0 ], 198 | "style" : "", 199 | "text" : "Number of active outputs" 200 | } 201 | 202 | } 203 | , { 204 | "box" : { 205 | "fontname" : "Arial", 206 | "fontsize" : 13.0, 207 | "id" : "obj-2", 208 | "maxclass" : "message", 209 | "numinlets" : 2, 210 | "numoutlets" : 1, 211 | "outlettype" : [ "" ], 212 | "patching_rect" : [ 394.5, 351.0, 66.0, 23.0 ], 213 | "presentation" : 1, 214 | "presentation_rect" : [ 261.5, 341.0, 66.0, 23.0 ], 215 | "style" : "", 216 | "text" : "640 480" 217 | } 218 | 219 | } 220 | , { 221 | "box" : { 222 | "fontname" : "Arial", 223 | "fontsize" : 13.0, 224 | "id" : "obj-8", 225 | "maxclass" : "message", 226 | "numinlets" : 2, 227 | "numoutlets" : 1, 228 | "outlettype" : [ "" ], 229 | "patching_rect" : [ 325.5, 351.0, 66.0, 23.0 ], 230 | "presentation" : 1, 231 | "presentation_rect" : [ 192.5, 341.0, 66.0, 23.0 ], 232 | "style" : "", 233 | "text" : "char" 234 | } 235 | 236 | } 237 | , { 238 | "box" : { 239 | "fontname" : "Arial", 240 | "fontsize" : 13.0, 241 | "id" : "obj-9", 242 | "maxclass" : "message", 243 | "numinlets" : 2, 244 | "numoutlets" : 1, 245 | "outlettype" : [ "" ], 246 | "patching_rect" : [ 241.5, 351.0, 74.0, 23.0 ], 247 | "presentation" : 1, 248 | "presentation_rect" : [ 108.5, 341.0, 74.0, 23.0 ], 249 | "style" : "", 250 | "text" : "1" 251 | } 252 | 253 | } 254 | , { 255 | "box" : { 256 | "fontname" : "Arial", 257 | "fontsize" : 13.0, 258 | "id" : "obj-10", 259 | "maxclass" : "newobj", 260 | "numinlets" : 4, 261 | "numoutlets" : 4, 262 | "outlettype" : [ "", "", "", "" ], 263 | "patching_rect" : [ 241.5, 316.0, 252.0, 23.0 ], 264 | "style" : "", 265 | "text" : "route planecount type dim" 266 | } 267 | 268 | } 269 | , { 270 | "box" : { 271 | "fontname" : "Arial", 272 | "fontsize" : 13.0, 273 | "id" : "obj-11", 274 | "maxclass" : "newobj", 275 | "numinlets" : 1, 276 | "numoutlets" : 1, 277 | "outlettype" : [ "" ], 278 | "patching_rect" : [ 241.5, 284.0, 80.0, 23.0 ], 279 | "style" : "", 280 | "text" : "jit.matrixinfo" 281 | } 282 | 283 | } 284 | , { 285 | "box" : { 286 | "id" : "obj-7", 287 | "interp" : 1, 288 | "maxclass" : "jit.pwindow", 289 | "numinlets" : 1, 290 | "numoutlets" : 2, 291 | "outlettype" : [ "", "" ], 292 | "patching_rect" : [ 631.0, 488.0, 262.0, 207.0 ], 293 | "presentation" : 1, 294 | "presentation_rect" : [ 500.5, 379.0, 318.0, 240.0 ] 295 | } 296 | 297 | } 298 | , { 299 | "box" : { 300 | "id" : "obj-1", 301 | "maxclass" : "jit.pwindow", 302 | "numinlets" : 1, 303 | "numoutlets" : 2, 304 | "outlettype" : [ "", "" ], 305 | "patching_rect" : [ 241.5, 443.0, 320.0, 240.0 ], 306 | "presentation" : 1, 307 | "presentation_rect" : [ 65.5, 379.0, 320.0, 240.0 ] 308 | } 309 | 310 | } 311 | , { 312 | "box" : { 313 | "fontname" : "Arial", 314 | "fontsize" : 13.0, 315 | "id" : "obj-21", 316 | "maxclass" : "message", 317 | "numinlets" : 2, 318 | "numoutlets" : 1, 319 | "outlettype" : [ "" ], 320 | "patching_rect" : [ 786.333313, 351.0, 66.0, 23.0 ], 321 | "presentation" : 1, 322 | "presentation_rect" : [ 715.833313, 277.0, 66.0, 23.0 ], 323 | "style" : "", 324 | "text" : "640 480" 325 | } 326 | 327 | } 328 | , { 329 | "box" : { 330 | "fontname" : "Arial", 331 | "fontsize" : 13.0, 332 | "id" : "obj-22", 333 | "maxclass" : "message", 334 | "numinlets" : 2, 335 | "numoutlets" : 1, 336 | "outlettype" : [ "" ], 337 | "patching_rect" : [ 715.0, 351.0, 66.0, 23.0 ], 338 | "presentation" : 1, 339 | "presentation_rect" : [ 644.5, 277.0, 66.0, 23.0 ], 340 | "style" : "", 341 | "text" : "long" 342 | } 343 | 344 | } 345 | , { 346 | "box" : { 347 | "fontname" : "Arial", 348 | "fontsize" : 13.0, 349 | "id" : "obj-23", 350 | "maxclass" : "message", 351 | "numinlets" : 2, 352 | "numoutlets" : 1, 353 | "outlettype" : [ "" ], 354 | "patching_rect" : [ 631.0, 351.0, 74.0, 23.0 ], 355 | "presentation" : 1, 356 | "presentation_rect" : [ 560.5, 277.0, 74.0, 23.0 ], 357 | "style" : "", 358 | "text" : "1" 359 | } 360 | 361 | } 362 | , { 363 | "box" : { 364 | "fontname" : "Arial", 365 | "fontsize" : 13.0, 366 | "id" : "obj-26", 367 | "maxclass" : "newobj", 368 | "numinlets" : 4, 369 | "numoutlets" : 4, 370 | "outlettype" : [ "", "", "", "" ], 371 | "patching_rect" : [ 631.0, 295.0, 252.0, 23.0 ], 372 | "style" : "", 373 | "text" : "route planecount type dim" 374 | } 375 | 376 | } 377 | , { 378 | "box" : { 379 | "fontname" : "Arial", 380 | "fontsize" : 13.0, 381 | "id" : "obj-30", 382 | "maxclass" : "newobj", 383 | "numinlets" : 1, 384 | "numoutlets" : 1, 385 | "outlettype" : [ "" ], 386 | "patching_rect" : [ 631.0, 265.0, 80.0, 23.0 ], 387 | "style" : "", 388 | "text" : "jit.matrixinfo" 389 | } 390 | 391 | } 392 | , { 393 | "box" : { 394 | "id" : "obj-14", 395 | "maxclass" : "newobj", 396 | "numinlets" : 2, 397 | "numoutlets" : 1, 398 | "outlettype" : [ "bang" ], 399 | "patching_rect" : [ 167.0, 110.0, 65.0, 22.0 ], 400 | "style" : "", 401 | "text" : "qmetro 16" 402 | } 403 | 404 | } 405 | , { 406 | "box" : { 407 | "id" : "obj-6", 408 | "maxclass" : "button", 409 | "numinlets" : 1, 410 | "numoutlets" : 1, 411 | "outlettype" : [ "bang" ], 412 | "patching_rect" : [ 130.0, 78.0, 24.0, 24.0 ], 413 | "presentation" : 1, 414 | "presentation_rect" : [ 303.0, 13.0, 24.0, 24.0 ], 415 | "style" : "" 416 | } 417 | 418 | } 419 | , { 420 | "box" : { 421 | "id" : "obj-5", 422 | "maxclass" : "toggle", 423 | "numinlets" : 1, 424 | "numoutlets" : 1, 425 | "outlettype" : [ "int" ], 426 | "parameter_enable" : 0, 427 | "patching_rect" : [ 167.0, 78.0, 24.0, 24.0 ], 428 | "presentation" : 1, 429 | "presentation_rect" : [ 340.0, 13.0, 24.0, 24.0 ], 430 | "style" : "" 431 | } 432 | 433 | } 434 | , { 435 | "box" : { 436 | "id" : "obj-4", 437 | "maxclass" : "newobj", 438 | "numinlets" : 1, 439 | "numoutlets" : 7, 440 | "outlettype" : [ "jit_matrix", "jit_matrix", "jit_matrix", "jit_matrix", "jit_matrix", "jit_matrix", "" ], 441 | "patching_rect" : [ 167.0, 180.0, 75.0, 22.0 ], 442 | "presentation" : 1, 443 | "presentation_rect" : [ 599.5, 10.0, 75.0, 22.0 ], 444 | "style" : "", 445 | "text" : "jit.realsense" 446 | } 447 | 448 | } 449 | , { 450 | "box" : { 451 | "attr" : "rs_out_count", 452 | "id" : "obj-24", 453 | "maxclass" : "attrui", 454 | "numinlets" : 1, 455 | "numoutlets" : 1, 456 | "outlettype" : [ "" ], 457 | "patching_rect" : [ 76.0, 42.0, 197.0, 22.0 ], 458 | "presentation" : 1, 459 | "presentation_rect" : [ 76.0, 42.0, 197.0, 22.0 ], 460 | "style" : "" 461 | } 462 | 463 | } 464 | , { 465 | "box" : { 466 | "attr" : "rs_dim", 467 | "id" : "obj-27", 468 | "maxclass" : "attrui", 469 | "numinlets" : 1, 470 | "numoutlets" : 1, 471 | "outlettype" : [ "" ], 472 | "patching_rect" : [ 300.0, 177.0, 197.0, 22.0 ], 473 | "presentation" : 1, 474 | "presentation_rect" : [ 135.5, 225.0, 197.0, 22.0 ], 475 | "style" : "" 476 | } 477 | 478 | } 479 | , { 480 | "box" : { 481 | "attr" : "rs_rate", 482 | "id" : "obj-28", 483 | "maxclass" : "attrui", 484 | "numinlets" : 1, 485 | "numoutlets" : 1, 486 | "outlettype" : [ "" ], 487 | "patching_rect" : [ 300.0, 108.333336, 197.0, 22.0 ], 488 | "presentation" : 1, 489 | "presentation_rect" : [ 135.5, 156.333344, 197.0, 22.0 ], 490 | "style" : "" 491 | } 492 | 493 | } 494 | , { 495 | "box" : { 496 | "attr" : "rs_stream", 497 | "id" : "obj-29", 498 | "maxclass" : "attrui", 499 | "numinlets" : 1, 500 | "numoutlets" : 1, 501 | "outlettype" : [ "" ], 502 | "patching_rect" : [ 300.0, 74.0, 197.0, 22.0 ], 503 | "presentation" : 1, 504 | "presentation_rect" : [ 135.5, 122.0, 197.0, 22.0 ], 505 | "style" : "" 506 | } 507 | 508 | } 509 | , { 510 | "box" : { 511 | "attr" : "out2_rs_stream", 512 | "id" : "obj-31", 513 | "maxclass" : "attrui", 514 | "numinlets" : 1, 515 | "numoutlets" : 1, 516 | "outlettype" : [ "" ], 517 | "patching_rect" : [ 631.0, 74.0, 199.0, 22.0 ], 518 | "presentation" : 1, 519 | "presentation_rect" : [ 572.0, 122.0, 199.0, 22.0 ], 520 | "style" : "" 521 | } 522 | 523 | } 524 | , { 525 | "box" : { 526 | "attr" : "out2_rs_dim", 527 | "id" : "obj-33", 528 | "maxclass" : "attrui", 529 | "numinlets" : 1, 530 | "numoutlets" : 1, 531 | "outlettype" : [ "" ], 532 | "patching_rect" : [ 631.0, 177.0, 199.0, 22.0 ], 533 | "presentation" : 1, 534 | "presentation_rect" : [ 572.0, 225.0, 199.0, 22.0 ], 535 | "style" : "" 536 | } 537 | 538 | } 539 | , { 540 | "box" : { 541 | "attr" : "out2_rs_rate", 542 | "id" : "obj-34", 543 | "maxclass" : "attrui", 544 | "numinlets" : 1, 545 | "numoutlets" : 1, 546 | "outlettype" : [ "" ], 547 | "patching_rect" : [ 631.0, 108.333336, 199.0, 22.0 ], 548 | "presentation" : 1, 549 | "presentation_rect" : [ 572.0, 156.333344, 199.0, 22.0 ], 550 | "style" : "" 551 | } 552 | 553 | } 554 | , { 555 | "box" : { 556 | "attr" : "rs_index", 557 | "id" : "obj-3", 558 | "maxclass" : "attrui", 559 | "numinlets" : 1, 560 | "numoutlets" : 1, 561 | "outlettype" : [ "" ], 562 | "patching_rect" : [ 300.0, 142.666656, 197.0, 22.0 ], 563 | "presentation" : 1, 564 | "presentation_rect" : [ 135.5, 190.666656, 197.0, 22.0 ], 565 | "style" : "" 566 | } 567 | 568 | } 569 | , { 570 | "box" : { 571 | "attr" : "out2_rs_index", 572 | "id" : "obj-12", 573 | "maxclass" : "attrui", 574 | "numinlets" : 1, 575 | "numoutlets" : 1, 576 | "outlettype" : [ "" ], 577 | "patching_rect" : [ 631.0, 142.666656, 199.0, 22.0 ], 578 | "presentation" : 1, 579 | "presentation_rect" : [ 572.0, 190.666656, 199.0, 22.0 ], 580 | "style" : "" 581 | } 582 | 583 | } 584 | ], 585 | "lines" : [ { 586 | "patchline" : { 587 | "destination" : [ "obj-2", 1 ], 588 | "midpoints" : [ 406.333333, 347.0, 451.0, 347.0 ], 589 | "source" : [ "obj-10", 2 ] 590 | } 591 | 592 | } 593 | , { 594 | "patchline" : { 595 | "destination" : [ "obj-8", 1 ], 596 | "midpoints" : [ 328.666667, 347.0, 382.0, 347.0 ], 597 | "source" : [ "obj-10", 1 ] 598 | } 599 | 600 | } 601 | , { 602 | "patchline" : { 603 | "destination" : [ "obj-9", 1 ], 604 | "midpoints" : [ 251.0, 347.0, 306.0, 347.0 ], 605 | "source" : [ "obj-10", 0 ] 606 | } 607 | 608 | } 609 | , { 610 | "patchline" : { 611 | "destination" : [ "obj-10", 0 ], 612 | "midpoints" : [ 251.0, 308.0, 251.0, 308.0 ], 613 | "source" : [ "obj-11", 0 ] 614 | } 615 | 616 | } 617 | , { 618 | "patchline" : { 619 | "destination" : [ "obj-4", 0 ], 620 | "midpoints" : [ 640.5, 165.0, 508.0, 165.0, 508.0, 210.0, 253.0, 210.0, 253.0, 165.0, 176.5, 165.0 ], 621 | "source" : [ "obj-12", 0 ] 622 | } 623 | 624 | } 625 | , { 626 | "patchline" : { 627 | "destination" : [ "obj-4", 0 ], 628 | "midpoints" : [ 176.5, 135.0, 176.5, 135.0 ], 629 | "source" : [ "obj-14", 0 ] 630 | } 631 | 632 | } 633 | , { 634 | "patchline" : { 635 | "destination" : [ "obj-35", 0 ], 636 | "source" : [ "obj-20", 0 ] 637 | } 638 | 639 | } 640 | , { 641 | "patchline" : { 642 | "destination" : [ "obj-32", 0 ], 643 | "source" : [ "obj-21", 0 ] 644 | } 645 | 646 | } 647 | , { 648 | "patchline" : { 649 | "destination" : [ "obj-4", 0 ], 650 | "midpoints" : [ 85.5, 126.0, 154.0, 126.0, 154.0, 165.0, 176.5, 165.0 ], 651 | "source" : [ "obj-24", 0 ] 652 | } 653 | 654 | } 655 | , { 656 | "patchline" : { 657 | "destination" : [ "obj-24", 0 ], 658 | "source" : [ "obj-25", 0 ] 659 | } 660 | 661 | } 662 | , { 663 | "patchline" : { 664 | "destination" : [ "obj-21", 1 ], 665 | "midpoints" : [ 795.833333, 347.0, 842.833313, 347.0 ], 666 | "order" : 0, 667 | "source" : [ "obj-26", 2 ] 668 | } 669 | 670 | } 671 | , { 672 | "patchline" : { 673 | "destination" : [ "obj-21", 0 ], 674 | "order" : 1, 675 | "source" : [ "obj-26", 2 ] 676 | } 677 | 678 | } 679 | , { 680 | "patchline" : { 681 | "destination" : [ "obj-22", 1 ], 682 | "midpoints" : [ 718.166667, 347.0, 771.5, 347.0 ], 683 | "source" : [ "obj-26", 1 ] 684 | } 685 | 686 | } 687 | , { 688 | "patchline" : { 689 | "destination" : [ "obj-23", 1 ], 690 | "midpoints" : [ 640.5, 347.0, 695.5, 347.0 ], 691 | "source" : [ "obj-26", 0 ] 692 | } 693 | 694 | } 695 | , { 696 | "patchline" : { 697 | "destination" : [ "obj-4", 0 ], 698 | "midpoints" : [ 309.5, 201.0, 253.0, 201.0, 253.0, 165.0, 176.5, 165.0 ], 699 | "source" : [ "obj-27", 0 ] 700 | } 701 | 702 | } 703 | , { 704 | "patchline" : { 705 | "destination" : [ "obj-4", 0 ], 706 | "midpoints" : [ 309.5, 132.0, 244.0, 132.0, 244.0, 165.0, 176.5, 165.0 ], 707 | "source" : [ "obj-28", 0 ] 708 | } 709 | 710 | } 711 | , { 712 | "patchline" : { 713 | "destination" : [ "obj-4", 0 ], 714 | "midpoints" : [ 309.5, 99.0, 244.0, 99.0, 244.0, 165.0, 176.5, 165.0 ], 715 | "source" : [ "obj-29", 0 ] 716 | } 717 | 718 | } 719 | , { 720 | "patchline" : { 721 | "destination" : [ "obj-4", 0 ], 722 | "midpoints" : [ 309.5, 165.0, 176.5, 165.0 ], 723 | "source" : [ "obj-3", 0 ] 724 | } 725 | 726 | } 727 | , { 728 | "patchline" : { 729 | "destination" : [ "obj-26", 0 ], 730 | "midpoints" : [ 640.5, 308.0, 640.5, 308.0 ], 731 | "source" : [ "obj-30", 0 ] 732 | } 733 | 734 | } 735 | , { 736 | "patchline" : { 737 | "destination" : [ "obj-4", 0 ], 738 | "midpoints" : [ 640.5, 99.0, 508.0, 99.0, 508.0, 60.0, 283.0, 60.0, 283.0, 165.0, 176.5, 165.0 ], 739 | "source" : [ "obj-31", 0 ] 740 | } 741 | 742 | } 743 | , { 744 | "patchline" : { 745 | "destination" : [ "obj-20", 0 ], 746 | "midpoints" : [ 795.833313, 410.0, 640.5, 410.0 ], 747 | "source" : [ "obj-32", 0 ] 748 | } 749 | 750 | } 751 | , { 752 | "patchline" : { 753 | "destination" : [ "obj-4", 0 ], 754 | "midpoints" : [ 640.5, 210.0, 253.0, 210.0, 253.0, 165.0, 176.5, 165.0 ], 755 | "source" : [ "obj-33", 0 ] 756 | } 757 | 758 | } 759 | , { 760 | "patchline" : { 761 | "destination" : [ "obj-4", 0 ], 762 | "midpoints" : [ 640.5, 132.0, 508.0, 132.0, 508.0, 210.0, 253.0, 210.0, 253.0, 165.0, 176.5, 165.0 ], 763 | "source" : [ "obj-34", 0 ] 764 | } 765 | 766 | } 767 | , { 768 | "patchline" : { 769 | "destination" : [ "obj-7", 0 ], 770 | "source" : [ "obj-35", 0 ] 771 | } 772 | 773 | } 774 | , { 775 | "patchline" : { 776 | "destination" : [ "obj-29", 0 ], 777 | "source" : [ "obj-39", 0 ] 778 | } 779 | 780 | } 781 | , { 782 | "patchline" : { 783 | "destination" : [ "obj-1", 0 ], 784 | "midpoints" : [ 176.5, 435.0, 251.0, 435.0 ], 785 | "order" : 0, 786 | "source" : [ "obj-4", 0 ] 787 | } 788 | 789 | } 790 | , { 791 | "patchline" : { 792 | "destination" : [ "obj-11", 0 ], 793 | "midpoints" : [ 176.5, 275.0, 251.0, 275.0 ], 794 | "order" : 1, 795 | "source" : [ "obj-4", 0 ] 796 | } 797 | 798 | } 799 | , { 800 | "patchline" : { 801 | "destination" : [ "obj-20", 0 ], 802 | "midpoints" : [ 185.833333, 258.0, 561.0, 258.0, 561.0, 390.0, 640.5, 390.0 ], 803 | "order" : 0, 804 | "source" : [ "obj-4", 1 ] 805 | } 806 | 807 | } 808 | , { 809 | "patchline" : { 810 | "destination" : [ "obj-30", 0 ], 811 | "midpoints" : [ 185.833333, 258.0, 640.5, 258.0 ], 812 | "order" : 1, 813 | "source" : [ "obj-4", 1 ] 814 | } 815 | 816 | } 817 | , { 818 | "patchline" : { 819 | "destination" : [ "obj-31", 0 ], 820 | "source" : [ "obj-40", 0 ] 821 | } 822 | 823 | } 824 | , { 825 | "patchline" : { 826 | "destination" : [ "obj-14", 0 ], 827 | "midpoints" : [ 176.5, 105.0, 176.5, 105.0 ], 828 | "source" : [ "obj-5", 0 ] 829 | } 830 | 831 | } 832 | , { 833 | "patchline" : { 834 | "destination" : [ "obj-4", 0 ], 835 | "midpoints" : [ 139.5, 174.0, 176.5, 174.0 ], 836 | "source" : [ "obj-6", 0 ] 837 | } 838 | 839 | } 840 | ], 841 | "dependency_cache" : [ { 842 | "name" : "jit.realsense.mxe64", 843 | "type" : "mx64" 844 | } 845 | , { 846 | "name" : "jit.*.mxe64", 847 | "type" : "mx64" 848 | } 849 | ], 850 | "autosave" : 0, 851 | "styles" : [ { 852 | "name" : "AudioStatus_Menu", 853 | "default" : { 854 | "bgfillcolor" : { 855 | "type" : "color", 856 | "color" : [ 0.294118, 0.313726, 0.337255, 1 ], 857 | "color1" : [ 0.454902, 0.462745, 0.482353, 0.0 ], 858 | "color2" : [ 0.290196, 0.309804, 0.301961, 1.0 ], 859 | "angle" : 270.0, 860 | "proportion" : 0.39, 861 | "autogradient" : 0 862 | } 863 | 864 | } 865 | , 866 | "parentstyle" : "", 867 | "multi" : 0 868 | } 869 | ] 870 | } 871 | 872 | } 873 | --------------------------------------------------------------------------------