├── icon.png ├── .gitmodules ├── .gitignore ├── source └── projects │ ├── dict.edit │ ├── CMakeLists.txt │ └── dict.edit.cpp │ ├── sin_tilde │ ├── CMakeLists.txt │ └── sin_tilde.cpp │ ├── simpletext │ ├── CMakeLists.txt │ └── simpletext.cpp │ └── dspstress_tilde │ ├── CMakeLists.txt │ └── dspstress_tilde.cpp ├── ReadMe.md ├── package-info.json.in ├── CMakeLists.txt ├── appveyor.yml ├── License.md ├── help ├── dspstress~.maxhelp ├── simpletext.maxhelp ├── sin~.maxhelp └── dict.edit.maxhelp ├── .travis.yml └── docs └── sin~.maxref.xml /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cycling74/max-devkit/HEAD/icon.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "source/max-api"] 2 | path = source/max-api 3 | url = https://github.com/Cycling74/max-api.git -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | sysbuild 2 | *.sdf 3 | *.suo 4 | *.sln 5 | *.opensdf 6 | log.txt 7 | externals 8 | support 9 | build 10 | *.o 11 | *.dylib 12 | tmp 13 | 14 | package-info.json 15 | -------------------------------------------------------------------------------- /source/projects/dict.edit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../max-api/script/max-pretarget.cmake) 5 | 6 | 7 | include_directories( 8 | "${C74_INCLUDES}" 9 | ) 10 | 11 | 12 | add_library( 13 | ${PROJECT_NAME} 14 | MODULE 15 | ${PROJECT_NAME}.cpp 16 | ) 17 | 18 | 19 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../max-api/script/max-posttarget.cmake) 20 | -------------------------------------------------------------------------------- /source/projects/sin_tilde/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../max-api/script/max-pretarget.cmake) 5 | 6 | 7 | include_directories( 8 | "${C74_INCLUDES}" 9 | ) 10 | 11 | 12 | add_library( 13 | ${PROJECT_NAME} 14 | MODULE 15 | ${PROJECT_NAME}.cpp 16 | ) 17 | 18 | 19 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../max-api/script/max-posttarget.cmake) 20 | -------------------------------------------------------------------------------- /source/projects/simpletext/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../max-api/script/max-pretarget.cmake) 5 | 6 | 7 | include_directories( 8 | "${C74_INCLUDES}" 9 | ) 10 | 11 | 12 | add_library( 13 | ${PROJECT_NAME} 14 | MODULE 15 | ${PROJECT_NAME}.cpp 16 | ) 17 | 18 | 19 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../max-api/script/max-posttarget.cmake) 20 | -------------------------------------------------------------------------------- /source/projects/dspstress_tilde/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../max-api/script/max-pretarget.cmake) 5 | 6 | 7 | include_directories( 8 | "${C74_INCLUDES}" 9 | ) 10 | 11 | 12 | add_library( 13 | ${PROJECT_NAME} 14 | MODULE 15 | ${PROJECT_NAME}.cpp 16 | ) 17 | 18 | 19 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../max-api/script/max-posttarget.cmake) 20 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | # Max-DevKit 2 | 3 | This project is discontinued, do not use. 4 | 5 | For traditional Max external development use the [Max SDK](https://github.com/Cycling74/max-sdk), or for an advanced C++ based api for external development and package creation take a look at the [min-devkit.](https://github.com/Cycling74/min-devkit) 6 | 7 | ## Support 8 | 9 | For support, please use the developer forums at: 10 | http://cycling74.com/forums/ 11 | -------------------------------------------------------------------------------- /package-info.json.in: -------------------------------------------------------------------------------- 1 | { 2 | "author" : "Cycling '74", 3 | "description" : "Lightweight reference implementation of a package built around the core Max-API.", 4 | "homepatcher" : "max-devkit.maxpat", 5 | "max_version_min" : "7.1", 6 | "name" : "max-devkit", 7 | "os" : { 8 | "macintosh" : { 9 | "platform" : [ "ia32", "x64" ], 10 | "min_version" : "none" 11 | }, 12 | "windows" : { 13 | "platform" : [ "ia32", "x64" ], 14 | "min_version" : "none" 15 | } 16 | }, 17 | "package_extra" : { 18 | "reverse_domain" : "com.cycling74", 19 | "copyright" : "Copyright (c) 2016 Cycling '74" 20 | }, 21 | "tags" : [ ], 22 | "version" : "@GIT_VERSION_MAJ@.@GIT_VERSION_MIN@.@GIT_VERSION_SUB@", 23 | "website" : "http://www.github.com/Cycling74/max-devkit" 24 | } 25 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | # Fetch the correct verion of the max-api 4 | message(STATUS "Updating Git Submodules") 5 | execute_process( 6 | COMMAND git submodule update --init --recursive 7 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 8 | ) 9 | 10 | 11 | # Misc setup and subroutines 12 | include(${CMAKE_CURRENT_SOURCE_DIR}/source/max-api/script/max-package.cmake) 13 | 14 | 15 | # Generate a project for every folder in the "source/projects" folder 16 | SUBDIRLIST(PROJECT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/source/projects) 17 | foreach (project_dir ${PROJECT_DIRS}) 18 | if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/source/projects/${project_dir}/CMakeLists.txt") 19 | message("Generating: ${project_dir}") 20 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/source/projects/${project_dir}) 21 | endif () 22 | endforeach () 23 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | os: Visual Studio 2017 2 | 3 | environment: 4 | VS_VERSION: "Visual Studio 15" 5 | 6 | configuration: Release 7 | shallow_clone: false 8 | 9 | platform: 10 | - x86 11 | - x64 12 | 13 | build_script: 14 | - if "%platform%" == "x86" SET VS_FULL=%VS_VERSION% 15 | - if "%platform%" == "x86" SET CUSTOM_FLAG="" 16 | - if "%platform%" == "x64" SET VS_FULL=%VS_VERSION% Win64 17 | - if "%platform%" == "x64" SET CUSTOM_FLAG="-DWIN64:Bool=True" 18 | - mkdir build 19 | - cd build 20 | - cmake -G "%VS_FULL%" %CUSTOM_FLAG% .. > %APPVEYOR_BUILD_FOLDER%\configure.log 21 | - cmake --build . --config Release > %APPVEYOR_BUILD_FOLDER%\build.log 22 | - cd .. 23 | - mkdir %APPVEYOR_PROJECT_NAME% 24 | - cp -r externals %APPVEYOR_PROJECT_NAME% 25 | - cp -r help %APPVEYOR_PROJECT_NAME% 26 | - cp License.md %APPVEYOR_PROJECT_NAME% 27 | - cp ReadMe.md %APPVEYOR_PROJECT_NAME% 28 | - 7z a %APPVEYOR_PROJECT_NAME%-win-%platform%.zip %APPVEYOR_PROJECT_NAME% > %APPVEYOR_BUILD_FOLDER%\archive.log 29 | 30 | artifacts: 31 | - name: Build 32 | path: '*.zip' 33 | - name: Log files 34 | path: '*.log' 35 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | The software to which this license pertains is the Max API that consists of the C/C++ language header files and source code examples contained within this archive. 2 | 3 | The MIT License 4 | 5 | Copyright (c) 2016, Cycling '74 6 | 7 | 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: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | 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. 12 | -------------------------------------------------------------------------------- /help/dspstress~.maxhelp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "rect" : [ 436.0, 289.0, 640.0, 506.0 ], 5 | "bglocked" : 0, 6 | "defrect" : [ 436.0, 289.0, 640.0, 506.0 ], 7 | "openrect" : [ 0.0, 0.0, 0.0, 0.0 ], 8 | "openinpresentation" : 0, 9 | "default_fontsize" : 10.0, 10 | "default_fontface" : 0, 11 | "default_fontname" : "Verdana", 12 | "gridonopen" : 0, 13 | "gridsize" : [ 5.0, 5.0 ], 14 | "gridsnaponopen" : 0, 15 | "toolbarvisible" : 1, 16 | "boxanimatetime" : 200, 17 | "imprint" : 0, 18 | "enablehscroll" : 1, 19 | "enablevscroll" : 1, 20 | "boxes" : [ { 21 | "box" : { 22 | "maxclass" : "ezdac~", 23 | "numoutlets" : 0, 24 | "patching_rect" : [ 180.0, 255.0, 45.0, 45.0 ], 25 | "id" : "obj-4", 26 | "numinlets" : 2 27 | } 28 | 29 | } 30 | , { 31 | "box" : { 32 | "maxclass" : "newobj", 33 | "text" : "dspstress~", 34 | "numoutlets" : 0, 35 | "fontname" : "Verdana", 36 | "patching_rect" : [ 175.0, 175.0, 66.0, 19.0 ], 37 | "id" : "obj-1", 38 | "fontsize" : 10.0, 39 | "numinlets" : 1 40 | } 41 | 42 | } 43 | , { 44 | "box" : { 45 | "maxclass" : "flonum", 46 | "numoutlets" : 2, 47 | "outlettype" : [ "float", "bang" ], 48 | "fontname" : "Verdana", 49 | "patching_rect" : [ 175.0, 145.0, 50.0, 19.0 ], 50 | "id" : "obj-2", 51 | "fontsize" : 10.0, 52 | "numinlets" : 1 53 | } 54 | 55 | } 56 | ], 57 | "lines" : [ { 58 | "patchline" : { 59 | "source" : [ "obj-2", 0 ], 60 | "destination" : [ "obj-1", 0 ], 61 | "hidden" : 0, 62 | "midpoints" : [ ] 63 | } 64 | 65 | } 66 | ] 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /source/projects/sin_tilde/sin_tilde.cpp: -------------------------------------------------------------------------------- 1 | #include "c74_msp.h" 2 | 3 | using namespace c74::max; 4 | 5 | static t_class* this_class = nullptr; 6 | 7 | 8 | struct t_sin { 9 | t_pxobject obj; 10 | }; 11 | 12 | 13 | void* sin_new(void) { 14 | t_sin* self = (t_sin*)object_alloc(this_class); 15 | 16 | dsp_setup((t_pxobject*)self, 1); 17 | outlet_new(self, "signal"); 18 | return self; 19 | } 20 | 21 | 22 | void sin_free(t_sin* self) { 23 | dsp_free((t_pxobject*)self); 24 | } 25 | 26 | 27 | void sin_perform64(t_sin* self, t_object* dsp64, double** ins, long numins, double** outs, long numouts, long sampleframes, long flags, void* userparam) { 28 | for (auto i=0; icpuusagetarget = f; 26 | } 27 | 28 | 29 | void dspstress_int(t_dspstress* self, long n) { 30 | dspstress_float(self, (double)n); 31 | } 32 | 33 | 34 | void dspstress_perform64(t_dspstress* self, t_object* dsp64, double** ins, long numins, double** outs, long numouts, long sampleframes, long flags, void* userparam) { 35 | double spintime = self->svtime_ms * self->cpuusagetarget / 100.0; 36 | double intime = systimer_gettime(); 37 | double outtime = intime + spintime; 38 | unsigned long spincounter = 0; 39 | 40 | while (systimer_gettime() < outtime) 41 | spincounter++; // tra la la 42 | } 43 | 44 | 45 | void dspstress_dsp64(t_dspstress* self, t_object* dsp64, short *count, double samplerate, long maxvectorsize, long flags) { 46 | self->svtime_ms = maxvectorsize / samplerate * 1000.0; 47 | object_method_direct(void, (t_object*, t_object*, t_perfroutine64, long, void*), 48 | dsp64, gensym("dsp_add64"), (t_object*)self, (t_perfroutine64)dspstress_perform64, 0, NULL); 49 | } 50 | 51 | 52 | void dspstress_assist(t_dspstress* self, void* unused, t_assist_function io, long index, char* string_dest) { 53 | if (io == ASSIST_INLET) { 54 | switch (index) { 55 | case 0: 56 | strncpy(string_dest, "Specify cpu usage % here", ASSIST_STRING_MAXSIZE); 57 | break; 58 | } 59 | } 60 | } 61 | 62 | 63 | void* dspstress_new(double val) { 64 | t_dspstress* x = (t_dspstress*)object_alloc(this_class); 65 | dsp_setup((t_pxobject*)x, 1); 66 | dspstress_float(x, val); 67 | return x; 68 | } 69 | 70 | 71 | void ext_main(void* r) { 72 | this_class = class_new("dspstress~", (method)dspstress_new, (method)dsp_free, sizeof(t_dspstress), 0, A_DEFFLOAT, 0); 73 | 74 | class_addmethod(this_class, (method)dspstress_dsp64, "dsp64", A_CANT, 0); 75 | class_addmethod(this_class, (method)dspstress_float, "float", A_FLOAT, 0); 76 | class_addmethod(this_class, (method)dspstress_int, "int", A_LONG, 0); 77 | class_addmethod(this_class, (method)dspstress_assist,"assist",A_CANT,0); 78 | class_dspinit(this_class); 79 | 80 | class_register(CLASS_BOX, this_class); 81 | } 82 | -------------------------------------------------------------------------------- /source/projects/simpletext/simpletext.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | simpletext - show use of text reading and editing 4 | 5 | @ingroup examples 6 | */ 7 | 8 | #include "c74_max.h" 9 | #include 10 | #include 11 | 12 | using namespace c74::max; 13 | 14 | struct t_simpletext { 15 | t_object ob; 16 | t_object* editor; 17 | std::string text; 18 | }; 19 | 20 | 21 | static t_class* this_class = nullptr; 22 | 23 | 24 | void* simpletext_new(t_symbol* name, long argc, t_atom* argv) { 25 | return object_alloc(this_class); 26 | } 27 | 28 | 29 | void simpletext_free(t_simpletext* self) { 30 | ; 31 | } 32 | 33 | 34 | void simpletext_dblclick(t_simpletext* self) { 35 | if (self->editor) 36 | object_attr_setchar(self->editor, gensym("visible"), 1); 37 | else { 38 | self->editor = (t_object*)object_new(CLASS_NOBOX, gensym("jed"), self, 0); 39 | object_method_direct(void, (t_object*, const char*, t_symbol*), 40 | self->editor, gensym("settext"), self->text.c_str(), gensym("utf-8")); 41 | object_attr_setchar(self->editor, gensym("scratch"), 1); 42 | object_attr_setsym(self->editor, gensym("title"), gensym("simpletext")); 43 | } 44 | } 45 | 46 | 47 | void simpletext_doread(t_simpletext* self, t_symbol* s, long argc, t_atom* argv) { 48 | char filename[MAX_FILENAME_CHARS]; 49 | char fullpath[MAX_PATH_CHARS]; 50 | short path; 51 | t_fourcc type = 'TEXT'; 52 | long err; 53 | 54 | if (s == gensym("")) { 55 | filename[0] = 0; 56 | if (open_dialog(filename, &path, &type, &type, 1)) 57 | return; // cancelled 58 | } 59 | else { 60 | strncpy(filename, s->s_name, MAX_FILENAME_CHARS); 61 | if (locatefile_extended(filename, &path, &type, &type, 1)) { 62 | object_error((t_object*)self, "can't find file %s", filename); 63 | return; // error 64 | } 65 | } 66 | 67 | err = path_toabsolutesystempath(path, filename, fullpath); 68 | if (!err) { 69 | std::ifstream filestream(fullpath); 70 | self->text.assign((std::istreambuf_iterator(filestream)), std::istreambuf_iterator()); 71 | } 72 | else 73 | object_error((t_object*)self, "can't get full path for file %s", filename); 74 | } 75 | 76 | 77 | void simpletext_read(t_object* self, t_symbol* s) { 78 | defer(self, (method)simpletext_doread, s, 0, NULL); 79 | } 80 | 81 | 82 | void simpletext_edclose(t_simpletext* self, char** text, long size) { 83 | self->text.assign(*text, size); 84 | self->editor = nullptr; 85 | } 86 | 87 | 88 | void simpletext_assist(t_simpletext* self, void* unused, t_assist_function io, long index, char* string_dest) { 89 | if (io == ASSIST_INLET) 90 | strncpy(string_dest, "Message In", ASSIST_STRING_MAXSIZE); 91 | } 92 | 93 | 94 | void ext_main(void* r) { 95 | this_class = class_new("simpletext", (method)simpletext_new, (method)simpletext_free, sizeof(t_simpletext), 0L, A_GIMME, 0); 96 | 97 | class_addmethod(this_class, (method)simpletext_read, "read", A_DEFSYM, 0); 98 | class_addmethod(this_class, (method)simpletext_dblclick, "dblclick", A_CANT, 0); 99 | class_addmethod(this_class, (method)simpletext_edclose, "edclose", A_CANT, 0); 100 | 101 | class_register(CLASS_BOX, this_class); 102 | } 103 | -------------------------------------------------------------------------------- /docs/sin~.maxref.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Signal sine function (0-1 range) 8 | 9 | 10 | Use the sin~ object to calculate and output a signal that is the cosine function of each sample of the input signal. 11 | 12 | 13 | 14 | 15 | 16 | 17 | Cycling '74 18 | 19 | 20 | MSP 21 | 22 | 23 | MSP Operators 24 | 25 | 26 | MSP Synthesis 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | (signal) Phase (0-1) 36 | 37 | 38 | TEXT_HERE 39 | 40 | 41 | 42 | 43 | 44 | 45 | TEXT_HERE 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | (signal) Sine Output 56 | 57 | 58 | TEXT_HERE 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | TEXT_HERE 69 | 70 | 71 | TEXT_HERE 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | Input to a sine function 83 | 84 | 85 | Input to a sine function. The input is stated as a fraction of a cycle (typically in the range from 0 to 1), and is multiplied by 2π before being used in the sine function. 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | The sine of 2π times the input. The method used in this object to calculate the cosine directly is typically less efficient than using the stored cosine in a cycle~ object. 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /help/sin~.maxhelp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 7, 6 | "minor" : 2, 7 | "revision" : 1, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "rect" : [ 38.0, 79.0, 666.0, 489.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 | "showrootpatcherontab" : 0, 40 | "showontab" : 0, 41 | "boxes" : [ { 42 | "box" : { 43 | "fontname" : "Arial", 44 | "fontsize" : 12.0, 45 | "id" : "obj-1", 46 | "maxclass" : "newobj", 47 | "numinlets" : 1, 48 | "numoutlets" : 1, 49 | "outlettype" : [ "" ], 50 | "patching_rect" : [ 334.0, 100.0, 123.0, 20.0 ], 51 | "saved_object_attributes" : { 52 | "filename" : "helpstarter.js", 53 | "parameter_enable" : 0 54 | } 55 | , 56 | "style" : "", 57 | "text" : "js helpstarter.js cos~" 58 | } 59 | 60 | } 61 | , { 62 | "box" : { 63 | "fontname" : "Arial", 64 | "fontsize" : 12.0, 65 | "id" : "obj-2", 66 | "maxclass" : "newobj", 67 | "numinlets" : 0, 68 | "numoutlets" : 0, 69 | "patcher" : { 70 | "fileversion" : 1, 71 | "appversion" : { 72 | "major" : 7, 73 | "minor" : 2, 74 | "revision" : 1, 75 | "architecture" : "x64", 76 | "modernui" : 1 77 | } 78 | , 79 | "rect" : [ 38.0, 105.0, 666.0, 463.0 ], 80 | "bglocked" : 0, 81 | "openinpresentation" : 0, 82 | "default_fontsize" : 13.0, 83 | "default_fontface" : 0, 84 | "default_fontname" : "Arial", 85 | "gridonopen" : 1, 86 | "gridsize" : [ 15.0, 15.0 ], 87 | "gridsnaponopen" : 1, 88 | "objectsnaponopen" : 1, 89 | "statusbarvisible" : 2, 90 | "toolbarvisible" : 1, 91 | "lefttoolbarpinned" : 0, 92 | "toptoolbarpinned" : 0, 93 | "righttoolbarpinned" : 0, 94 | "bottomtoolbarpinned" : 0, 95 | "toolbars_unpinned_last_save" : 0, 96 | "tallnewobj" : 0, 97 | "boxanimatetime" : 200, 98 | "enablehscroll" : 1, 99 | "enablevscroll" : 1, 100 | "devicewidth" : 0.0, 101 | "description" : "", 102 | "digest" : "", 103 | "tags" : "", 104 | "style" : "", 105 | "subpatcher_template" : "", 106 | "showontab" : 1, 107 | "boxes" : [ { 108 | "box" : { 109 | "id" : "obj-4", 110 | "local" : 1, 111 | "maxclass" : "ezdac~", 112 | "numinlets" : 2, 113 | "numoutlets" : 0, 114 | "patching_rect" : [ 155.7939, 406.0, 45.0, 45.0 ], 115 | "style" : "" 116 | } 117 | 118 | } 119 | , { 120 | "box" : { 121 | "fontface" : 0, 122 | "fontsize" : 12.0, 123 | "id" : "obj-5", 124 | "maxclass" : "live.gain~", 125 | "numinlets" : 2, 126 | "numoutlets" : 5, 127 | "orientation" : 1, 128 | "outlettype" : [ "signal", "signal", "", "float", "list" ], 129 | "parameter_enable" : 1, 130 | "patching_rect" : [ 155.7939, 335.0, 136.0, 40.0 ], 131 | "presentation_rect" : [ 0.0, 0.0, 50.0, 26.0 ], 132 | "saved_attribute_attributes" : { 133 | "valueof" : { 134 | "parameter_longname" : "live.gain~", 135 | "parameter_shortname" : "live.gain~", 136 | "parameter_type" : 0, 137 | "parameter_mmin" : -70.0, 138 | "parameter_mmax" : 6.0, 139 | "parameter_initial" : [ 0.0 ], 140 | "parameter_unitstyle" : 4 141 | } 142 | 143 | } 144 | , 145 | "showname" : 0, 146 | "varname" : "live.gain~" 147 | } 148 | 149 | } 150 | , { 151 | "box" : { 152 | "bubble" : 1, 153 | "fontname" : "Arial", 154 | "fontsize" : 13.0, 155 | "id" : "obj-3", 156 | "maxclass" : "comment", 157 | "numinlets" : 1, 158 | "numoutlets" : 0, 159 | "patching_rect" : [ 203.7939, 416.0, 77.0, 25.0 ], 160 | "style" : "", 161 | "text" : "start dsp" 162 | } 163 | 164 | } 165 | , { 166 | "box" : { 167 | "fontname" : "Arial", 168 | "fontsize" : 13.0, 169 | "id" : "obj-16", 170 | "maxclass" : "newobj", 171 | "numinlets" : 2, 172 | "numoutlets" : 1, 173 | "outlettype" : [ "signal" ], 174 | "patching_rect" : [ 309.648865, 266.486023, 46.0, 23.0 ], 175 | "style" : "", 176 | "text" : "*~ 0.2" 177 | } 178 | 179 | } 180 | , { 181 | "box" : { 182 | "fontname" : "Arial", 183 | "fontsize" : 13.0, 184 | "id" : "obj-17", 185 | "maxclass" : "newobj", 186 | "numinlets" : 2, 187 | "numoutlets" : 1, 188 | "outlettype" : [ "signal" ], 189 | "patching_rect" : [ 309.648865, 234.653946, 41.0, 23.0 ], 190 | "style" : "", 191 | "text" : "+~ 1." 192 | } 193 | 194 | } 195 | , { 196 | "box" : { 197 | "fontname" : "Arial", 198 | "fontsize" : 13.0, 199 | "id" : "obj-18", 200 | "maxclass" : "newobj", 201 | "numinlets" : 1, 202 | "numoutlets" : 1, 203 | "outlettype" : [ "" ], 204 | "patching_rect" : [ 309.648865, 202.821884, 35.0, 23.0 ], 205 | "style" : "", 206 | "text" : "sin~" 207 | } 208 | 209 | } 210 | , { 211 | "box" : { 212 | "fontname" : "Arial", 213 | "fontsize" : 13.0, 214 | "id" : "obj-19", 215 | "maxclass" : "newobj", 216 | "numinlets" : 2, 217 | "numoutlets" : 1, 218 | "outlettype" : [ "signal" ], 219 | "patching_rect" : [ 155.7939, 299.732819, 173.0, 23.0 ], 220 | "style" : "", 221 | "text" : "*~" 222 | } 223 | 224 | } 225 | , { 226 | "box" : { 227 | "fontname" : "Arial", 228 | "fontsize" : 13.0, 229 | "id" : "obj-20", 230 | "maxclass" : "newobj", 231 | "numinlets" : 2, 232 | "numoutlets" : 1, 233 | "outlettype" : [ "signal" ], 234 | "patching_rect" : [ 309.648865, 170.28244, 70.0, 23.0 ], 235 | "style" : "", 236 | "text" : "phasor~ 2" 237 | } 238 | 239 | } 240 | , { 241 | "box" : { 242 | "fontname" : "Arial", 243 | "fontsize" : 13.0, 244 | "id" : "obj-21", 245 | "maxclass" : "newobj", 246 | "numinlets" : 2, 247 | "numoutlets" : 1, 248 | "outlettype" : [ "signal" ], 249 | "patching_rect" : [ 155.7939, 170.28244, 91.0, 23.0 ], 250 | "style" : "", 251 | "text" : "phasor~ 1000" 252 | } 253 | 254 | } 255 | , { 256 | "box" : { 257 | "fontname" : "Arial", 258 | "fontsize" : 13.0, 259 | "id" : "obj-22", 260 | "maxclass" : "newobj", 261 | "numinlets" : 1, 262 | "numoutlets" : 1, 263 | "outlettype" : [ "" ], 264 | "patching_rect" : [ 155.7939, 236.091599, 35.0, 23.0 ], 265 | "style" : "", 266 | "text" : "sin~" 267 | } 268 | 269 | } 270 | , { 271 | "box" : { 272 | "fontname" : "Arial", 273 | "fontsize" : 13.0, 274 | "id" : "obj-24", 275 | "maxclass" : "comment", 276 | "numinlets" : 1, 277 | "numoutlets" : 0, 278 | "patching_rect" : [ 167.465652, 195.748093, 86.0, 21.0 ], 279 | "style" : "", 280 | "text" : "input (0<->1)", 281 | "textcolor" : [ 0.336957, 0.336957, 0.336957, 1.0 ] 282 | } 283 | 284 | } 285 | , { 286 | "box" : { 287 | "fontname" : "Arial", 288 | "fontsize" : 13.0, 289 | "id" : "obj-25", 290 | "maxclass" : "comment", 291 | "numinlets" : 1, 292 | "numoutlets" : 0, 293 | "patching_rect" : [ 168.526718, 262.618317, 98.0, 21.0 ], 294 | "style" : "", 295 | "text" : "output (-1<->1)", 296 | "textcolor" : [ 0.336957, 0.336957, 0.336957, 1.0 ] 297 | } 298 | 299 | } 300 | , { 301 | "box" : { 302 | "fontname" : "Arial", 303 | "fontsize" : 13.0, 304 | "id" : "obj-26", 305 | "maxclass" : "comment", 306 | "numinlets" : 1, 307 | "numoutlets" : 0, 308 | "patching_rect" : [ 142.0, 143.0, 136.0, 21.0 ], 309 | "style" : "", 310 | "text" : "audio signal example" 311 | } 312 | 313 | } 314 | , { 315 | "box" : { 316 | "fontname" : "Arial", 317 | "fontsize" : 13.0, 318 | "id" : "obj-27", 319 | "maxclass" : "comment", 320 | "numinlets" : 1, 321 | "numoutlets" : 0, 322 | "patching_rect" : [ 283.122131, 143.0, 129.0, 21.0 ], 323 | "style" : "", 324 | "text" : "modulation example" 325 | } 326 | 327 | } 328 | , { 329 | "box" : { 330 | "border" : 0, 331 | "filename" : "helpdetails.js", 332 | "id" : "obj-2", 333 | "ignoreclick" : 1, 334 | "jsarguments" : [ "sin~" ], 335 | "maxclass" : "jsui", 336 | "numinlets" : 1, 337 | "numoutlets" : 1, 338 | "outlettype" : [ "" ], 339 | "parameter_enable" : 0, 340 | "patching_rect" : [ 10.0, 10.0, 620.0, 125.0 ] 341 | } 342 | 343 | } 344 | ], 345 | "lines" : [ { 346 | "patchline" : { 347 | "destination" : [ "obj-19", 1 ], 348 | "disabled" : 0, 349 | "hidden" : 0, 350 | "source" : [ "obj-16", 0 ] 351 | } 352 | 353 | } 354 | , { 355 | "patchline" : { 356 | "destination" : [ "obj-16", 0 ], 357 | "disabled" : 0, 358 | "hidden" : 0, 359 | "source" : [ "obj-17", 0 ] 360 | } 361 | 362 | } 363 | , { 364 | "patchline" : { 365 | "destination" : [ "obj-17", 0 ], 366 | "disabled" : 0, 367 | "hidden" : 0, 368 | "source" : [ "obj-18", 0 ] 369 | } 370 | 371 | } 372 | , { 373 | "patchline" : { 374 | "destination" : [ "obj-5", 0 ], 375 | "disabled" : 0, 376 | "hidden" : 0, 377 | "source" : [ "obj-19", 0 ] 378 | } 379 | 380 | } 381 | , { 382 | "patchline" : { 383 | "destination" : [ "obj-18", 0 ], 384 | "disabled" : 0, 385 | "hidden" : 0, 386 | "source" : [ "obj-20", 0 ] 387 | } 388 | 389 | } 390 | , { 391 | "patchline" : { 392 | "destination" : [ "obj-22", 0 ], 393 | "disabled" : 0, 394 | "hidden" : 0, 395 | "source" : [ "obj-21", 0 ] 396 | } 397 | 398 | } 399 | , { 400 | "patchline" : { 401 | "destination" : [ "obj-19", 0 ], 402 | "disabled" : 0, 403 | "hidden" : 0, 404 | "source" : [ "obj-22", 0 ] 405 | } 406 | 407 | } 408 | , { 409 | "patchline" : { 410 | "destination" : [ "obj-4", 1 ], 411 | "disabled" : 0, 412 | "hidden" : 0, 413 | "source" : [ "obj-5", 0 ] 414 | } 415 | 416 | } 417 | , { 418 | "patchline" : { 419 | "destination" : [ "obj-4", 0 ], 420 | "disabled" : 0, 421 | "hidden" : 0, 422 | "source" : [ "obj-5", 0 ] 423 | } 424 | 425 | } 426 | ], 427 | "bgfillcolor_type" : "gradient", 428 | "bgfillcolor_color1" : [ 0.454902, 0.462745, 0.482353, 1.0 ], 429 | "bgfillcolor_color2" : [ 0.290196, 0.309804, 0.301961, 1.0 ], 430 | "bgfillcolor_color" : [ 0.290196, 0.309804, 0.301961, 1.0 ], 431 | "bgfillcolor_angle" : 270.0, 432 | "bgfillcolor_proportion" : 0.39 433 | } 434 | , 435 | "patching_rect" : [ 10.0, 85.0, 50.0, 20.0 ], 436 | "saved_object_attributes" : { 437 | "description" : "", 438 | "digest" : "", 439 | "fontsize" : 13.0, 440 | "globalpatchername" : "", 441 | "style" : "", 442 | "tags" : "" 443 | } 444 | , 445 | "style" : "", 446 | "text" : "p basic", 447 | "varname" : "basic_tab" 448 | } 449 | 450 | } 451 | , { 452 | "box" : { 453 | "border" : 0, 454 | "filename" : "helpname.js", 455 | "id" : "obj-4", 456 | "ignoreclick" : 1, 457 | "jsarguments" : [ "cos~" ], 458 | "maxclass" : "jsui", 459 | "numinlets" : 1, 460 | "numoutlets" : 1, 461 | "outlettype" : [ "" ], 462 | "parameter_enable" : 0, 463 | "patching_rect" : [ 10.0, 10.0, 305.0, 55.0 ] 464 | } 465 | 466 | } 467 | , { 468 | "box" : { 469 | "fontname" : "Arial", 470 | "fontsize" : 12.0, 471 | "id" : "obj-5", 472 | "maxclass" : "newobj", 473 | "numinlets" : 0, 474 | "numoutlets" : 0, 475 | "patcher" : { 476 | "fileversion" : 1, 477 | "appversion" : { 478 | "major" : 7, 479 | "minor" : 2, 480 | "revision" : 1, 481 | "architecture" : "x64", 482 | "modernui" : 1 483 | } 484 | , 485 | "rect" : [ 0.0, 26.0, 666.0, 463.0 ], 486 | "bglocked" : 0, 487 | "openinpresentation" : 0, 488 | "default_fontsize" : 12.0, 489 | "default_fontface" : 0, 490 | "default_fontname" : "Arial", 491 | "gridonopen" : 1, 492 | "gridsize" : [ 15.0, 15.0 ], 493 | "gridsnaponopen" : 1, 494 | "objectsnaponopen" : 1, 495 | "statusbarvisible" : 2, 496 | "toolbarvisible" : 1, 497 | "lefttoolbarpinned" : 0, 498 | "toptoolbarpinned" : 0, 499 | "righttoolbarpinned" : 0, 500 | "bottomtoolbarpinned" : 0, 501 | "toolbars_unpinned_last_save" : 0, 502 | "tallnewobj" : 0, 503 | "boxanimatetime" : 200, 504 | "enablehscroll" : 1, 505 | "enablevscroll" : 1, 506 | "devicewidth" : 0.0, 507 | "description" : "", 508 | "digest" : "", 509 | "tags" : "", 510 | "style" : "", 511 | "subpatcher_template" : "", 512 | "showontab" : 1, 513 | "boxes" : [ ], 514 | "lines" : [ ], 515 | "bgfillcolor_type" : "gradient", 516 | "bgfillcolor_color1" : [ 0.454902, 0.462745, 0.482353, 1.0 ], 517 | "bgfillcolor_color2" : [ 0.290196, 0.309804, 0.301961, 1.0 ], 518 | "bgfillcolor_color" : [ 0.290196, 0.309804, 0.301961, 1.0 ], 519 | "bgfillcolor_angle" : 270.0, 520 | "bgfillcolor_proportion" : 0.39 521 | } 522 | , 523 | "patching_rect" : [ 205.0, 205.0, 50.0, 20.0 ], 524 | "saved_object_attributes" : { 525 | "description" : "", 526 | "digest" : "", 527 | "globalpatchername" : "", 528 | "style" : "", 529 | "tags" : "" 530 | } 531 | , 532 | "style" : "", 533 | "text" : "p ?", 534 | "varname" : "q_tab" 535 | } 536 | 537 | } 538 | ], 539 | "lines" : [ ], 540 | "parameters" : { 541 | "obj-2::obj-5" : [ "live.gain~", "live.gain~", 0 ] 542 | } 543 | , 544 | "dependency_cache" : [ { 545 | "name" : "helpname.js", 546 | "bootpath" : "~/Code/Max/maxmsp-misc/help/resources", 547 | "type" : "TEXT", 548 | "implicit" : 1 549 | } 550 | , { 551 | "name" : "helpdetails.js", 552 | "bootpath" : "~/Code/Max/maxmsp-misc/help/resources", 553 | "type" : "TEXT", 554 | "implicit" : 1 555 | } 556 | , { 557 | "name" : "helpstarter.js", 558 | "bootpath" : "~/Code/Max/maxmsp-misc/help/resources", 559 | "type" : "TEXT", 560 | "implicit" : 1 561 | } 562 | ], 563 | "autosave" : 0 564 | } 565 | 566 | } 567 | -------------------------------------------------------------------------------- /help/dict.edit.maxhelp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 3, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "box", 13 | "rect" : [ 59.0, 104.0, 1184.0, 992.0 ], 14 | "bglocked" : 0, 15 | "openinpresentation" : 0, 16 | "default_fontsize" : 13.0, 17 | "default_fontface" : 0, 18 | "default_fontname" : "Ableton Sans Light Regular", 19 | "gridonopen" : 1, 20 | "gridsize" : [ 5.0, 5.0 ], 21 | "gridsnaponopen" : 2, 22 | "objectsnaponopen" : 0, 23 | "statusbarvisible" : 2, 24 | "toolbarvisible" : 1, 25 | "lefttoolbarpinned" : 2, 26 | "toptoolbarpinned" : 2, 27 | "righttoolbarpinned" : 2, 28 | "bottomtoolbarpinned" : 2, 29 | "toolbars_unpinned_last_save" : 15, 30 | "tallnewobj" : 0, 31 | "boxanimatetime" : 200, 32 | "enablehscroll" : 1, 33 | "enablevscroll" : 1, 34 | "devicewidth" : 0.0, 35 | "description" : "", 36 | "digest" : "", 37 | "tags" : "", 38 | "style" : "", 39 | "subpatcher_template" : "tap.dark-template", 40 | "boxes" : [ { 41 | "box" : { 42 | "id" : "obj-7", 43 | "maxclass" : "panel", 44 | "numinlets" : 1, 45 | "numoutlets" : 0, 46 | "patching_rect" : [ 849.0, 176.0, 128.0, 128.0 ], 47 | "rounded" : 66 48 | } 49 | 50 | } 51 | , { 52 | "box" : { 53 | "id" : "obj-37", 54 | "maxclass" : "newobj", 55 | "numinlets" : 2, 56 | "numoutlets" : 2, 57 | "outlettype" : [ "int", "int" ], 58 | "patching_rect" : [ 524.0, 696.0, 61.0, 24.0 ], 59 | "text" : "maximum" 60 | } 61 | 62 | } 63 | , { 64 | "box" : { 65 | "id" : "obj-33", 66 | "linecount" : 5, 67 | "maxclass" : "comment", 68 | "numinlets" : 1, 69 | "numoutlets" : 0, 70 | "patching_rect" : [ 192.0, 769.0, 203.0, 85.0 ], 71 | "text" : "maybe there is some way to figure out the mouse was clicked in the region but no new number came out using the mouse state object or something?" 72 | } 73 | 74 | } 75 | , { 76 | "box" : { 77 | "id" : "obj-32", 78 | "linecount" : 3, 79 | "maxclass" : "comment", 80 | "numinlets" : 1, 81 | "numoutlets" : 0, 82 | "patching_rect" : [ 192.0, 716.0, 195.0, 53.0 ], 83 | "text" : "there is no way to know when a row is \"unselected\" without changes to the Max kernel." 84 | } 85 | 86 | } 87 | , { 88 | "box" : { 89 | "id" : "obj-12", 90 | "maxclass" : "comment", 91 | "numinlets" : 1, 92 | "numoutlets" : 0, 93 | "patching_rect" : [ 192.0, 690.0, 110.0, 22.0 ], 94 | "text" : "last selected row" 95 | } 96 | 97 | } 98 | , { 99 | "box" : { 100 | "id" : "obj-15", 101 | "maxclass" : "button", 102 | "numinlets" : 1, 103 | "numoutlets" : 1, 104 | "outlettype" : [ "bang" ], 105 | "parameter_enable" : 0, 106 | "patching_rect" : [ 128.0, 643.5, 24.0, 24.0 ] 107 | } 108 | 109 | } 110 | , { 111 | "box" : { 112 | "id" : "obj-13", 113 | "maxclass" : "message", 114 | "numinlets" : 2, 115 | "numoutlets" : 1, 116 | "outlettype" : [ "" ], 117 | "patching_rect" : [ 128.0, 690.0, 62.0, 24.0 ], 118 | "text" : "\"3\"" 119 | } 120 | 121 | } 122 | , { 123 | "box" : { 124 | "fontsize" : 12.0, 125 | "id" : "obj-8", 126 | "linecount" : 4, 127 | "maxclass" : "comment", 128 | "numinlets" : 1, 129 | "numoutlets" : 0, 130 | "patching_rect" : [ 712.0, 787.0, 189.0, 64.0 ], 131 | "text" : "just filling in dummy values, but instead you could pop up a patcher with a UI to set the values you want" 132 | } 133 | 134 | } 135 | , { 136 | "box" : { 137 | "id" : "obj-6", 138 | "maxclass" : "newobj", 139 | "numinlets" : 2, 140 | "numoutlets" : 1, 141 | "outlettype" : [ "int" ], 142 | "patching_rect" : [ 524.0, 755.0, 29.5, 24.0 ], 143 | "text" : "+ 1" 144 | } 145 | 146 | } 147 | , { 148 | "box" : { 149 | "id" : "obj-22", 150 | "maxclass" : "newobj", 151 | "numinlets" : 1, 152 | "numoutlets" : 2, 153 | "outlettype" : [ "bang", "" ], 154 | "patching_rect" : [ 524.0, 532.0, 30.0, 24.0 ], 155 | "text" : "t b l" 156 | } 157 | 158 | } 159 | , { 160 | "box" : { 161 | "id" : "obj-21", 162 | "maxclass" : "newobj", 163 | "numinlets" : 2, 164 | "numoutlets" : 2, 165 | "outlettype" : [ "", "" ], 166 | "patching_rect" : [ 524.0, 663.0, 54.0, 24.0 ], 167 | "text" : "zl.group" 168 | } 169 | 170 | } 171 | , { 172 | "box" : { 173 | "id" : "obj-14", 174 | "maxclass" : "newobj", 175 | "numinlets" : 1, 176 | "numoutlets" : 1, 177 | "outlettype" : [ "" ], 178 | "patching_rect" : [ 540.0, 600.0, 74.0, 24.0 ], 179 | "text" : "fromsymbol" 180 | } 181 | 182 | } 183 | , { 184 | "box" : { 185 | "id" : "obj-10", 186 | "maxclass" : "newobj", 187 | "numinlets" : 1, 188 | "numoutlets" : 6, 189 | "outlettype" : [ "signal", "bang", "int", "float", "", "list" ], 190 | "patching_rect" : [ 540.0, 627.0, 71.5, 24.0 ], 191 | "text" : "typeroute~" 192 | } 193 | 194 | } 195 | , { 196 | "box" : { 197 | "id" : "obj-9", 198 | "maxclass" : "newobj", 199 | "numinlets" : 1, 200 | "numoutlets" : 1, 201 | "outlettype" : [ "" ], 202 | "patching_rect" : [ 540.0, 571.0, 27.0, 24.0 ], 203 | "text" : "iter" 204 | } 205 | 206 | } 207 | , { 208 | "box" : { 209 | "id" : "obj-30", 210 | "maxclass" : "newobj", 211 | "numinlets" : 1, 212 | "numoutlets" : 1, 213 | "outlettype" : [ "" ], 214 | "patching_rect" : [ 524.0, 791.0, 59.0, 24.0 ], 215 | "text" : "tosymbol" 216 | } 217 | 218 | } 219 | , { 220 | "box" : { 221 | "id" : "obj-29", 222 | "maxclass" : "message", 223 | "numinlets" : 2, 224 | "numoutlets" : 1, 225 | "outlettype" : [ "" ], 226 | "patching_rect" : [ 524.0, 819.0, 198.0, 24.0 ], 227 | "text" : "set $1 output 0 \"\" 0" 228 | } 229 | 230 | } 231 | , { 232 | "box" : { 233 | "id" : "obj-27", 234 | "maxclass" : "number", 235 | "numinlets" : 1, 236 | "numoutlets" : 2, 237 | "outlettype" : [ "", "bang" ], 238 | "parameter_enable" : 0, 239 | "patching_rect" : [ 524.0, 727.0, 50.0, 24.0 ] 240 | } 241 | 242 | } 243 | , { 244 | "box" : { 245 | "id" : "obj-24", 246 | "maxclass" : "message", 247 | "numinlets" : 2, 248 | "numoutlets" : 1, 249 | "outlettype" : [ "" ], 250 | "patching_rect" : [ 466.0, 464.0, 52.0, 24.0 ], 251 | "text" : "getkeys" 252 | } 253 | 254 | } 255 | , { 256 | "box" : { 257 | "id" : "obj-23", 258 | "maxclass" : "button", 259 | "numinlets" : 1, 260 | "numoutlets" : 1, 261 | "outlettype" : [ "bang" ], 262 | "parameter_enable" : 0, 263 | "patching_rect" : [ 63.0, 643.5, 24.0, 24.0 ] 264 | } 265 | 266 | } 267 | , { 268 | "box" : { 269 | "handoff" : "", 270 | "id" : "obj-20", 271 | "maxclass" : "ubutton", 272 | "numinlets" : 1, 273 | "numoutlets" : 4, 274 | "outlettype" : [ "bang", "bang", "", "int" ], 275 | "parameter_enable" : 0, 276 | "patching_rect" : [ 63.0, 593.5, 47.0, 34.0 ] 277 | } 278 | 279 | } 280 | , { 281 | "box" : { 282 | "fontsize" : 24.0, 283 | "id" : "obj-18", 284 | "maxclass" : "comment", 285 | "numinlets" : 1, 286 | "numoutlets" : 0, 287 | "patching_rect" : [ 70.0, 593.5, 33.0, 35.0 ], 288 | "text" : "+" 289 | } 290 | 291 | } 292 | , { 293 | "box" : { 294 | "id" : "obj-5", 295 | "maxclass" : "newobj", 296 | "numinlets" : 1, 297 | "numoutlets" : 1, 298 | "outlettype" : [ "bang" ], 299 | "patching_rect" : [ 19.0, 13.0, 61.0, 24.0 ], 300 | "text" : "loadbang" 301 | } 302 | 303 | } 304 | , { 305 | "box" : { 306 | "id" : "obj-4", 307 | "maxclass" : "newobj", 308 | "numinlets" : 1, 309 | "numoutlets" : 1, 310 | "outlettype" : [ "bang" ], 311 | "patching_rect" : [ 481.0, 21.0, 61.0, 24.0 ], 312 | "text" : "loadbang" 313 | } 314 | 315 | } 316 | , { 317 | "box" : { 318 | "id" : "obj-3", 319 | "maxclass" : "message", 320 | "numinlets" : 2, 321 | "numoutlets" : 1, 322 | "outlettype" : [ "" ], 323 | "patching_rect" : [ 50.0, 47.0, 86.0, 24.0 ], 324 | "text" : "dictionary bar" 325 | } 326 | 327 | } 328 | , { 329 | "box" : { 330 | "data" : { 331 | "name" : [ "Type", "On", "Device / Protocol", "SubNet", "Universe" ], 332 | "type" : [ "static", "toggle", "text", [ 0, 1, 2, 3, "foo" ], { 333 | "integer" : [ 0, 255 ] 334 | } 335 | ], 336 | "width" : [ 60, 40, 200, 60, 60 ], 337 | "1" : [ "input", 1, "Art-Net", 3, 0 ], 338 | "2" : [ "input", 0, "Enttec DMX USB Pro", 0, 33 ], 339 | "3" : [ "input", 0, "Art-Net", 2, 255 ], 340 | "5" : [ "output", 1, "", "foo", 55 ], 341 | "7" : [ "output", 1, "foo bar", 0, 0 ] 342 | } 343 | , 344 | "id" : "obj-1", 345 | "maxclass" : "newobj", 346 | "numinlets" : 2, 347 | "numoutlets" : 4, 348 | "outlettype" : [ "dictionary", "", "", "" ], 349 | "patching_rect" : [ 466.0, 501.0, 116.0, 24.0 ], 350 | "saved_object_attributes" : { 351 | "embed" : 1, 352 | "parameter_enable" : 0, 353 | "parameter_mappable" : 0 354 | } 355 | , 356 | "text" : "dict bar @embed 1" 357 | } 358 | 359 | } 360 | , { 361 | "box" : { 362 | "id" : "obj-2", 363 | "maxclass" : "button", 364 | "numinlets" : 1, 365 | "numoutlets" : 1, 366 | "outlettype" : [ "bang" ], 367 | "parameter_enable" : 0, 368 | "patching_rect" : [ 19.0, 47.0, 24.0, 24.0 ] 369 | } 370 | 371 | } 372 | , { 373 | "box" : { 374 | "id" : "obj-17", 375 | "maxclass" : "message", 376 | "numinlets" : 2, 377 | "numoutlets" : 1, 378 | "outlettype" : [ "" ], 379 | "patching_rect" : [ 481.0, 54.0, 86.0, 24.0 ], 380 | "text" : "dictionary bar" 381 | } 382 | 383 | } 384 | , { 385 | "box" : { 386 | "id" : "obj-16", 387 | "maxclass" : "dict.view", 388 | "numinlets" : 1, 389 | "numoutlets" : 0, 390 | "patching_rect" : [ 481.0, 85.0, 285.0, 355.0 ] 391 | } 392 | 393 | } 394 | , { 395 | "box" : { 396 | "color" : [ 1.0, 1.0, 1.0, 1.0 ], 397 | "id" : "obj-11", 398 | "maxclass" : "dict.edit", 399 | "numinlets" : 1, 400 | "numoutlets" : 1, 401 | "outlettype" : [ "" ], 402 | "patching_rect" : [ 19.0, 85.0, 422.0, 355.0 ] 403 | } 404 | 405 | } 406 | , { 407 | "box" : { 408 | "id" : "obj-19", 409 | "maxclass" : "panel", 410 | "numinlets" : 1, 411 | "numoutlets" : 0, 412 | "patching_rect" : [ 63.0, 593.5, 47.0, 34.0 ] 413 | } 414 | 415 | } 416 | , { 417 | "box" : { 418 | "handoff" : "", 419 | "id" : "obj-26", 420 | "maxclass" : "ubutton", 421 | "numinlets" : 1, 422 | "numoutlets" : 4, 423 | "outlettype" : [ "bang", "bang", "", "int" ], 424 | "parameter_enable" : 0, 425 | "patching_rect" : [ 128.0, 593.5, 47.0, 34.0 ] 426 | } 427 | 428 | } 429 | , { 430 | "box" : { 431 | "fontsize" : 24.0, 432 | "id" : "obj-28", 433 | "maxclass" : "comment", 434 | "numinlets" : 1, 435 | "numoutlets" : 0, 436 | "patching_rect" : [ 135.0, 593.5, 33.0, 35.0 ], 437 | "text" : "-" 438 | } 439 | 440 | } 441 | , { 442 | "box" : { 443 | "id" : "obj-31", 444 | "maxclass" : "panel", 445 | "numinlets" : 1, 446 | "numoutlets" : 0, 447 | "patching_rect" : [ 128.0, 593.5, 47.0, 34.0 ] 448 | } 449 | 450 | } 451 | , { 452 | "box" : { 453 | "id" : "obj-35", 454 | "maxclass" : "message", 455 | "numinlets" : 2, 456 | "numoutlets" : 1, 457 | "outlettype" : [ "" ], 458 | "patching_rect" : [ 128.0, 721.0, 68.0, 24.0 ], 459 | "text" : "remove $1" 460 | } 461 | 462 | } 463 | ], 464 | "lines" : [ { 465 | "patchline" : { 466 | "destination" : [ "obj-22", 0 ], 467 | "source" : [ "obj-1", 2 ] 468 | } 469 | 470 | } 471 | , { 472 | "patchline" : { 473 | "destination" : [ "obj-21", 0 ], 474 | "source" : [ "obj-10", 2 ] 475 | } 476 | 477 | } 478 | , { 479 | "patchline" : { 480 | "destination" : [ "obj-13", 1 ], 481 | "source" : [ "obj-11", 0 ] 482 | } 483 | 484 | } 485 | , { 486 | "patchline" : { 487 | "destination" : [ "obj-35", 0 ], 488 | "source" : [ "obj-13", 0 ] 489 | } 490 | 491 | } 492 | , { 493 | "patchline" : { 494 | "destination" : [ "obj-10", 0 ], 495 | "source" : [ "obj-14", 0 ] 496 | } 497 | 498 | } 499 | , { 500 | "patchline" : { 501 | "destination" : [ "obj-13", 0 ], 502 | "source" : [ "obj-15", 0 ] 503 | } 504 | 505 | } 506 | , { 507 | "patchline" : { 508 | "destination" : [ "obj-16", 0 ], 509 | "source" : [ "obj-17", 0 ] 510 | } 511 | 512 | } 513 | , { 514 | "patchline" : { 515 | "destination" : [ "obj-11", 0 ], 516 | "source" : [ "obj-2", 0 ] 517 | } 518 | 519 | } 520 | , { 521 | "patchline" : { 522 | "destination" : [ "obj-23", 0 ], 523 | "source" : [ "obj-20", 0 ] 524 | } 525 | 526 | } 527 | , { 528 | "patchline" : { 529 | "destination" : [ "obj-37", 0 ], 530 | "source" : [ "obj-21", 0 ] 531 | } 532 | 533 | } 534 | , { 535 | "patchline" : { 536 | "destination" : [ "obj-21", 0 ], 537 | "source" : [ "obj-22", 0 ] 538 | } 539 | 540 | } 541 | , { 542 | "patchline" : { 543 | "destination" : [ "obj-9", 0 ], 544 | "source" : [ "obj-22", 1 ] 545 | } 546 | 547 | } 548 | , { 549 | "patchline" : { 550 | "destination" : [ "obj-24", 0 ], 551 | "source" : [ "obj-23", 0 ] 552 | } 553 | 554 | } 555 | , { 556 | "patchline" : { 557 | "destination" : [ "obj-1", 0 ], 558 | "source" : [ "obj-24", 0 ] 559 | } 560 | 561 | } 562 | , { 563 | "patchline" : { 564 | "destination" : [ "obj-15", 0 ], 565 | "source" : [ "obj-26", 0 ] 566 | } 567 | 568 | } 569 | , { 570 | "patchline" : { 571 | "destination" : [ "obj-6", 0 ], 572 | "source" : [ "obj-27", 0 ] 573 | } 574 | 575 | } 576 | , { 577 | "patchline" : { 578 | "destination" : [ "obj-1", 0 ], 579 | "midpoints" : [ 533.5, 853.0, 445.0, 853.0, 445.0, 493.0, 475.5, 493.0 ], 580 | "source" : [ "obj-29", 0 ] 581 | } 582 | 583 | } 584 | , { 585 | "patchline" : { 586 | "destination" : [ "obj-11", 0 ], 587 | "source" : [ "obj-3", 0 ] 588 | } 589 | 590 | } 591 | , { 592 | "patchline" : { 593 | "destination" : [ "obj-29", 0 ], 594 | "source" : [ "obj-30", 0 ] 595 | } 596 | 597 | } 598 | , { 599 | "patchline" : { 600 | "destination" : [ "obj-1", 0 ], 601 | "source" : [ "obj-35", 0 ] 602 | } 603 | 604 | } 605 | , { 606 | "patchline" : { 607 | "destination" : [ "obj-27", 0 ], 608 | "source" : [ "obj-37", 0 ] 609 | } 610 | 611 | } 612 | , { 613 | "patchline" : { 614 | "destination" : [ "obj-17", 0 ], 615 | "source" : [ "obj-4", 0 ] 616 | } 617 | 618 | } 619 | , { 620 | "patchline" : { 621 | "destination" : [ "obj-2", 0 ], 622 | "order" : 1, 623 | "source" : [ "obj-5", 0 ] 624 | } 625 | 626 | } 627 | , { 628 | "patchline" : { 629 | "destination" : [ "obj-3", 0 ], 630 | "order" : 0, 631 | "source" : [ "obj-5", 0 ] 632 | } 633 | 634 | } 635 | , { 636 | "patchline" : { 637 | "destination" : [ "obj-30", 0 ], 638 | "source" : [ "obj-6", 0 ] 639 | } 640 | 641 | } 642 | , { 643 | "patchline" : { 644 | "destination" : [ "obj-14", 0 ], 645 | "source" : [ "obj-9", 0 ] 646 | } 647 | 648 | } 649 | ], 650 | "dependency_cache" : [ { 651 | "name" : "dict.edit.mxo", 652 | "type" : "iLaX" 653 | } 654 | ], 655 | "autosave" : 0, 656 | "textcolor" : [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], 657 | "bgcolor" : [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], 658 | "editing_bgcolor" : [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] 659 | } 660 | 661 | } 662 | -------------------------------------------------------------------------------- /source/projects/dict.edit/dict.edit.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | dictedit - demonstrate use of jdataview 4 | Copyright 2020 - Cycling '74 5 | Timothy Place, tim@cycling74.com 6 | */ 7 | 8 | #include "c74_ui_dataview.h" 9 | 10 | using namespace c74::max; 11 | 12 | enum { 13 | kOutletParameterNames = 0, 14 | kOutletParameterValues, 15 | kOutletPresetNames, 16 | kOutletPluginNames, 17 | kNumContolOutlets 18 | }; 19 | 20 | 21 | typedef struct _dictedit_column { 22 | t_symbol* name; 23 | t_atom_long index; 24 | t_object* dataview_column; 25 | t_symbol* type; 26 | t_atom_long range[2]; 27 | bool use_range; 28 | } t_dictedit_column; 29 | 30 | typedef struct _dictedit { 31 | t_jbox d_box; 32 | void* d_outlet; 33 | t_object* d_dataview; ///< The dataview object 34 | t_hashtab* d_columns; ///< The dataview columns: column name -> column index 35 | t_dictionary* d_dict; 36 | t_symbol* d_name; 37 | } t_dictedit; 38 | 39 | 40 | // general prototypes 41 | void *dictedit_new(t_symbol *s, short argc, t_atom *argv); 42 | void dictedit_initdataview(t_dictedit *x); 43 | void dictedit_free(t_dictedit *x); 44 | void dictedit_newpatcherview(t_dictedit *x, t_object *patcherview); 45 | void dictedit_freepatcherview(t_dictedit *x, t_object *patcherview); 46 | t_max_err dictedit_notify(t_dictedit *x, t_symbol *s, t_symbol *msg, void *sender, void *data); 47 | void dictedit_assist(t_dictedit *x, void *b, long m, long a, char *s); 48 | void dictedit_bang(t_dictedit *x); 49 | void dictedit_getcelltext(t_dictedit *x, t_symbol *colname, t_rowref rr, char *text, long maxlen); 50 | void dictedit_getcellvalue(t_dictedit *x, t_symbol *colname, t_rowref rr, long *argc, t_atom *argv); 51 | 52 | void dictedit_setvalue(t_dictedit *x, t_symbol *colname, t_rowref rr, long argc, t_atom *argv); 53 | void dictedit_selectedrow(t_dictedit* self, t_rowref* rr); 54 | 55 | t_max_err dictedit_set_dictionary(t_dictedit *x, void *attr, long argc, t_atom *argv); 56 | void dictedit_toggle_component(t_object *x, t_symbol *colname, t_rowref rr, long *comptype, long *options, t_symbol **label); 57 | void dictedit_menu_component(t_object* self, t_symbol *colname, t_rowref rr, long *comptype, long *options, t_symbol **label); 58 | void dictedit_text_component(t_object* x, t_symbol *colname, t_rowref rr, long *comptype, long *options, t_symbol **label); 59 | void dictedit_integer_component(t_object* x, t_symbol *colname, t_rowref rr, long *comptype, long *options, t_symbol **label); 60 | void dictedit_getcellmenu(t_dictedit *x, t_symbol *colname, t_rowref rr, long *argc, t_atom *argv, char **enabled, long *currentitemindex); 61 | 62 | 63 | static t_class *s_dictedit_class = NULL; 64 | static t_symbol *ps_nothing; 65 | static t_symbol *ps_modified; 66 | static t_symbol *ps_name; 67 | static t_symbol *ps_type; 68 | 69 | 70 | /************************************************************************************/ 71 | 72 | void ext_main(void* r) { 73 | t_class* c = class_new("dict.edit", (method)dictedit_new, (method)dictedit_free, sizeof(t_dictedit), (method)0L, A_GIMME, 0); 74 | c->c_flags |= CLASS_FLAG_NEWDICTIONARY; 75 | 76 | jbox_initclass(c, JBOX_COLOR); 77 | 78 | class_addmethod(c, (method)dictedit_bang, "bang", 0); // refresh 79 | class_addmethod(c, (method)dictedit_getcelltext, "getcelltext", A_CANT, 0); 80 | class_addmethod(c, (method)dictedit_getcellvalue, "getcellvalue", A_CANT, 0); 81 | class_addmethod(c, (method)dictedit_setvalue, "setvalue", A_CANT, 0); 82 | class_addmethod(c, (method)dictedit_selectedrow, "selectedrow", A_CANT, 0); 83 | 84 | class_addmethod(c, (method)dictedit_newpatcherview, "newpatcherview", A_CANT, 0); 85 | class_addmethod(c, (method)dictedit_freepatcherview, "freepatcherview", A_CANT, 0); 86 | class_addmethod(c, (method)dictedit_notify, "notify", A_CANT, 0); 87 | class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0); 88 | class_addmethod(c, (method)dictedit_toggle_component, "dictedit_toggle_component", A_CANT, 0); 89 | 90 | class_addmethod(c, (method)dictedit_menu_component, "dictedit_menu_component", A_CANT, 0); 91 | class_addmethod(c, (method)dictedit_text_component, "dictedit_text_component", A_CANT, 0); 92 | class_addmethod(c, (method)dictedit_integer_component, "dictedit_integer_component", A_CANT, 0); 93 | class_addmethod(c, (method)dictedit_getcellmenu, "getcellmenu", A_CANT, 0); 94 | 95 | CLASS_ATTR_SYM(c, "dictionary", 0, t_dictedit, d_name); 96 | CLASS_ATTR_ACCESSORS(c, "dictionary", NULL, dictedit_set_dictionary); 97 | 98 | class_register(CLASS_BOX, c); 99 | s_dictedit_class = c; 100 | 101 | ps_nothing = gensym(""); 102 | ps_modified = gensym("modified"); 103 | ps_name = gensym("name"); 104 | ps_type = gensym("type"); 105 | } 106 | 107 | 108 | /************************************************************************************/ 109 | // Object Creation Method 110 | 111 | void *dictedit_new(t_symbol *s, short argc, t_atom *argv) { 112 | t_dictedit* x; 113 | t_dictionary* d = NULL; 114 | 115 | if (!(d=object_dictionaryarg(argc, argv))) 116 | return NULL; 117 | 118 | x = (t_dictedit*)object_alloc(s_dictedit_class); 119 | if (x) { 120 | long flags = 0 121 | | JBOX_DRAWFIRSTIN 122 | | JBOX_NODRAWBOX 123 | | JBOX_DRAWINLAST 124 | // | JBOX_TRANSPARENT 125 | // | JBOX_NOGROW 126 | // | JBOX_GROWY 127 | | JBOX_GROWBOTH 128 | // | JBOX_IGNORELOCKCLICK 129 | | JBOX_HILITE 130 | // | JBOX_BACKGROUND 131 | // | JBOX_NOFLOATINSPECTOR 132 | // | JBOX_TEXTFIELD 133 | ; 134 | 135 | jbox_new(&x->d_box, flags, argc, argv); 136 | x->d_name = ps_nothing; 137 | x->d_box.b_firstin = (t_object *)x; 138 | x->d_outlet = outlet_new(x, NULL); 139 | 140 | x->d_columns = hashtab_new(13); 141 | hashtab_flags(x->d_columns, OBJ_FLAG_DATA); 142 | 143 | dictedit_initdataview(x); 144 | attr_dictionary_process(x, d); 145 | 146 | jbox_ready(&x->d_box); 147 | } 148 | return x; 149 | } 150 | 151 | 152 | void dictedit_initdataview(t_dictedit *x) { 153 | x->d_dataview = (t_object*)jdataview_new(); 154 | jdataview_setclient(x->d_dataview, (t_object*)x); 155 | jdataview_setcolumnheaderheight(x->d_dataview, 40); 156 | jdataview_setheight(x->d_dataview, 16); 157 | } 158 | 159 | 160 | void dictedit_free(t_dictedit* x) { 161 | jbox_free(&x->d_box); 162 | object_free(x->d_dataview); 163 | 164 | if (x->d_dict) 165 | dictobj_release(x->d_dict); 166 | 167 | } 168 | 169 | 170 | void dictedit_newpatcherview(t_dictedit* x, t_object* patcherview) { 171 | jdataview_patchervis(x->d_dataview, patcherview, (t_object*)x); 172 | } 173 | 174 | void dictedit_freepatcherview(t_dictedit *x, t_object *patcherview) { 175 | jdataview_patcherinvis(x->d_dataview, patcherview); 176 | } 177 | 178 | 179 | t_max_err dictedit_notify(t_dictedit *x, t_symbol *s, t_symbol *msg, void *sender, void *data) { 180 | if (sender == x->d_dict && msg == ps_modified) { 181 | dictedit_bang(x); 182 | return MAX_ERR_NONE; 183 | } 184 | else 185 | return jbox_notify((t_jbox *)x, s, msg, sender, data); 186 | } 187 | 188 | 189 | 190 | t_symbol* dictedit_getkey(t_dictedit *x, t_rowref rr) { 191 | return (t_symbol*)rr; 192 | } 193 | 194 | 195 | t_dictedit_column* dictedit_getcolumn(t_dictedit *x, t_symbol *colname) { 196 | t_dictedit_column* dcolumn = nullptr; 197 | t_max_err err = hashtab_lookup(x->d_columns, colname, (t_object**)&dcolumn); 198 | 199 | if (err) 200 | return nullptr; 201 | else 202 | return dcolumn; 203 | } 204 | 205 | 206 | /************************************************************************************/ 207 | // Methods bound to input/inlets 208 | 209 | 210 | void dictedit_toggle_component(t_object *x, t_symbol *colname, t_rowref rr, long *comptype, long *options, t_symbol **label) { 211 | *comptype = JCOLUMN_COMPONENT_CHECKBOX; 212 | } 213 | 214 | 215 | void dictedit_menu_component(t_object* self, t_symbol *colname, t_rowref rr, long *comptype, long *options, t_symbol **label) { 216 | *comptype = JCOLUMN_COMPONENT_MENU; 217 | *options = /*JCOLUMN_MENU_INDEX |*/ JCOLUMN_MENU_SELECT; 218 | } 219 | 220 | 221 | void dictedit_text_component(t_object* x, t_symbol *colname, t_rowref rr, long *comptype, long *options, t_symbol **label) { 222 | *comptype = JCOLUMN_COMPONENT_TEXTEDITOR; 223 | *options = JCOLUMN_TEXT_ONESYMBOL; 224 | } 225 | 226 | 227 | void dictedit_integer_component(t_object* x, t_symbol *colname, t_rowref rr, long *comptype, long *options, t_symbol **label) { 228 | *comptype = JCOLUMN_COMPONENT_TEXTEDITOR; 229 | // *options = JCOLUMN_TEXT_INT; 230 | // the above doesn't work, causes memory corruption when scrolling the number outside of the inspector context 231 | } 232 | 233 | 234 | void dictedit_bang(t_dictedit *x) { 235 | jdataview_clear(x->d_dataview); 236 | 237 | t_atom* names = NULL; 238 | long namecount = 0; 239 | t_atom* types = NULL; 240 | long typecount = 0; 241 | t_atom* widths = NULL; 242 | long widthcount = 0; // TODO: leaking! 243 | 244 | dictionary_getatoms(x->d_dict, ps_name, &namecount, &names); 245 | dictionary_getatoms(x->d_dict, ps_type, &typecount, &types); 246 | dictionary_getatoms(x->d_dict, gensym("width"), &widthcount, &widths); 247 | 248 | for (auto i=0; id_columns, atom_getsym(names+i), &column_index); 252 | t_max_err err = hashtab_lookup(x->d_columns, atom_getsym(names+i), (t_object**)&dcolumn); 253 | 254 | if (!err) { 255 | // column already exists, so we leave it alone 256 | } 257 | else { 258 | dcolumn = new t_dictedit_column; 259 | dcolumn->name = atom_getsym(names+i); 260 | // dcolumn->type = 261 | dcolumn->use_range = false; 262 | dcolumn->index = i; 263 | dcolumn->dataview_column = jdataview_addcolumn(x->d_dataview, dcolumn->name, NULL, true); 264 | 265 | jcolumn_setlabel(dcolumn->dataview_column, atom_getsym(names+i)); 266 | 267 | if (atomisatomarray(types+i)) { 268 | dcolumn->type = gensym("enum"); 269 | jcolumn_setrowcomponentmsg(dcolumn->dataview_column, gensym("dictedit_menu_component")); 270 | jcolumn_setvaluemsg(dcolumn->dataview_column, gensym("setvalue"), nullptr, nullptr); 271 | } 272 | else if (atomisdictionary(types+i)) { 273 | t_dictionary* d = (t_dictionary*)atom_getobj(types+i); 274 | long keycount = 0; 275 | t_symbol** keys = nullptr; 276 | 277 | dictionary_getkeys(d, &keycount, &keys); 278 | if (keycount) { 279 | t_symbol* type = keys[0]; 280 | 281 | if (type == gensym("integer")) { 282 | long range_ac = 0; 283 | t_atom* range_av = nullptr; 284 | 285 | dictionary_getatoms(d, type, &range_ac, &range_av); 286 | 287 | if (range_ac == 2) { 288 | dcolumn->range[0] = atom_getlong(range_av+0); 289 | dcolumn->range[1] = atom_getlong(range_av+1); 290 | dcolumn->use_range = true; 291 | } 292 | 293 | // warning: duplicating code from below 294 | dcolumn->type = type; 295 | //jcolumn_setnumeric(column, true); 296 | jcolumn_setrowcomponentmsg(dcolumn->dataview_column, gensym("dictedit_integer_component")); 297 | jcolumn_setvaluemsg(dcolumn->dataview_column, gensym("setvalue"),NULL,NULL); 298 | } 299 | sysmem_freeptr(keys); 300 | } 301 | } 302 | else { 303 | if (atom_getsym(types+i) == gensym("toggle")) { 304 | dcolumn->type = atom_getsym(types+i); 305 | jcolumn_setcheckbox(dcolumn->dataview_column, gensym("setvalue")); // this sets numeric 306 | jcolumn_setrowcomponentmsg(dcolumn->dataview_column, gensym("dictedit_toggle_component")); 307 | } 308 | else if (atom_getsym(types+i) == gensym("text")) { 309 | dcolumn->type = atom_getsym(types+i); 310 | jcolumn_setrowcomponentmsg(dcolumn->dataview_column, gensym("dictedit_text_component")); 311 | jcolumn_setvaluemsg(dcolumn->dataview_column, gensym("setvalue"),NULL,NULL); 312 | } 313 | else if (atom_getsym(types+i) == gensym("integer")) { 314 | dcolumn->type = atom_getsym(types+i); 315 | //jcolumn_setnumeric(column, true); 316 | jcolumn_setrowcomponentmsg(dcolumn->dataview_column, gensym("dictedit_integer_component")); 317 | jcolumn_setvaluemsg(dcolumn->dataview_column, gensym("setvalue"),NULL,NULL); 318 | } 319 | else { 320 | dcolumn->type = gensym("static"); 321 | } 322 | } 323 | 324 | if (widthcount) 325 | jcolumn_setwidth(dcolumn->dataview_column, (long)atom_getlong(widths+i)); 326 | 327 | hashtab_store(x->d_columns, atom_getsym(names+i), (t_object*)dcolumn); 328 | 329 | } 330 | } 331 | 332 | long keycount = 0; 333 | t_symbol** keys = nullptr; 334 | 335 | dictionary_getkeys_ordered(x->d_dict, &keycount, &keys); 336 | 337 | t_rowref* rowrefs = (t_rowref*)malloc(sizeof(t_rowref) * keycount); 338 | int j = 0; 339 | 340 | for (auto i=0; id_dataview, j, rowrefs); 351 | free(rowrefs); 352 | } 353 | 354 | 355 | void dictedit_getcelltext(t_dictedit *x, t_symbol *colname, t_rowref rr, char *text, long maxlen) { 356 | t_max_err err; 357 | long ac = 0; 358 | t_atom* av = NULL; 359 | t_symbol* key = dictedit_getkey(x, rr); 360 | auto dcolumn = dictedit_getcolumn(x, colname); 361 | 362 | err = dictionary_getatoms(x->d_dict, key, &ac, &av); 363 | if (!err) { 364 | long textsize = 0; 365 | char* itemtext = nullptr; 366 | 367 | atom_gettext(1, av+(dcolumn->index), &textsize, &itemtext, OBEX_UTIL_ATOM_GETTEXT_SYM_NO_QUOTE); 368 | 369 | if (itemtext && itemtext[0]) { 370 | strncpy(text, itemtext, maxlen-1); 371 | sysmem_freeptr(itemtext); 372 | } 373 | } 374 | } 375 | 376 | 377 | void dictedit_getcellvalue(t_dictedit *x, t_symbol *colname, t_rowref rr, long *argc, t_atom *argv) { 378 | t_max_err err; 379 | long ac = 0; 380 | t_atom* av = NULL; 381 | t_symbol* key = dictedit_getkey(x, rr); 382 | auto dcolumn = dictedit_getcolumn(x, colname); 383 | 384 | *argc = 1; 385 | 386 | err = dictionary_getatoms(x->d_dict, key, &ac, &av); 387 | 388 | if (!err) 389 | *argv = *(av+(dcolumn->index)); 390 | } 391 | 392 | 393 | void dictedit_getcellmenu(t_dictedit *x, t_symbol *colname, t_rowref rr, long *argc, t_atom *argv, char **enabled, long *currentitemindex) 394 | { 395 | auto dcolumn = dictedit_getcolumn(x, colname); 396 | t_atom* types = NULL; 397 | long typecount = 0; 398 | 399 | dictionary_getatoms(x->d_dict, ps_type, &typecount, &types); 400 | 401 | t_atomarray* aa = (t_atomarray*)atom_getobj(types+(dcolumn->index)); 402 | long ac = 0; 403 | t_atom* av = nullptr; 404 | 405 | atomarray_getatoms(aa, &ac, &av); 406 | 407 | *argc = ac; 408 | *enabled = sysmem_newptr(ac); 409 | for (auto i=0; id_dict, key, &ac, &av); 427 | 428 | if (!err) { 429 | if (dcolumn->type == gensym("integer")) { 430 | auto val = atom_getlong(argv); 431 | 432 | if (dcolumn->use_range) { 433 | if (val < dcolumn->range[0]) 434 | val = dcolumn->range[0]; 435 | else if (val > dcolumn->range[1]) 436 | val = dcolumn->range[1]; 437 | } 438 | atom_setlong(av+(dcolumn->index), val); 439 | } 440 | else 441 | *(av+(dcolumn->index)) = *argv; 442 | } 443 | object_notify(x->d_dict, ps_modified, nullptr); 444 | } 445 | 446 | 447 | void dictedit_selectedrow(t_dictedit* self, t_rowref* rr) { 448 | outlet_anything(self->d_outlet, (t_symbol*)rr, 0, nullptr); 449 | } 450 | 451 | 452 | t_max_err dictedit_set_dictionary(t_dictedit *x, void *attr, long argc, t_atom *argv) { 453 | t_symbol* name = atom_getsym(argv); 454 | if (!name || name == ps_nothing) { 455 | object_error((t_object *)x, "invalid name specified", name); 456 | return MAX_ERR_GENERIC; 457 | } 458 | 459 | t_dictionary* d = dictobj_findregistered_retain(name); 460 | if (!d) { 461 | object_error((t_object *)x, "unable to reference dictionary named %s", name); 462 | return MAX_ERR_GENERIC; 463 | } 464 | 465 | if (x->d_dict) { 466 | object_detach_byptr(x, x->d_dict); 467 | dictobj_release(x->d_dict); 468 | } 469 | x->d_dict = d; 470 | x->d_name = name; 471 | object_attach_byptr(x, d); 472 | 473 | return MAX_ERR_NONE; 474 | } --------------------------------------------------------------------------------