├── .gitignore ├── README.md ├── m4l ├── amxd │ ├── clip_listener.amxd │ ├── events.amxd │ ├── param_changer.amxd │ ├── parse_chord.amxd │ ├── sf_player.amxd │ ├── tcp_client.amxd │ ├── to_cinder.amxd │ └── transport.amxd └── js │ ├── clip_listener.js │ ├── clip_trigger.js │ ├── config │ ├── cp_event.txt │ ├── cp_trigger.txt │ ├── sample_event_config.txt │ └── sample_trigger_config.txt │ ├── config_loader.js │ ├── cue_points.js │ ├── folder_traversal.js │ ├── global_m4l.js │ ├── live_time_events.js │ ├── param_changer.js │ ├── parse_chord.js │ ├── ramp_in_range.js │ ├── set_specific │ └── 15_11_14knife.js │ ├── sfplay_driver.js │ ├── to_cinder.js │ └── transport.js └── tcpServer ├── connection_handler.js ├── message_handler.js └── tcp_server.js /.gitignore: -------------------------------------------------------------------------------- 1 | #folders that contain items specific to certain live sets 2 | m4l/js/set_specific 3 | m4l/amxd/set_specific 4 | 5 | #perlin noise dependency 6 | m4l/js/perlin_noise.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | m4l_js2liveAPI 2 | ============== 3 | 4 | *Contains:* 5 | 6 | - commonly used functions to interface with Ableton Live javascript api for use within max for live 7 | - node.js TCP server to facilitate message passing between Cinder and Max/MSP (or any TCP client) 8 | 9 | *Dependencies* 10 | 11 | - Max/MSP 6 or 7 + Max for Live 12 | - node.js v0.12.2 13 | 14 | *Build Instructions* 15 | 16 | - add m4l script folder to Max File Preferences 17 | - global_m4l.js: send "compile" message to a js object pointing to this file and you can call its functions from anywhere in your Live project 18 | - to run TCP server: node start *path to .js file location*/tcp_server 19 | -------------------------------------------------------------------------------- /m4l/amxd/clip_listener.amxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blm81/m4l_js2liveAPI/a4b615280416ef6926ba4d523710878d0d014c98/m4l/amxd/clip_listener.amxd -------------------------------------------------------------------------------- /m4l/amxd/events.amxd: -------------------------------------------------------------------------------- 1 | ampfaaaametaptch8K{ 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 7, 6 | "minor" : 0, 7 | "revision" : 3, 8 | "architecture" : "x86", 9 | "modernui" : 1 10 | } 11 | , 12 | "rect" : [ 327.0, 156.0, 538.0, 635.0 ], 13 | "openrect" : [ 0.0, 0.0, 0.0, 169.0 ], 14 | "bglocked" : 0, 15 | "openinpresentation" : 1, 16 | "default_fontsize" : 10.0, 17 | "default_fontface" : 0, 18 | "default_fontname" : "Arial Bold", 19 | "gridonopen" : 1, 20 | "gridsize" : [ 8.0, 8.0 ], 21 | "gridsnaponopen" : 1, 22 | "objectsnaponopen" : 1, 23 | "statusbarvisible" : 2, 24 | "toolbarvisible" : 1, 25 | "lefttoolbarpinned" : 0, 26 | "toptoolbarpinned" : 0, 27 | "righttoolbarpinned" : 0, 28 | "bottomtoolbarpinned" : 0, 29 | "toolbars_unpinned_last_save" : 0, 30 | "tallnewobj" : 0, 31 | "boxanimatetime" : 500, 32 | "enablehscroll" : 1, 33 | "enablevscroll" : 1, 34 | "devicewidth" : 0.0, 35 | "description" : "", 36 | "digest" : "", 37 | "tags" : "", 38 | "style" : "", 39 | "subpatcher_template" : "", 40 | "boxes" : [ { 41 | "box" : { 42 | "id" : "obj-33", 43 | "maxclass" : "comment", 44 | "numinlets" : 1, 45 | "numoutlets" : 0, 46 | "patching_rect" : [ 334.0, 147.0, 59.0, 18.0 ], 47 | "presentation" : 1, 48 | "presentation_rect" : [ 13.375, 10.0, 78.0, 18.0 ], 49 | "style" : "", 50 | "text" : "reload all" 51 | } 52 | 53 | } 54 | , { 55 | "box" : { 56 | "id" : "obj-32", 57 | "maxclass" : "live.button", 58 | "numinlets" : 1, 59 | "numoutlets" : 1, 60 | "outlettype" : [ "" ], 61 | "parameter_enable" : 1, 62 | "patching_rect" : [ 313.0, 147.0, 15.0, 15.0 ], 63 | "presentation" : 1, 64 | "presentation_rect" : [ 20.0, 30.0, 15.0, 15.0 ], 65 | "saved_attribute_attributes" : { 66 | "valueof" : { 67 | "parameter_longname" : "live.button", 68 | "parameter_shortname" : "live.button", 69 | "parameter_type" : 2, 70 | "parameter_mmax" : 1.0, 71 | "parameter_enum" : [ "off", "on" ] 72 | } 73 | 74 | } 75 | , 76 | "varname" : "live.button" 77 | } 78 | 79 | } 80 | , { 81 | "box" : { 82 | "id" : "obj-44", 83 | "maxclass" : "comment", 84 | "numinlets" : 1, 85 | "numoutlets" : 0, 86 | "patching_rect" : [ 336.0, 184.0, 78.0, 18.0 ], 87 | "presentation" : 1, 88 | "presentation_rect" : [ 13.375, 115.0, 78.0, 18.0 ], 89 | "style" : "", 90 | "text" : "trigger config" 91 | } 92 | 93 | } 94 | , { 95 | "box" : { 96 | "id" : "obj-43", 97 | "maxclass" : "newobj", 98 | "numinlets" : 2, 99 | "numoutlets" : 2, 100 | "outlettype" : [ "", "" ], 101 | "patching_rect" : [ 336.0, 238.0, 63.0, 20.0 ], 102 | "style" : "", 103 | "text" : "zl.filter text" 104 | } 105 | 106 | } 107 | , { 108 | "box" : { 109 | "id" : "obj-42", 110 | "maxclass" : "textedit", 111 | "numinlets" : 1, 112 | "numoutlets" : 4, 113 | "outlettype" : [ "", "int", "", "" ], 114 | "parameter_enable" : 0, 115 | "patching_rect" : [ 336.0, 207.0, 80.0, 20.0 ], 116 | "presentation" : 1, 117 | "presentation_rect" : [ 14.375, 135.0, 77.0, 17.0 ], 118 | "style" : "" 119 | } 120 | 121 | } 122 | , { 123 | "box" : { 124 | "id" : "obj-41", 125 | "maxclass" : "comment", 126 | "numinlets" : 1, 127 | "numoutlets" : 0, 128 | "patching_rect" : [ 233.0, 184.0, 78.0, 18.0 ], 129 | "presentation" : 1, 130 | "presentation_rect" : [ 13.375, 55.0, 78.0, 18.0 ], 131 | "style" : "", 132 | "text" : "event config" 133 | } 134 | 135 | } 136 | , { 137 | "box" : { 138 | "id" : "obj-34", 139 | "maxclass" : "newobj", 140 | "numinlets" : 1, 141 | "numoutlets" : 1, 142 | "outlettype" : [ "" ], 143 | "patching_rect" : [ 312.0, 436.0, 73.0, 20.0 ], 144 | "style" : "", 145 | "text" : "prepend json" 146 | } 147 | 148 | } 149 | , { 150 | "box" : { 151 | "id" : "obj-24", 152 | "maxclass" : "message", 153 | "numinlets" : 2, 154 | "numoutlets" : 1, 155 | "outlettype" : [ "" ], 156 | "patching_rect" : [ 354.0, 267.0, 74.0, 20.0 ], 157 | "style" : "", 158 | "text" : "cp_trigger.txt" 159 | } 160 | 161 | } 162 | , { 163 | "box" : { 164 | "id" : "obj-25", 165 | "maxclass" : "newobj", 166 | "numinlets" : 1, 167 | "numoutlets" : 1, 168 | "outlettype" : [ "" ], 169 | "patching_rect" : [ 336.0, 335.0, 65.0, 20.0 ], 170 | "style" : "", 171 | "text" : "append trig" 172 | } 173 | 174 | } 175 | , { 176 | "box" : { 177 | "id" : "obj-27", 178 | "maxclass" : "newobj", 179 | "numinlets" : 1, 180 | "numoutlets" : 1, 181 | "outlettype" : [ "" ], 182 | "patching_rect" : [ 336.0, 304.0, 74.0, 20.0 ], 183 | "style" : "", 184 | "text" : "prepend read" 185 | } 186 | 187 | } 188 | , { 189 | "box" : { 190 | "id" : "obj-16", 191 | "maxclass" : "message", 192 | "numinlets" : 2, 193 | "numoutlets" : 1, 194 | "outlettype" : [ "" ], 195 | "patching_rect" : [ 251.0, 267.0, 69.0, 20.0 ], 196 | "style" : "", 197 | "text" : "cp_event.txt" 198 | } 199 | 200 | } 201 | , { 202 | "box" : { 203 | "id" : "obj-22", 204 | "maxclass" : "newobj", 205 | "numinlets" : 2, 206 | "numoutlets" : 2, 207 | "outlettype" : [ "", "" ], 208 | "patching_rect" : [ 233.0, 238.0, 63.0, 20.0 ], 209 | "style" : "", 210 | "text" : "zl.filter text" 211 | } 212 | 213 | } 214 | , { 215 | "box" : { 216 | "id" : "obj-23", 217 | "maxclass" : "textedit", 218 | "numinlets" : 1, 219 | "numoutlets" : 4, 220 | "outlettype" : [ "", "int", "", "" ], 221 | "parameter_enable" : 0, 222 | "patching_rect" : [ 233.0, 207.0, 80.0, 20.0 ], 223 | "presentation" : 1, 224 | "presentation_rect" : [ 13.375, 75.0, 77.0, 17.0 ], 225 | "style" : "" 226 | } 227 | 228 | } 229 | , { 230 | "box" : { 231 | "id" : "obj-21", 232 | "maxclass" : "newobj", 233 | "numinlets" : 3, 234 | "numoutlets" : 3, 235 | "outlettype" : [ "", "", "" ], 236 | "patching_rect" : [ 233.0, 403.0, 177.0, 20.0 ], 237 | "style" : "", 238 | "text" : "route time trig" 239 | } 240 | 241 | } 242 | , { 243 | "box" : { 244 | "id" : "obj-17", 245 | "maxclass" : "newobj", 246 | "numinlets" : 1, 247 | "numoutlets" : 1, 248 | "outlettype" : [ "" ], 249 | "patching_rect" : [ 233.0, 335.0, 69.0, 20.0 ], 250 | "style" : "", 251 | "text" : "append time" 252 | } 253 | 254 | } 255 | , { 256 | "box" : { 257 | "id" : "obj-15", 258 | "maxclass" : "newobj", 259 | "numinlets" : 1, 260 | "numoutlets" : 1, 261 | "outlettype" : [ "" ], 262 | "patching_rect" : [ 344.0, 499.0, 79.0, 20.0 ], 263 | "style" : "", 264 | "text" : "prepend event" 265 | } 266 | 267 | } 268 | , { 269 | "box" : { 270 | "id" : "obj-11", 271 | "maxclass" : "newobj", 272 | "numinlets" : 0, 273 | "numoutlets" : 1, 274 | "outlettype" : [ "" ], 275 | "patching_rect" : [ 344.0, 470.0, 54.0, 20.0 ], 276 | "style" : "", 277 | "text" : "r time_ev" 278 | } 279 | 280 | } 281 | , { 282 | "box" : { 283 | "id" : "obj-36", 284 | "maxclass" : "newobj", 285 | "numinlets" : 1, 286 | "numoutlets" : 1, 287 | "outlettype" : [ "" ], 288 | "patching_rect" : [ 18.0, 451.0, 74.0, 20.0 ], 289 | "saved_object_attributes" : { 290 | "filename" : "global_m4l", 291 | "parameter_enable" : 0 292 | } 293 | , 294 | "style" : "", 295 | "text" : "js global_m4l" 296 | } 297 | 298 | } 299 | , { 300 | "box" : { 301 | "id" : "obj-35", 302 | "maxclass" : "newobj", 303 | "numinlets" : 1, 304 | "numoutlets" : 1, 305 | "outlettype" : [ "" ], 306 | "patching_rect" : [ 344.0, 563.0, 68.0, 20.0 ], 307 | "style" : "", 308 | "text" : "fromsymbol" 309 | } 310 | 311 | } 312 | , { 313 | "box" : { 314 | "id" : "obj-28", 315 | "maxclass" : "message", 316 | "numinlets" : 2, 317 | "numoutlets" : 1, 318 | "outlettype" : [ "" ], 319 | "patching_rect" : [ 417.5, 367.0, 83.0, 20.0 ], 320 | "style" : "", 321 | "text" : "get_song_info" 322 | } 323 | 324 | } 325 | , { 326 | "box" : { 327 | "id" : "obj-26", 328 | "maxclass" : "newobj", 329 | "numinlets" : 1, 330 | "numoutlets" : 1, 331 | "outlettype" : [ "" ], 332 | "patching_rect" : [ 344.0, 533.0, 76.0, 20.0 ], 333 | "saved_object_attributes" : { 334 | "filename" : "clip_trigger", 335 | "parameter_enable" : 0 336 | } 337 | , 338 | "style" : "", 339 | "text" : "js clip_trigger" 340 | } 341 | 342 | } 343 | , { 344 | "box" : { 345 | "id" : "obj-20", 346 | "maxclass" : "newobj", 347 | "numinlets" : 1, 348 | "numoutlets" : 1, 349 | "outlettype" : [ "" ], 350 | "patching_rect" : [ 233.0, 436.0, 73.0, 20.0 ], 351 | "style" : "", 352 | "text" : "prepend json" 353 | } 354 | 355 | } 356 | , { 357 | "box" : { 358 | "id" : "obj-7", 359 | "maxclass" : "newobj", 360 | "numinlets" : 1, 361 | "numoutlets" : 1, 362 | "outlettype" : [ "" ], 363 | "patching_rect" : [ 233.0, 304.0, 74.0, 20.0 ], 364 | "style" : "", 365 | "text" : "prepend read" 366 | } 367 | 368 | } 369 | , { 370 | "box" : { 371 | "id" : "obj-5", 372 | "maxclass" : "newobj", 373 | "numinlets" : 1, 374 | "numoutlets" : 1, 375 | "outlettype" : [ "" ], 376 | "patching_rect" : [ 233.0, 371.0, 87.0, 20.0 ], 377 | "saved_object_attributes" : { 378 | "filename" : "config_loader", 379 | "parameter_enable" : 0 380 | } 381 | , 382 | "style" : "", 383 | "text" : "js config_loader" 384 | } 385 | 386 | } 387 | , { 388 | "box" : { 389 | "id" : "obj-18", 390 | "maxclass" : "message", 391 | "numinlets" : 2, 392 | "numoutlets" : 1, 393 | "outlettype" : [ "" ], 394 | "patching_rect" : [ 18.0, 323.0, 48.0, 20.0 ], 395 | "style" : "", 396 | "text" : "compile" 397 | } 398 | 399 | } 400 | , { 401 | "box" : { 402 | "id" : "obj-13", 403 | "maxclass" : "button", 404 | "numinlets" : 1, 405 | "numoutlets" : 1, 406 | "outlettype" : [ "bang" ], 407 | "patching_rect" : [ 195.0, 566.0, 24.0, 24.0 ], 408 | "style" : "" 409 | } 410 | 411 | } 412 | , { 413 | "box" : { 414 | "id" : "obj-12", 415 | "maxclass" : "button", 416 | "numinlets" : 1, 417 | "numoutlets" : 1, 418 | "outlettype" : [ "bang" ], 419 | "patching_rect" : [ 125.5, 566.0, 24.0, 24.0 ], 420 | "style" : "" 421 | } 422 | 423 | } 424 | , { 425 | "box" : { 426 | "id" : "obj-8", 427 | "maxclass" : "newobj", 428 | "numinlets" : 3, 429 | "numoutlets" : 3, 430 | "outlettype" : [ "", "", "" ], 431 | "patching_rect" : [ 125.5, 537.0, 158.0, 20.0 ], 432 | "style" : "", 433 | "text" : "route bar_change beat_change" 434 | } 435 | 436 | } 437 | , { 438 | "box" : { 439 | "id" : "obj-3", 440 | "maxclass" : "newobj", 441 | "numinlets" : 1, 442 | "numoutlets" : 1, 443 | "outlettype" : [ "" ], 444 | "patching_rect" : [ 125.5, 509.0, 102.0, 20.0 ], 445 | "saved_object_attributes" : { 446 | "filename" : "live_time_events", 447 | "parameter_enable" : 0 448 | } 449 | , 450 | "style" : "", 451 | "text" : "js live_time_events" 452 | } 453 | 454 | } 455 | , { 456 | "box" : { 457 | "id" : "obj-10", 458 | "maxclass" : "newobj", 459 | "numinlets" : 1, 460 | "numoutlets" : 2, 461 | "outlettype" : [ "compile", "transport" ], 462 | "patching_rect" : [ 18.0, 238.0, 101.0, 20.0 ], 463 | "style" : "", 464 | "text" : "t compile transport" 465 | } 466 | 467 | } 468 | , { 469 | "box" : { 470 | "id" : "obj-9", 471 | "maxclass" : "newobj", 472 | "numinlets" : 1, 473 | "numoutlets" : 3, 474 | "outlettype" : [ "bang", "int", "int" ], 475 | "patching_rect" : [ 18.0, 207.0, 79.0, 20.0 ], 476 | "style" : "", 477 | "text" : "live.thisdevice" 478 | } 479 | 480 | } 481 | , { 482 | "box" : { 483 | "id" : "obj-30", 484 | "maxclass" : "newobj", 485 | "numinlets" : 2, 486 | "numoutlets" : 2, 487 | "outlettype" : [ "", "" ], 488 | "patching_rect" : [ 125.5, 238.0, 63.0, 20.0 ], 489 | "style" : "", 490 | "text" : "zl.filter text" 491 | } 492 | 493 | } 494 | , { 495 | "box" : { 496 | "id" : "obj-19", 497 | "maxclass" : "textedit", 498 | "numinlets" : 1, 499 | "numoutlets" : 4, 500 | "outlettype" : [ "", "int", "", "" ], 501 | "parameter_enable" : 0, 502 | "patching_rect" : [ 125.5, 207.0, 80.0, 20.0 ], 503 | "style" : "" 504 | } 505 | 506 | } 507 | , { 508 | "box" : { 509 | "fontname" : "Arial Bold", 510 | "fontsize" : 10.0, 511 | "id" : "obj-6", 512 | "maxclass" : "newobj", 513 | "numinlets" : 1, 514 | "numoutlets" : 1, 515 | "outlettype" : [ "" ], 516 | "patching_rect" : [ 125.5, 267.0, 67.0, 20.0 ], 517 | "style" : "", 518 | "text" : "prepend set" 519 | } 520 | 521 | } 522 | , { 523 | "box" : { 524 | "fontname" : "Arial Bold", 525 | "fontsize" : 10.0, 526 | "id" : "obj-4", 527 | "maxclass" : "newobj", 528 | "numinlets" : 1, 529 | "numoutlets" : 1, 530 | "outlettype" : [ "" ], 531 | "patching_rect" : [ 125.5, 298.0, 19.0, 20.0 ], 532 | "style" : "", 533 | "text" : "r" 534 | } 535 | 536 | } 537 | , { 538 | "box" : { 539 | "fontname" : "Arial Bold", 540 | "fontsize" : 10.0, 541 | "id" : "obj-2", 542 | "maxclass" : "newobj", 543 | "numinlets" : 2, 544 | "numoutlets" : 2, 545 | "outlettype" : [ "signal", "signal" ], 546 | "patching_rect" : [ 21.5, 550.0, 53.0, 20.0 ], 547 | "style" : "", 548 | "text" : "plugout~" 549 | } 550 | 551 | } 552 | , { 553 | "box" : { 554 | "fontname" : "Arial Bold", 555 | "fontsize" : 10.0, 556 | "id" : "obj-1", 557 | "maxclass" : "newobj", 558 | "numinlets" : 2, 559 | "numoutlets" : 2, 560 | "outlettype" : [ "signal", "signal" ], 561 | "patching_rect" : [ 21.5, 513.0, 53.0, 20.0 ], 562 | "style" : "", 563 | "text" : "plugin~" 564 | } 565 | 566 | } 567 | ], 568 | "lines" : [ { 569 | "patchline" : { 570 | "destination" : [ "obj-2", 1 ], 571 | "disabled" : 0, 572 | "hidden" : 0, 573 | "source" : [ "obj-1", 1 ] 574 | } 575 | 576 | } 577 | , { 578 | "patchline" : { 579 | "destination" : [ "obj-2", 0 ], 580 | "disabled" : 0, 581 | "hidden" : 0, 582 | "source" : [ "obj-1", 0 ] 583 | } 584 | 585 | } 586 | , { 587 | "patchline" : { 588 | "destination" : [ "obj-26", 0 ], 589 | "disabled" : 0, 590 | "hidden" : 0, 591 | "source" : [ "obj-10", 0 ] 592 | } 593 | 594 | } 595 | , { 596 | "patchline" : { 597 | "destination" : [ "obj-3", 0 ], 598 | "disabled" : 0, 599 | "hidden" : 0, 600 | "source" : [ "obj-10", 0 ] 601 | } 602 | 603 | } 604 | , { 605 | "patchline" : { 606 | "destination" : [ "obj-5", 0 ], 607 | "disabled" : 0, 608 | "hidden" : 0, 609 | "source" : [ "obj-10", 0 ] 610 | } 611 | 612 | } 613 | , { 614 | "patchline" : { 615 | "destination" : [ "obj-6", 0 ], 616 | "disabled" : 0, 617 | "hidden" : 0, 618 | "source" : [ "obj-10", 1 ] 619 | } 620 | 621 | } 622 | , { 623 | "patchline" : { 624 | "destination" : [ "obj-15", 0 ], 625 | "disabled" : 0, 626 | "hidden" : 0, 627 | "source" : [ "obj-11", 0 ] 628 | } 629 | 630 | } 631 | , { 632 | "patchline" : { 633 | "destination" : [ "obj-26", 0 ], 634 | "disabled" : 0, 635 | "hidden" : 0, 636 | "source" : [ "obj-15", 0 ] 637 | } 638 | 639 | } 640 | , { 641 | "patchline" : { 642 | "destination" : [ "obj-7", 0 ], 643 | "disabled" : 0, 644 | "hidden" : 0, 645 | "source" : [ "obj-16", 0 ] 646 | } 647 | 648 | } 649 | , { 650 | "patchline" : { 651 | "destination" : [ "obj-5", 0 ], 652 | "disabled" : 0, 653 | "hidden" : 0, 654 | "source" : [ "obj-17", 0 ] 655 | } 656 | 657 | } 658 | , { 659 | "patchline" : { 660 | "destination" : [ "obj-26", 0 ], 661 | "disabled" : 0, 662 | "hidden" : 0, 663 | "source" : [ "obj-18", 0 ] 664 | } 665 | 666 | } 667 | , { 668 | "patchline" : { 669 | "destination" : [ "obj-3", 0 ], 670 | "disabled" : 0, 671 | "hidden" : 0, 672 | "source" : [ "obj-18", 0 ] 673 | } 674 | 675 | } 676 | , { 677 | "patchline" : { 678 | "destination" : [ "obj-36", 0 ], 679 | "disabled" : 0, 680 | "hidden" : 0, 681 | "source" : [ "obj-18", 0 ] 682 | } 683 | 684 | } 685 | , { 686 | "patchline" : { 687 | "destination" : [ "obj-30", 0 ], 688 | "disabled" : 0, 689 | "hidden" : 0, 690 | "source" : [ "obj-19", 0 ] 691 | } 692 | 693 | } 694 | , { 695 | "patchline" : { 696 | "destination" : [ "obj-3", 0 ], 697 | "disabled" : 0, 698 | "hidden" : 0, 699 | "source" : [ "obj-20", 0 ] 700 | } 701 | 702 | } 703 | , { 704 | "patchline" : { 705 | "destination" : [ "obj-20", 0 ], 706 | "disabled" : 0, 707 | "hidden" : 0, 708 | "source" : [ "obj-21", 0 ] 709 | } 710 | 711 | } 712 | , { 713 | "patchline" : { 714 | "destination" : [ "obj-34", 0 ], 715 | "disabled" : 0, 716 | "hidden" : 0, 717 | "source" : [ "obj-21", 1 ] 718 | } 719 | 720 | } 721 | , { 722 | "patchline" : { 723 | "destination" : [ "obj-7", 0 ], 724 | "disabled" : 0, 725 | "hidden" : 0, 726 | "source" : [ "obj-22", 0 ] 727 | } 728 | 729 | } 730 | , { 731 | "patchline" : { 732 | "destination" : [ "obj-22", 0 ], 733 | "disabled" : 0, 734 | "hidden" : 0, 735 | "source" : [ "obj-23", 0 ] 736 | } 737 | 738 | } 739 | , { 740 | "patchline" : { 741 | "destination" : [ "obj-27", 0 ], 742 | "disabled" : 0, 743 | "hidden" : 0, 744 | "source" : [ "obj-24", 0 ] 745 | } 746 | 747 | } 748 | , { 749 | "patchline" : { 750 | "destination" : [ "obj-5", 0 ], 751 | "disabled" : 0, 752 | "hidden" : 0, 753 | "source" : [ "obj-25", 0 ] 754 | } 755 | 756 | } 757 | , { 758 | "patchline" : { 759 | "destination" : [ "obj-35", 0 ], 760 | "disabled" : 0, 761 | "hidden" : 0, 762 | "source" : [ "obj-26", 0 ] 763 | } 764 | 765 | } 766 | , { 767 | "patchline" : { 768 | "destination" : [ "obj-25", 0 ], 769 | "disabled" : 0, 770 | "hidden" : 0, 771 | "source" : [ "obj-27", 0 ] 772 | } 773 | 774 | } 775 | , { 776 | "patchline" : { 777 | "destination" : [ "obj-26", 0 ], 778 | "disabled" : 0, 779 | "hidden" : 0, 780 | "source" : [ "obj-28", 0 ] 781 | } 782 | 783 | } 784 | , { 785 | "patchline" : { 786 | "destination" : [ "obj-8", 0 ], 787 | "disabled" : 0, 788 | "hidden" : 0, 789 | "source" : [ "obj-3", 0 ] 790 | } 791 | 792 | } 793 | , { 794 | "patchline" : { 795 | "destination" : [ "obj-6", 0 ], 796 | "disabled" : 0, 797 | "hidden" : 0, 798 | "source" : [ "obj-30", 0 ] 799 | } 800 | 801 | } 802 | , { 803 | "patchline" : { 804 | "destination" : [ "obj-23", 0 ], 805 | "disabled" : 0, 806 | "hidden" : 0, 807 | "source" : [ "obj-32", 0 ] 808 | } 809 | 810 | } 811 | , { 812 | "patchline" : { 813 | "destination" : [ "obj-42", 0 ], 814 | "disabled" : 0, 815 | "hidden" : 0, 816 | "source" : [ "obj-32", 0 ] 817 | } 818 | 819 | } 820 | , { 821 | "patchline" : { 822 | "destination" : [ "obj-26", 0 ], 823 | "disabled" : 0, 824 | "hidden" : 0, 825 | "source" : [ "obj-34", 0 ] 826 | } 827 | 828 | } 829 | , { 830 | "patchline" : { 831 | "destination" : [ "obj-3", 0 ], 832 | "disabled" : 0, 833 | "hidden" : 0, 834 | "source" : [ "obj-4", 0 ] 835 | } 836 | 837 | } 838 | , { 839 | "patchline" : { 840 | "destination" : [ "obj-43", 0 ], 841 | "disabled" : 0, 842 | "hidden" : 0, 843 | "source" : [ "obj-42", 0 ] 844 | } 845 | 846 | } 847 | , { 848 | "patchline" : { 849 | "destination" : [ "obj-27", 0 ], 850 | "disabled" : 0, 851 | "hidden" : 0, 852 | "source" : [ "obj-43", 0 ] 853 | } 854 | 855 | } 856 | , { 857 | "patchline" : { 858 | "destination" : [ "obj-21", 0 ], 859 | "disabled" : 0, 860 | "hidden" : 0, 861 | "source" : [ "obj-5", 0 ] 862 | } 863 | 864 | } 865 | , { 866 | "patchline" : { 867 | "destination" : [ "obj-4", 0 ], 868 | "disabled" : 0, 869 | "hidden" : 0, 870 | "source" : [ "obj-6", 0 ] 871 | } 872 | 873 | } 874 | , { 875 | "patchline" : { 876 | "destination" : [ "obj-17", 0 ], 877 | "disabled" : 0, 878 | "hidden" : 0, 879 | "source" : [ "obj-7", 0 ] 880 | } 881 | 882 | } 883 | , { 884 | "patchline" : { 885 | "destination" : [ "obj-12", 0 ], 886 | "disabled" : 0, 887 | "hidden" : 0, 888 | "source" : [ "obj-8", 0 ] 889 | } 890 | 891 | } 892 | , { 893 | "patchline" : { 894 | "destination" : [ "obj-13", 0 ], 895 | "disabled" : 0, 896 | "hidden" : 0, 897 | "source" : [ "obj-8", 1 ] 898 | } 899 | 900 | } 901 | , { 902 | "patchline" : { 903 | "destination" : [ "obj-10", 0 ], 904 | "disabled" : 0, 905 | "hidden" : 0, 906 | "source" : [ "obj-9", 0 ] 907 | } 908 | 909 | } 910 | ], 911 | "parameters" : { 912 | "obj-32" : [ "live.button", "live.button", 0 ] 913 | } 914 | , 915 | "dependency_cache" : [ { 916 | "name" : "live_time_events.js", 917 | "bootpath" : "~/Music/Ableton/User Library/Presets/Audio Effects/Max Audio Effect/m4l_js2liveAPI/m4l", 918 | "type" : "TEXT", 919 | "implicit" : 1 920 | } 921 | , { 922 | "name" : "config_loader.js", 923 | "bootpath" : "~/Music/Ableton/User Library/Presets/Audio Effects/Max Audio Effect/m4l_js2liveAPI/m4l", 924 | "type" : "TEXT", 925 | "implicit" : 1 926 | } 927 | , { 928 | "name" : "clip_trigger.js", 929 | "bootpath" : "~/Music/Ableton/User Library/Presets/Audio Effects/Max Audio Effect/m4l_js2liveAPI/m4l", 930 | "type" : "TEXT", 931 | "implicit" : 1 932 | } 933 | , { 934 | "name" : "global_m4l.js", 935 | "bootpath" : "~/Music/Ableton/User Library/Presets/Audio Effects/Max Audio Effect/m4l_js2liveAPI/m4l", 936 | "type" : "TEXT", 937 | "implicit" : 1 938 | } 939 | ], 940 | "latency" : 0, 941 | "project" : { 942 | "version" : 1, 943 | "creationdate" : -778403322, 944 | "modificationdate" : -778403322, 945 | "viewrect" : [ 0.0, 0.0, 300.0, 500.0 ], 946 | "autoorganize" : 1, 947 | "hideprojectwindow" : 1, 948 | "showdependencies" : 1, 949 | "autolocalize" : 0, 950 | "contents" : { 951 | "patchers" : { 952 | 953 | } 954 | , 955 | "code" : { 956 | 957 | } 958 | 959 | } 960 | , 961 | "layout" : { 962 | 963 | } 964 | , 965 | "searchpath" : { 966 | 967 | } 968 | , 969 | "detailsvisible" : 0, 970 | "amxdtype" : 1633771873, 971 | "readonly" : 0 972 | } 973 | , 974 | "embedsnapshot" : 0 975 | } 976 | 977 | } 978 | -------------------------------------------------------------------------------- /m4l/amxd/param_changer.amxd: -------------------------------------------------------------------------------- 1 | ampfaaaametaptch^{ 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 7, 6 | "minor" : 1, 7 | "revision" : 0, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "rect" : [ 266.0, 136.0, 601.0, 681.0 ], 13 | "openrect" : [ 0.0, 0.0, 305.0, 169.0 ], 14 | "bglocked" : 0, 15 | "openinpresentation" : 1, 16 | "default_fontsize" : 10.0, 17 | "default_fontface" : 0, 18 | "default_fontname" : "Arial Bold", 19 | "gridonopen" : 1, 20 | "gridsize" : [ 8.0, 8.0 ], 21 | "gridsnaponopen" : 1, 22 | "objectsnaponopen" : 1, 23 | "statusbarvisible" : 0, 24 | "toolbarvisible" : 1, 25 | "lefttoolbarpinned" : 0, 26 | "toptoolbarpinned" : 0, 27 | "righttoolbarpinned" : 0, 28 | "bottomtoolbarpinned" : 0, 29 | "toolbars_unpinned_last_save" : 0, 30 | "tallnewobj" : 0, 31 | "boxanimatetime" : 500, 32 | "enablehscroll" : 1, 33 | "enablevscroll" : 1, 34 | "devicewidth" : 305.0, 35 | "description" : "", 36 | "digest" : "", 37 | "tags" : "", 38 | "style" : "", 39 | "subpatcher_template" : "", 40 | "boxes" : [ { 41 | "box" : { 42 | "id" : "obj-19", 43 | "maxclass" : "newobj", 44 | "numinlets" : 2, 45 | "numoutlets" : 1, 46 | "outlettype" : [ "int" ], 47 | "patching_rect" : [ 207.0, 253.5, 29.5, 20.0 ], 48 | "style" : "", 49 | "text" : "+ 1" 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "id" : "obj-11", 56 | "linecount" : 3, 57 | "maxclass" : "comment", 58 | "numinlets" : 1, 59 | "numoutlets" : 0, 60 | "patching_rect" : [ 155.0, 170.0, 85.0, 40.0 ], 61 | "presentation" : 1, 62 | "presentation_linecount" : 6, 63 | "presentation_rect" : [ 176.0, 15.0, 66.5, 74.0 ], 64 | "style" : "", 65 | "text" : "toggle mode:\n0 = direct value\n1 = percentage" 66 | } 67 | 68 | } 69 | , { 70 | "box" : { 71 | "id" : "obj-10", 72 | "maxclass" : "live.toggle", 73 | "numinlets" : 1, 74 | "numoutlets" : 1, 75 | "outlettype" : [ "" ], 76 | "parameter_enable" : 1, 77 | "patching_rect" : [ 207.0, 220.0, 25.0, 25.0 ], 78 | "presentation" : 1, 79 | "presentation_rect" : [ 189.75, 91.0, 25.0, 25.0 ], 80 | "saved_attribute_attributes" : { 81 | "valueof" : { 82 | "parameter_longname" : "live.toggle", 83 | "parameter_shortname" : "live.toggle", 84 | "parameter_type" : 2, 85 | "parameter_mmax" : 1.0, 86 | "parameter_enum" : [ "off", "on" ] 87 | } 88 | 89 | } 90 | , 91 | "varname" : "live.toggle" 92 | } 93 | 94 | } 95 | , { 96 | "box" : { 97 | "id" : "obj-9", 98 | "maxclass" : "live.numbox", 99 | "numinlets" : 1, 100 | "numoutlets" : 2, 101 | "outlettype" : [ "", "float" ], 102 | "parameter_enable" : 1, 103 | "patching_rect" : [ 200.0, 325.0, 36.0, 15.0 ], 104 | "presentation" : 1, 105 | "presentation_rect" : [ 249.0, 129.5, 36.0, 15.0 ], 106 | "saved_attribute_attributes" : { 107 | "valueof" : { 108 | "parameter_longname" : "live.numbox", 109 | "parameter_shortname" : "live.numbox", 110 | "parameter_type" : 0, 111 | "parameter_mmin" : -1000.0, 112 | "parameter_mmax" : 1000.0, 113 | "parameter_unitstyle" : 1 114 | } 115 | 116 | } 117 | , 118 | "varname" : "live.numbox" 119 | } 120 | 121 | } 122 | , { 123 | "box" : { 124 | "id" : "obj-8", 125 | "maxclass" : "newobj", 126 | "numinlets" : 2, 127 | "numoutlets" : 2, 128 | "outlettype" : [ "", "" ], 129 | "patching_rect" : [ 236.0, 287.0, 39.0, 20.0 ], 130 | "style" : "", 131 | "text" : "gate 2" 132 | } 133 | 134 | } 135 | , { 136 | "box" : { 137 | "id" : "obj-32", 138 | "maxclass" : "comment", 139 | "numinlets" : 1, 140 | "numoutlets" : 0, 141 | "patching_rect" : [ 342.0, 170.0, 72.0, 18.0 ], 142 | "presentation" : 1, 143 | "presentation_linecount" : 2, 144 | "presentation_rect" : [ 83.0, 15.0, 66.0, 29.0 ], 145 | "style" : "", 146 | "text" : "receive from" 147 | } 148 | 149 | } 150 | , { 151 | "box" : { 152 | "id" : "obj-30", 153 | "maxclass" : "newobj", 154 | "numinlets" : 2, 155 | "numoutlets" : 2, 156 | "outlettype" : [ "", "" ], 157 | "patching_rect" : [ 256.0, 198.5, 63.0, 20.0 ], 158 | "style" : "", 159 | "text" : "zl.filter text" 160 | } 161 | 162 | } 163 | , { 164 | "box" : { 165 | "id" : "obj-15", 166 | "maxclass" : "textedit", 167 | "numinlets" : 1, 168 | "numoutlets" : 4, 169 | "outlettype" : [ "", "int", "", "" ], 170 | "parameter_enable" : 0, 171 | "patching_rect" : [ 256.0, 170.0, 80.0, 20.0 ], 172 | "presentation" : 1, 173 | "presentation_rect" : [ 87.0, 51.5, 80.0, 20.0 ], 174 | "style" : "" 175 | } 176 | 177 | } 178 | , { 179 | "box" : { 180 | "fontname" : "Arial Bold", 181 | "fontsize" : 10.0, 182 | "id" : "obj-20", 183 | "maxclass" : "newobj", 184 | "numinlets" : 1, 185 | "numoutlets" : 1, 186 | "outlettype" : [ "" ], 187 | "patching_rect" : [ 256.0, 228.0, 67.0, 20.0 ], 188 | "style" : "", 189 | "text" : "prepend set" 190 | } 191 | 192 | } 193 | , { 194 | "box" : { 195 | "fontname" : "Arial Bold", 196 | "fontsize" : 10.0, 197 | "id" : "obj-21", 198 | "maxclass" : "newobj", 199 | "numinlets" : 1, 200 | "numoutlets" : 1, 201 | "outlettype" : [ "" ], 202 | "patching_rect" : [ 256.0, 256.5, 19.0, 20.0 ], 203 | "style" : "", 204 | "text" : "r" 205 | } 206 | 207 | } 208 | , { 209 | "box" : { 210 | "id" : "obj-28", 211 | "linecount" : 2, 212 | "maxclass" : "comment", 213 | "numinlets" : 1, 214 | "numoutlets" : 0, 215 | "patching_rect" : [ 182.0, 389.0, 72.0, 29.0 ], 216 | "presentation" : 1, 217 | "presentation_linecount" : 2, 218 | "presentation_rect" : [ 233.0, 14.0, 69.0, 29.0 ], 219 | "style" : "", 220 | "text" : "set value by percentage" 221 | } 222 | 223 | } 224 | , { 225 | "box" : { 226 | "id" : "obj-27", 227 | "maxclass" : "newobj", 228 | "numinlets" : 1, 229 | "numoutlets" : 3, 230 | "outlettype" : [ "bang", "int", "int" ], 231 | "patching_rect" : [ 23.0, 220.0, 79.0, 20.0 ], 232 | "style" : "", 233 | "text" : "live.thisdevice" 234 | } 235 | 236 | } 237 | , { 238 | "box" : { 239 | "id" : "obj-5", 240 | "maxclass" : "live.dial", 241 | "numinlets" : 1, 242 | "numoutlets" : 2, 243 | "outlettype" : [ "", "float" ], 244 | "parameter_enable" : 1, 245 | "patching_rect" : [ 255.0, 389.0, 44.0, 47.0 ], 246 | "presentation" : 1, 247 | "presentation_rect" : [ 240.5, 45.0, 44.0, 47.0 ], 248 | "saved_attribute_attributes" : { 249 | "valueof" : { 250 | "parameter_longname" : "live.dial", 251 | "parameter_shortname" : "live.dial", 252 | "parameter_type" : 0, 253 | "parameter_mmax" : 1.0, 254 | "parameter_initial_enable" : 1, 255 | "parameter_initial" : [ 1.0 ], 256 | "parameter_unitstyle" : 1 257 | } 258 | 259 | } 260 | , 261 | "varname" : "live.dial" 262 | } 263 | 264 | } 265 | , { 266 | "box" : { 267 | "id" : "obj-7", 268 | "linecount" : 2, 269 | "maxclass" : "comment", 270 | "numinlets" : 1, 271 | "numoutlets" : 0, 272 | "patching_rect" : [ 315.0, 572.0, 72.0, 29.0 ], 273 | "presentation" : 1, 274 | "presentation_linecount" : 2, 275 | "presentation_rect" : [ 77.0, 89.0, 66.0, 29.0 ], 276 | "style" : "", 277 | "text" : "select\nparameter" 278 | } 279 | 280 | } 281 | , { 282 | "box" : { 283 | "id" : "obj-17", 284 | "linecount" : 3, 285 | "maxclass" : "comment", 286 | "numinlets" : 1, 287 | "numoutlets" : 0, 288 | "patching_rect" : [ 359.0, 459.0, 72.0, 40.0 ], 289 | "presentation" : 1, 290 | "presentation_linecount" : 3, 291 | "presentation_rect" : [ 9.0, 9.5, 66.0, 40.0 ], 292 | "style" : "", 293 | "text" : "reset parameter umenu" 294 | } 295 | 296 | } 297 | , { 298 | "box" : { 299 | "id" : "obj-16", 300 | "linecount" : 2, 301 | "maxclass" : "comment", 302 | "numinlets" : 1, 303 | "numoutlets" : 0, 304 | "patching_rect" : [ 359.0, 354.0, 72.0, 29.0 ], 305 | "presentation" : 1, 306 | "presentation_linecount" : 2, 307 | "presentation_rect" : [ 9.0, 89.0, 66.0, 29.0 ], 308 | "style" : "", 309 | "text" : "set device number" 310 | } 311 | 312 | } 313 | , { 314 | "box" : { 315 | "id" : "obj-14", 316 | "linecount" : 2, 317 | "maxclass" : "comment", 318 | "numinlets" : 1, 319 | "numoutlets" : 0, 320 | "patching_rect" : [ 182.0, 287.0, 54.0, 29.0 ], 321 | "presentation" : 1, 322 | "presentation_linecount" : 2, 323 | "presentation_rect" : [ 240.5, 98.5, 54.0, 29.0 ], 324 | "style" : "", 325 | "text" : "set value directly" 326 | } 327 | 328 | } 329 | , { 330 | "box" : { 331 | "id" : "obj-13", 332 | "linecount" : 2, 333 | "maxclass" : "comment", 334 | "numinlets" : 1, 335 | "numoutlets" : 0, 336 | "patching_rect" : [ 40.0, 249.0, 66.0, 29.0 ], 337 | "style" : "", 338 | "text" : "compile \njs" 339 | } 340 | 341 | } 342 | , { 343 | "box" : { 344 | "id" : "obj-61", 345 | "maxclass" : "newobj", 346 | "numinlets" : 1, 347 | "numoutlets" : 2, 348 | "outlettype" : [ "", "" ], 349 | "patcher" : { 350 | "fileversion" : 1, 351 | "appversion" : { 352 | "major" : 7, 353 | "minor" : 1, 354 | "revision" : 0, 355 | "architecture" : "x64", 356 | "modernui" : 1 357 | } 358 | , 359 | "rect" : [ 211.0, 85.0, 141.0, 367.0 ], 360 | "bglocked" : 0, 361 | "openinpresentation" : 0, 362 | "default_fontsize" : 12.0, 363 | "default_fontface" : 0, 364 | "default_fontname" : "Arial", 365 | "gridonopen" : 1, 366 | "gridsize" : [ 15.0, 15.0 ], 367 | "gridsnaponopen" : 1, 368 | "objectsnaponopen" : 1, 369 | "statusbarvisible" : 2, 370 | "toolbarvisible" : 1, 371 | "lefttoolbarpinned" : 0, 372 | "toptoolbarpinned" : 0, 373 | "righttoolbarpinned" : 0, 374 | "bottomtoolbarpinned" : 0, 375 | "toolbars_unpinned_last_save" : 0, 376 | "tallnewobj" : 0, 377 | "boxanimatetime" : 200, 378 | "enablehscroll" : 1, 379 | "enablevscroll" : 1, 380 | "devicewidth" : 0.0, 381 | "description" : "", 382 | "digest" : "", 383 | "tags" : "", 384 | "style" : "", 385 | "subpatcher_template" : "", 386 | "boxes" : [ { 387 | "box" : { 388 | "id" : "obj-54", 389 | "linecount" : 2, 390 | "maxclass" : "newobj", 391 | "numinlets" : 2, 392 | "numoutlets" : 2, 393 | "outlettype" : [ "", "" ], 394 | "patching_rect" : [ 34.0, 211.0, 39.0, 35.0 ], 395 | "style" : "", 396 | "text" : "gate 2" 397 | } 398 | 399 | } 400 | , { 401 | "box" : { 402 | "id" : "obj-53", 403 | "linecount" : 2, 404 | "maxclass" : "newobj", 405 | "numinlets" : 1, 406 | "numoutlets" : 2, 407 | "outlettype" : [ "int", "compile" ], 408 | "patching_rect" : [ 34.0, 153.0, 60.0, 35.0 ], 409 | "style" : "", 410 | "text" : "t i compile" 411 | } 412 | 413 | } 414 | , { 415 | "box" : { 416 | "id" : "obj-52", 417 | "maxclass" : "newobj", 418 | "numinlets" : 1, 419 | "numoutlets" : 2, 420 | "outlettype" : [ "bang", "bang" ], 421 | "patching_rect" : [ 34.0, 74.0, 32.0, 22.0 ], 422 | "style" : "", 423 | "text" : "t b b" 424 | } 425 | 426 | } 427 | , { 428 | "box" : { 429 | "id" : "obj-51", 430 | "maxclass" : "newobj", 431 | "numinlets" : 2, 432 | "numoutlets" : 1, 433 | "outlettype" : [ "int" ], 434 | "patching_rect" : [ 34.0, 182.0, 29.5, 22.0 ], 435 | "style" : "", 436 | "text" : "+ 1" 437 | } 438 | 439 | } 440 | , { 441 | "box" : { 442 | "id" : "obj-46", 443 | "maxclass" : "newobj", 444 | "numinlets" : 5, 445 | "numoutlets" : 4, 446 | "outlettype" : [ "int", "", "", "int" ], 447 | "patching_rect" : [ 34.0, 128.0, 61.0, 22.0 ], 448 | "style" : "", 449 | "text" : "counter 1" 450 | } 451 | 452 | } 453 | , { 454 | "box" : { 455 | "id" : "obj-45", 456 | "maxclass" : "newobj", 457 | "numinlets" : 2, 458 | "numoutlets" : 3, 459 | "outlettype" : [ "bang", "bang", "int" ], 460 | "patching_rect" : [ 34.0, 100.0, 40.0, 22.0 ], 461 | "style" : "", 462 | "text" : "uzi 2" 463 | } 464 | 465 | } 466 | , { 467 | "box" : { 468 | "comment" : "", 469 | "id" : "obj-58", 470 | "maxclass" : "inlet", 471 | "numinlets" : 0, 472 | "numoutlets" : 1, 473 | "outlettype" : [ "bang" ], 474 | "patching_rect" : [ 34.0, 23.0, 30.0, 30.0 ], 475 | "style" : "" 476 | } 477 | 478 | } 479 | , { 480 | "box" : { 481 | "comment" : "", 482 | "id" : "obj-59", 483 | "maxclass" : "outlet", 484 | "numinlets" : 1, 485 | "numoutlets" : 0, 486 | "patching_rect" : [ 34.0, 264.0, 30.0, 30.0 ], 487 | "style" : "" 488 | } 489 | 490 | } 491 | , { 492 | "box" : { 493 | "comment" : "", 494 | "id" : "obj-60", 495 | "maxclass" : "outlet", 496 | "numinlets" : 1, 497 | "numoutlets" : 0, 498 | "patching_rect" : [ 54.0, 264.0, 30.0, 30.0 ], 499 | "style" : "" 500 | } 501 | 502 | } 503 | ], 504 | "lines" : [ { 505 | "patchline" : { 506 | "destination" : [ "obj-46", 0 ], 507 | "disabled" : 0, 508 | "hidden" : 0, 509 | "source" : [ "obj-45", 0 ] 510 | } 511 | 512 | } 513 | , { 514 | "patchline" : { 515 | "destination" : [ "obj-53", 0 ], 516 | "disabled" : 0, 517 | "hidden" : 0, 518 | "source" : [ "obj-46", 0 ] 519 | } 520 | 521 | } 522 | , { 523 | "patchline" : { 524 | "destination" : [ "obj-54", 0 ], 525 | "disabled" : 0, 526 | "hidden" : 0, 527 | "source" : [ "obj-51", 0 ] 528 | } 529 | 530 | } 531 | , { 532 | "patchline" : { 533 | "destination" : [ "obj-45", 0 ], 534 | "disabled" : 0, 535 | "hidden" : 0, 536 | "source" : [ "obj-52", 0 ] 537 | } 538 | 539 | } 540 | , { 541 | "patchline" : { 542 | "destination" : [ "obj-46", 3 ], 543 | "disabled" : 0, 544 | "hidden" : 0, 545 | "source" : [ "obj-52", 1 ] 546 | } 547 | 548 | } 549 | , { 550 | "patchline" : { 551 | "destination" : [ "obj-51", 0 ], 552 | "disabled" : 0, 553 | "hidden" : 0, 554 | "source" : [ "obj-53", 0 ] 555 | } 556 | 557 | } 558 | , { 559 | "patchline" : { 560 | "destination" : [ "obj-54", 1 ], 561 | "disabled" : 0, 562 | "hidden" : 0, 563 | "source" : [ "obj-53", 1 ] 564 | } 565 | 566 | } 567 | , { 568 | "patchline" : { 569 | "destination" : [ "obj-59", 0 ], 570 | "disabled" : 0, 571 | "hidden" : 0, 572 | "source" : [ "obj-54", 0 ] 573 | } 574 | 575 | } 576 | , { 577 | "patchline" : { 578 | "destination" : [ "obj-60", 0 ], 579 | "disabled" : 0, 580 | "hidden" : 0, 581 | "source" : [ "obj-54", 1 ] 582 | } 583 | 584 | } 585 | , { 586 | "patchline" : { 587 | "destination" : [ "obj-52", 0 ], 588 | "disabled" : 0, 589 | "hidden" : 0, 590 | "source" : [ "obj-58", 0 ] 591 | } 592 | 593 | } 594 | ] 595 | } 596 | , 597 | "patching_rect" : [ 23.0, 325.0, 83.0, 20.0 ], 598 | "saved_object_attributes" : { 599 | "description" : "", 600 | "digest" : "", 601 | "globalpatchername" : "", 602 | "style" : "", 603 | "tags" : "" 604 | } 605 | , 606 | "style" : "", 607 | "text" : "p compile_msg" 608 | } 609 | 610 | } 611 | , { 612 | "box" : { 613 | "id" : "obj-50", 614 | "maxclass" : "button", 615 | "numinlets" : 1, 616 | "numoutlets" : 1, 617 | "outlettype" : [ "bang" ], 618 | "patching_rect" : [ 52.5, 283.0, 24.0, 24.0 ], 619 | "style" : "" 620 | } 621 | 622 | } 623 | , { 624 | "box" : { 625 | "id" : "obj-42", 626 | "maxclass" : "number", 627 | "numinlets" : 1, 628 | "numoutlets" : 2, 629 | "outlettype" : [ "", "bang" ], 630 | "parameter_enable" : 0, 631 | "patching_rect" : [ 359.0, 389.0, 50.0, 20.0 ], 632 | "presentation" : 1, 633 | "presentation_rect" : [ 9.0, 120.0, 50.0, 20.0 ], 634 | "style" : "" 635 | } 636 | 637 | } 638 | , { 639 | "box" : { 640 | "id" : "obj-40", 641 | "maxclass" : "newobj", 642 | "numinlets" : 1, 643 | "numoutlets" : 1, 644 | "outlettype" : [ "" ], 645 | "patching_rect" : [ 359.0, 421.0, 104.0, 20.0 ], 646 | "style" : "", 647 | "text" : "prepend set_device" 648 | } 649 | 650 | } 651 | , { 652 | "box" : { 653 | "id" : "obj-23", 654 | "maxclass" : "newobj", 655 | "numinlets" : 1, 656 | "numoutlets" : 1, 657 | "outlettype" : [ "" ], 658 | "patching_rect" : [ 207.0, 458.0, 140.0, 20.0 ], 659 | "style" : "", 660 | "text" : "prepend set_percent_value" 661 | } 662 | 663 | } 664 | , { 665 | "box" : { 666 | "id" : "obj-6", 667 | "maxclass" : "newobj", 668 | "numinlets" : 1, 669 | "numoutlets" : 1, 670 | "outlettype" : [ "" ], 671 | "patching_rect" : [ 207.0, 612.0, 103.0, 20.0 ], 672 | "style" : "", 673 | "text" : "prepend set_param" 674 | } 675 | 676 | } 677 | , { 678 | "box" : { 679 | "id" : "obj-35", 680 | "maxclass" : "message", 681 | "numinlets" : 2, 682 | "numoutlets" : 1, 683 | "outlettype" : [ "" ], 684 | "patching_rect" : [ 136.0, 541.0, 34.0, 20.0 ], 685 | "style" : "", 686 | "text" : "clear" 687 | } 688 | 689 | } 690 | , { 691 | "box" : { 692 | "id" : "obj-29", 693 | "maxclass" : "newobj", 694 | "numinlets" : 1, 695 | "numoutlets" : 1, 696 | "outlettype" : [ "" ], 697 | "patching_rect" : [ 207.0, 549.0, 68.0, 20.0 ], 698 | "style" : "", 699 | "text" : "fromsymbol" 700 | } 701 | 702 | } 703 | , { 704 | "box" : { 705 | "id" : "obj-26", 706 | "items" : "", 707 | "maxclass" : "umenu", 708 | "numinlets" : 1, 709 | "numoutlets" : 3, 710 | "outlettype" : [ "int", "", "" ], 711 | "parameter_enable" : 0, 712 | "patching_rect" : [ 207.0, 581.0, 100.0, 20.0 ], 713 | "presentation" : 1, 714 | "presentation_rect" : [ 77.0, 120.0, 100.0, 20.0 ], 715 | "style" : "" 716 | } 717 | 718 | } 719 | , { 720 | "box" : { 721 | "id" : "obj-25", 722 | "maxclass" : "message", 723 | "numinlets" : 2, 724 | "numoutlets" : 1, 725 | "outlettype" : [ "" ], 726 | "patching_rect" : [ 359.0, 504.0, 66.0, 20.0 ], 727 | "presentation" : 1, 728 | "presentation_rect" : [ 9.0, 51.5, 66.0, 20.0 ], 729 | "style" : "", 730 | "text" : "list_params" 731 | } 732 | 733 | } 734 | , { 735 | "box" : { 736 | "id" : "obj-4", 737 | "maxclass" : "newobj", 738 | "numinlets" : 1, 739 | "numoutlets" : 1, 740 | "outlettype" : [ "" ], 741 | "patching_rect" : [ 23.0, 376.0, 85.0, 20.0 ], 742 | "saved_object_attributes" : { 743 | "filename" : "global_m4l.js", 744 | "parameter_enable" : 0 745 | } 746 | , 747 | "style" : "", 748 | "text" : "js global_m4l.js" 749 | } 750 | 751 | } 752 | , { 753 | "box" : { 754 | "fontname" : "Arial Bold", 755 | "fontsize" : 10.0, 756 | "id" : "obj-22", 757 | "maxclass" : "number", 758 | "numinlets" : 1, 759 | "numoutlets" : 2, 760 | "outlettype" : [ "", "bang" ], 761 | "parameter_enable" : 0, 762 | "patching_rect" : [ 128.0, 325.0, 50.0, 20.0 ], 763 | "style" : "" 764 | } 765 | 766 | } 767 | , { 768 | "box" : { 769 | "fontface" : 0, 770 | "fontname" : "Arial Bold", 771 | "fontsize" : 10.0, 772 | "id" : "obj-18", 773 | "maxclass" : "newobj", 774 | "numinlets" : 1, 775 | "numoutlets" : 1, 776 | "outlettype" : [ "" ], 777 | "patching_rect" : [ 128.0, 360.0, 98.0, 20.0 ], 778 | "style" : "", 779 | "text" : "prepend set_value" 780 | } 781 | 782 | } 783 | , { 784 | "box" : { 785 | "fontface" : 0, 786 | "fontname" : "Arial Bold", 787 | "fontsize" : 10.0, 788 | "id" : "obj-3", 789 | "maxclass" : "newobj", 790 | "numinlets" : 1, 791 | "numoutlets" : 1, 792 | "outlettype" : [ "" ], 793 | "patching_rect" : [ 207.0, 520.0, 107.0, 20.0 ], 794 | "saved_object_attributes" : { 795 | "filename" : "param_changer.js", 796 | "parameter_enable" : 0 797 | } 798 | , 799 | "style" : "", 800 | "text" : "js param_changer.js" 801 | } 802 | 803 | } 804 | , { 805 | "box" : { 806 | "fontname" : "Arial Bold", 807 | "fontsize" : 10.0, 808 | "id" : "obj-2", 809 | "maxclass" : "newobj", 810 | "numinlets" : 2, 811 | "numoutlets" : 2, 812 | "outlettype" : [ "signal", "signal" ], 813 | "patching_rect" : [ 23.0, 469.0, 53.0, 20.0 ], 814 | "style" : "", 815 | "text" : "plugout~" 816 | } 817 | 818 | } 819 | , { 820 | "box" : { 821 | "fontname" : "Arial Bold", 822 | "fontsize" : 10.0, 823 | "id" : "obj-1", 824 | "maxclass" : "newobj", 825 | "numinlets" : 2, 826 | "numoutlets" : 2, 827 | "outlettype" : [ "signal", "signal" ], 828 | "patching_rect" : [ 23.0, 421.0, 53.0, 20.0 ], 829 | "style" : "", 830 | "text" : "plugin~" 831 | } 832 | 833 | } 834 | ], 835 | "lines" : [ { 836 | "patchline" : { 837 | "destination" : [ "obj-2", 1 ], 838 | "disabled" : 0, 839 | "hidden" : 0, 840 | "source" : [ "obj-1", 1 ] 841 | } 842 | 843 | } 844 | , { 845 | "patchline" : { 846 | "destination" : [ "obj-2", 0 ], 847 | "disabled" : 0, 848 | "hidden" : 0, 849 | "source" : [ "obj-1", 0 ] 850 | } 851 | 852 | } 853 | , { 854 | "patchline" : { 855 | "destination" : [ "obj-19", 0 ], 856 | "disabled" : 0, 857 | "hidden" : 0, 858 | "source" : [ "obj-10", 0 ] 859 | } 860 | 861 | } 862 | , { 863 | "patchline" : { 864 | "destination" : [ "obj-30", 0 ], 865 | "disabled" : 0, 866 | "hidden" : 0, 867 | "source" : [ "obj-15", 0 ] 868 | } 869 | 870 | } 871 | , { 872 | "patchline" : { 873 | "destination" : [ "obj-3", 0 ], 874 | "disabled" : 0, 875 | "hidden" : 0, 876 | "source" : [ "obj-18", 0 ] 877 | } 878 | 879 | } 880 | , { 881 | "patchline" : { 882 | "destination" : [ "obj-8", 0 ], 883 | "disabled" : 0, 884 | "hidden" : 0, 885 | "source" : [ "obj-19", 0 ] 886 | } 887 | 888 | } 889 | , { 890 | "patchline" : { 891 | "destination" : [ "obj-21", 0 ], 892 | "disabled" : 0, 893 | "hidden" : 0, 894 | "source" : [ "obj-20", 0 ] 895 | } 896 | 897 | } 898 | , { 899 | "patchline" : { 900 | "destination" : [ "obj-8", 1 ], 901 | "disabled" : 0, 902 | "hidden" : 0, 903 | "source" : [ "obj-21", 0 ] 904 | } 905 | 906 | } 907 | , { 908 | "patchline" : { 909 | "destination" : [ "obj-18", 0 ], 910 | "disabled" : 0, 911 | "hidden" : 0, 912 | "source" : [ "obj-22", 0 ] 913 | } 914 | 915 | } 916 | , { 917 | "patchline" : { 918 | "destination" : [ "obj-3", 0 ], 919 | "disabled" : 0, 920 | "hidden" : 0, 921 | "source" : [ "obj-23", 0 ] 922 | } 923 | 924 | } 925 | , { 926 | "patchline" : { 927 | "destination" : [ "obj-3", 0 ], 928 | "disabled" : 0, 929 | "hidden" : 0, 930 | "source" : [ "obj-25", 0 ] 931 | } 932 | 933 | } 934 | , { 935 | "patchline" : { 936 | "destination" : [ "obj-6", 0 ], 937 | "disabled" : 0, 938 | "hidden" : 0, 939 | "source" : [ "obj-26", 0 ] 940 | } 941 | 942 | } 943 | , { 944 | "patchline" : { 945 | "destination" : [ "obj-61", 0 ], 946 | "disabled" : 0, 947 | "hidden" : 0, 948 | "source" : [ "obj-27", 0 ] 949 | } 950 | 951 | } 952 | , { 953 | "patchline" : { 954 | "destination" : [ "obj-26", 0 ], 955 | "disabled" : 0, 956 | "hidden" : 0, 957 | "source" : [ "obj-29", 0 ] 958 | } 959 | 960 | } 961 | , { 962 | "patchline" : { 963 | "destination" : [ "obj-29", 0 ], 964 | "disabled" : 0, 965 | "hidden" : 0, 966 | "source" : [ "obj-3", 0 ] 967 | } 968 | 969 | } 970 | , { 971 | "patchline" : { 972 | "destination" : [ "obj-20", 0 ], 973 | "disabled" : 0, 974 | "hidden" : 0, 975 | "source" : [ "obj-30", 0 ] 976 | } 977 | 978 | } 979 | , { 980 | "patchline" : { 981 | "destination" : [ "obj-26", 0 ], 982 | "disabled" : 0, 983 | "hidden" : 0, 984 | "source" : [ "obj-35", 0 ] 985 | } 986 | 987 | } 988 | , { 989 | "patchline" : { 990 | "destination" : [ "obj-3", 0 ], 991 | "disabled" : 0, 992 | "hidden" : 0, 993 | "source" : [ "obj-40", 0 ] 994 | } 995 | 996 | } 997 | , { 998 | "patchline" : { 999 | "destination" : [ "obj-40", 0 ], 1000 | "disabled" : 0, 1001 | "hidden" : 0, 1002 | "source" : [ "obj-42", 0 ] 1003 | } 1004 | 1005 | } 1006 | , { 1007 | "patchline" : { 1008 | "destination" : [ "obj-23", 0 ], 1009 | "disabled" : 0, 1010 | "hidden" : 0, 1011 | "source" : [ "obj-5", 0 ] 1012 | } 1013 | 1014 | } 1015 | , { 1016 | "patchline" : { 1017 | "destination" : [ "obj-61", 0 ], 1018 | "disabled" : 0, 1019 | "hidden" : 0, 1020 | "source" : [ "obj-50", 0 ] 1021 | } 1022 | 1023 | } 1024 | , { 1025 | "patchline" : { 1026 | "destination" : [ "obj-3", 0 ], 1027 | "disabled" : 0, 1028 | "hidden" : 0, 1029 | "midpoints" : [ 216.5, 645.0, 189.0, 645.0, 189.0, 502.0, 216.5, 502.0 ], 1030 | "source" : [ "obj-6", 0 ] 1031 | } 1032 | 1033 | } 1034 | , { 1035 | "patchline" : { 1036 | "destination" : [ "obj-3", 0 ], 1037 | "disabled" : 0, 1038 | "hidden" : 0, 1039 | "source" : [ "obj-61", 1 ] 1040 | } 1041 | 1042 | } 1043 | , { 1044 | "patchline" : { 1045 | "destination" : [ "obj-4", 0 ], 1046 | "disabled" : 0, 1047 | "hidden" : 0, 1048 | "source" : [ "obj-61", 0 ] 1049 | } 1050 | 1051 | } 1052 | , { 1053 | "patchline" : { 1054 | "destination" : [ "obj-5", 0 ], 1055 | "disabled" : 0, 1056 | "hidden" : 0, 1057 | "source" : [ "obj-8", 1 ] 1058 | } 1059 | 1060 | } 1061 | , { 1062 | "patchline" : { 1063 | "destination" : [ "obj-9", 0 ], 1064 | "disabled" : 0, 1065 | "hidden" : 0, 1066 | "source" : [ "obj-8", 0 ] 1067 | } 1068 | 1069 | } 1070 | , { 1071 | "patchline" : { 1072 | "destination" : [ "obj-18", 0 ], 1073 | "disabled" : 0, 1074 | "hidden" : 0, 1075 | "source" : [ "obj-9", 0 ] 1076 | } 1077 | 1078 | } 1079 | ], 1080 | "parameters" : { 1081 | "obj-5" : [ "live.dial", "live.dial", 0 ], 1082 | "obj-9" : [ "live.numbox", "live.numbox", 0 ], 1083 | "obj-10" : [ "live.toggle", "live.toggle", 0 ] 1084 | } 1085 | , 1086 | "dependency_cache" : [ { 1087 | "name" : "param_changer.js", 1088 | "bootpath" : "~/Documents/Git/m4l_js2liveAPI/m4l/js", 1089 | "type" : "TEXT", 1090 | "implicit" : 1 1091 | } 1092 | , { 1093 | "name" : "global_m4l.js", 1094 | "bootpath" : "~/Documents/Git/m4l_js2liveAPI/m4l/js", 1095 | "type" : "TEXT", 1096 | "implicit" : 1 1097 | } 1098 | ], 1099 | "latency" : 0, 1100 | "project" : { 1101 | "version" : 1, 1102 | "creationdate" : -835264559, 1103 | "modificationdate" : -835264559, 1104 | "viewrect" : [ 0.0, 0.0, 300.0, 500.0 ], 1105 | "autoorganize" : 1, 1106 | "hideprojectwindow" : 1, 1107 | "showdependencies" : 1, 1108 | "autolocalize" : 0, 1109 | "contents" : { 1110 | "patchers" : { 1111 | 1112 | } 1113 | , 1114 | "code" : { 1115 | 1116 | } 1117 | 1118 | } 1119 | , 1120 | "layout" : { 1121 | 1122 | } 1123 | , 1124 | "searchpath" : { 1125 | 1126 | } 1127 | , 1128 | "detailsvisible" : 0, 1129 | "amxdtype" : 0, 1130 | "readonly" : 1, 1131 | "devpathtype" : 0, 1132 | "devpath" : "." 1133 | } 1134 | , 1135 | "autosave" : 0 1136 | } 1137 | 1138 | } 1139 | -------------------------------------------------------------------------------- /m4l/amxd/parse_chord.amxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blm81/m4l_js2liveAPI/a4b615280416ef6926ba4d523710878d0d014c98/m4l/amxd/parse_chord.amxd -------------------------------------------------------------------------------- /m4l/amxd/sf_player.amxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blm81/m4l_js2liveAPI/a4b615280416ef6926ba4d523710878d0d014c98/m4l/amxd/sf_player.amxd -------------------------------------------------------------------------------- /m4l/amxd/tcp_client.amxd: -------------------------------------------------------------------------------- 1 | ampfaaaametaptcht{ 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 7, 6 | "minor" : 0, 7 | "revision" : 3, 8 | "architecture" : "x86", 9 | "modernui" : 1 10 | } 11 | , 12 | "rect" : [ 320.0, 362.0, 594.0, 424.0 ], 13 | "openrect" : [ 0.0, 0.0, 0.0, 169.0 ], 14 | "bglocked" : 0, 15 | "openinpresentation" : 1, 16 | "default_fontsize" : 10.0, 17 | "default_fontface" : 0, 18 | "default_fontname" : "Arial Bold", 19 | "gridonopen" : 1, 20 | "gridsize" : [ 8.0, 8.0 ], 21 | "gridsnaponopen" : 1, 22 | "objectsnaponopen" : 1, 23 | "statusbarvisible" : 2, 24 | "toolbarvisible" : 1, 25 | "lefttoolbarpinned" : 0, 26 | "toptoolbarpinned" : 0, 27 | "righttoolbarpinned" : 0, 28 | "bottomtoolbarpinned" : 0, 29 | "toolbars_unpinned_last_save" : 0, 30 | "tallnewobj" : 0, 31 | "boxanimatetime" : 500, 32 | "enablehscroll" : 1, 33 | "enablevscroll" : 1, 34 | "devicewidth" : 0.0, 35 | "description" : "", 36 | "digest" : "", 37 | "tags" : "", 38 | "style" : "", 39 | "subpatcher_template" : "", 40 | "boxes" : [ { 41 | "box" : { 42 | "id" : "obj-26", 43 | "maxclass" : "comment", 44 | "numinlets" : 1, 45 | "numoutlets" : 0, 46 | "patching_rect" : [ 369.799988, 205.0, 52.0, 18.0 ], 47 | "presentation" : 1, 48 | "presentation_rect" : [ 54.0, 97.0, 66.0, 18.0 ], 49 | "style" : "", 50 | "text" : "name" 51 | } 52 | 53 | } 54 | , { 55 | "box" : { 56 | "id" : "obj-25", 57 | "maxclass" : "comment", 58 | "numinlets" : 1, 59 | "numoutlets" : 0, 60 | "patching_rect" : [ 277.0, 235.0, 34.0, 18.0 ], 61 | "presentation" : 1, 62 | "presentation_rect" : [ 10.0, 97.0, 66.0, 18.0 ], 63 | "style" : "", 64 | "text" : "close" 65 | } 66 | 67 | } 68 | , { 69 | "box" : { 70 | "id" : "obj-12", 71 | "maxclass" : "newobj", 72 | "numinlets" : 1, 73 | "numoutlets" : 1, 74 | "outlettype" : [ "" ], 75 | "patching_rect" : [ 459.5, 282.0, 67.0, 20.0 ], 76 | "style" : "", 77 | "text" : "prepend set" 78 | } 79 | 80 | } 81 | , { 82 | "box" : { 83 | "id" : "obj-11", 84 | "maxclass" : "newobj", 85 | "numinlets" : 1, 86 | "numoutlets" : 1, 87 | "outlettype" : [ "" ], 88 | "patching_rect" : [ 459.5, 315.0, 19.0, 20.0 ], 89 | "style" : "", 90 | "text" : "r" 91 | } 92 | 93 | } 94 | , { 95 | "box" : { 96 | "id" : "obj-3", 97 | "linecount" : 2, 98 | "maxclass" : "comment", 99 | "numinlets" : 1, 100 | "numoutlets" : 0, 101 | "patching_rect" : [ 459.5, 193.5, 52.0, 29.0 ], 102 | "presentation" : 1, 103 | "presentation_linecount" : 2, 104 | "presentation_rect" : [ 54.0, 43.0, 66.0, 29.0 ], 105 | "style" : "", 106 | "text" : "receive from" 107 | } 108 | 109 | } 110 | , { 111 | "box" : { 112 | "id" : "obj-5", 113 | "maxclass" : "newobj", 114 | "numinlets" : 2, 115 | "numoutlets" : 2, 116 | "outlettype" : [ "", "" ], 117 | "patching_rect" : [ 459.5, 254.0, 63.0, 20.0 ], 118 | "style" : "", 119 | "text" : "zl.filter text" 120 | } 121 | 122 | } 123 | , { 124 | "box" : { 125 | "id" : "obj-6", 126 | "maxclass" : "textedit", 127 | "numinlets" : 1, 128 | "numoutlets" : 4, 129 | "outlettype" : [ "", "int", "", "" ], 130 | "parameter_enable" : 0, 131 | "patching_rect" : [ 459.5, 221.5, 80.0, 20.0 ], 132 | "presentation" : 1, 133 | "presentation_rect" : [ 54.0, 74.0, 77.0, 17.0 ], 134 | "style" : "", 135 | "text" : "to_server" 136 | } 137 | 138 | } 139 | , { 140 | "box" : { 141 | "id" : "obj-7", 142 | "maxclass" : "comment", 143 | "numinlets" : 1, 144 | "numoutlets" : 0, 145 | "patching_rect" : [ 122.5, 205.0, 52.0, 18.0 ], 146 | "presentation" : 1, 147 | "presentation_rect" : [ 54.0, 6.0, 66.0, 18.0 ], 148 | "style" : "", 149 | "text" : "send to" 150 | } 151 | 152 | } 153 | , { 154 | "box" : { 155 | "id" : "obj-31", 156 | "maxclass" : "newobj", 157 | "numinlets" : 1, 158 | "numoutlets" : 1, 159 | "outlettype" : [ "" ], 160 | "patching_rect" : [ 122.5, 288.0, 76.0, 20.0 ], 161 | "style" : "", 162 | "text" : "prepend send" 163 | } 164 | 165 | } 166 | , { 167 | "box" : { 168 | "id" : "obj-30", 169 | "maxclass" : "newobj", 170 | "numinlets" : 2, 171 | "numoutlets" : 2, 172 | "outlettype" : [ "", "" ], 173 | "patching_rect" : [ 122.5, 256.5, 63.0, 20.0 ], 174 | "style" : "", 175 | "text" : "zl.filter text" 176 | } 177 | 178 | } 179 | , { 180 | "box" : { 181 | "id" : "obj-19", 182 | "maxclass" : "textedit", 183 | "numinlets" : 1, 184 | "numoutlets" : 4, 185 | "outlettype" : [ "", "int", "", "" ], 186 | "parameter_enable" : 0, 187 | "patching_rect" : [ 122.5, 233.0, 80.0, 20.0 ], 188 | "presentation" : 1, 189 | "presentation_rect" : [ 54.0, 24.0, 77.0, 17.0 ], 190 | "style" : "" 191 | } 192 | 193 | } 194 | , { 195 | "box" : { 196 | "id" : "obj-4", 197 | "maxclass" : "newobj", 198 | "numinlets" : 1, 199 | "numoutlets" : 0, 200 | "patching_rect" : [ 122.5, 366.0, 47.0, 20.0 ], 201 | "style" : "", 202 | "text" : "forward" 203 | } 204 | 205 | } 206 | , { 207 | "box" : { 208 | "id" : "obj-27", 209 | "maxclass" : "newobj", 210 | "numinlets" : 1, 211 | "numoutlets" : 3, 212 | "outlettype" : [ "bang", "int", "int" ], 213 | "patching_rect" : [ 23.0, 199.0, 79.0, 20.0 ], 214 | "style" : "", 215 | "text" : "live.thisdevice" 216 | } 217 | 218 | } 219 | , { 220 | "box" : { 221 | "id" : "obj-51", 222 | "maxclass" : "comment", 223 | "numinlets" : 1, 224 | "numoutlets" : 0, 225 | "patching_rect" : [ 323.599976, 235.0, 37.0, 18.0 ], 226 | "presentation" : 1, 227 | "presentation_rect" : [ 10.0, 6.0, 36.0, 18.0 ], 228 | "style" : "", 229 | "text" : "port" 230 | } 231 | 232 | } 233 | , { 234 | "box" : { 235 | "id" : "obj-48", 236 | "maxclass" : "comment", 237 | "numinlets" : 1, 238 | "numoutlets" : 0, 239 | "patching_rect" : [ 229.0, 235.0, 34.0, 18.0 ], 240 | "presentation" : 1, 241 | "presentation_rect" : [ 10.0, 43.0, 66.0, 18.0 ], 242 | "style" : "", 243 | "text" : "open" 244 | } 245 | 246 | } 247 | , { 248 | "box" : { 249 | "id" : "obj-43", 250 | "maxclass" : "newobj", 251 | "numinlets" : 2, 252 | "numoutlets" : 2, 253 | "outlettype" : [ "", "" ], 254 | "patching_rect" : [ 369.799988, 254.0, 63.0, 20.0 ], 255 | "style" : "", 256 | "text" : "zl filter text" 257 | } 258 | 259 | } 260 | , { 261 | "box" : { 262 | "id" : "obj-33", 263 | "maxclass" : "textedit", 264 | "numinlets" : 1, 265 | "numoutlets" : 4, 266 | "outlettype" : [ "", "int", "", "" ], 267 | "parameter_enable" : 0, 268 | "patching_rect" : [ 369.799988, 226.0, 78.0, 19.0 ], 269 | "presentation" : 1, 270 | "presentation_rect" : [ 54.0, 119.5, 78.0, 19.0 ], 271 | "style" : "", 272 | "text" : "max" 273 | } 274 | 275 | } 276 | , { 277 | "box" : { 278 | "id" : "obj-15", 279 | "maxclass" : "live.numbox", 280 | "numinlets" : 1, 281 | "numoutlets" : 2, 282 | "outlettype" : [ "", "float" ], 283 | "parameter_enable" : 1, 284 | "patching_rect" : [ 323.599976, 256.5, 36.0, 15.0 ], 285 | "presentation" : 1, 286 | "presentation_rect" : [ 10.0, 26.0, 36.0, 15.0 ], 287 | "saved_attribute_attributes" : { 288 | "valueof" : { 289 | "parameter_longname" : "live.numbox", 290 | "parameter_shortname" : "live.numbox", 291 | "parameter_type" : 0, 292 | "parameter_mmin" : 1000.0, 293 | "parameter_mmax" : 9999.0, 294 | "parameter_unitstyle" : 0 295 | } 296 | 297 | } 298 | , 299 | "varname" : "live.numbox" 300 | } 301 | 302 | } 303 | , { 304 | "box" : { 305 | "id" : "obj-10", 306 | "maxclass" : "button", 307 | "numinlets" : 1, 308 | "numoutlets" : 1, 309 | "outlettype" : [ "bang" ], 310 | "patching_rect" : [ 277.0, 256.5, 24.0, 24.0 ], 311 | "presentation" : 1, 312 | "presentation_rect" : [ 10.0, 114.5, 24.0, 24.0 ], 313 | "style" : "", 314 | "varname" : "live.button[1]" 315 | } 316 | 317 | } 318 | , { 319 | "box" : { 320 | "id" : "obj-9", 321 | "maxclass" : "button", 322 | "numinlets" : 1, 323 | "numoutlets" : 1, 324 | "outlettype" : [ "bang" ], 325 | "patching_rect" : [ 229.0, 256.5, 24.0, 24.0 ], 326 | "presentation" : 1, 327 | "presentation_rect" : [ 10.0, 63.0, 24.0, 24.0 ], 328 | "style" : "", 329 | "varname" : "live.button" 330 | } 331 | 332 | } 333 | , { 334 | "box" : { 335 | "id" : "obj-8", 336 | "maxclass" : "newobj", 337 | "numinlets" : 6, 338 | "numoutlets" : 1, 339 | "outlettype" : [ "" ], 340 | "patcher" : { 341 | "fileversion" : 1, 342 | "appversion" : { 343 | "major" : 7, 344 | "minor" : 0, 345 | "revision" : 3, 346 | "architecture" : "x86", 347 | "modernui" : 1 348 | } 349 | , 350 | "rect" : [ 130.0, 139.0, 688.0, 713.0 ], 351 | "bglocked" : 0, 352 | "openinpresentation" : 0, 353 | "default_fontsize" : 12.0, 354 | "default_fontface" : 0, 355 | "default_fontname" : "Arial", 356 | "gridonopen" : 1, 357 | "gridsize" : [ 15.0, 15.0 ], 358 | "gridsnaponopen" : 1, 359 | "objectsnaponopen" : 1, 360 | "statusbarvisible" : 2, 361 | "toolbarvisible" : 1, 362 | "lefttoolbarpinned" : 0, 363 | "toptoolbarpinned" : 0, 364 | "righttoolbarpinned" : 0, 365 | "bottomtoolbarpinned" : 0, 366 | "toolbars_unpinned_last_save" : 0, 367 | "tallnewobj" : 0, 368 | "boxanimatetime" : 200, 369 | "enablehscroll" : 1, 370 | "enablevscroll" : 1, 371 | "devicewidth" : 0.0, 372 | "description" : "", 373 | "digest" : "", 374 | "tags" : "", 375 | "style" : "", 376 | "subpatcher_template" : "", 377 | "boxes" : [ { 378 | "box" : { 379 | "comment" : "", 380 | "id" : "obj-38", 381 | "maxclass" : "outlet", 382 | "numinlets" : 1, 383 | "numoutlets" : 0, 384 | "patching_rect" : [ 133.5, 664.0, 30.0, 30.0 ], 385 | "style" : "" 386 | } 387 | 388 | } 389 | , { 390 | "box" : { 391 | "id" : "obj-37", 392 | "maxclass" : "comment", 393 | "numinlets" : 1, 394 | "numoutlets" : 0, 395 | "patching_rect" : [ 479.0, 54.0, 72.0, 20.0 ], 396 | "style" : "", 397 | "text" : "send value" 398 | } 399 | 400 | } 401 | , { 402 | "box" : { 403 | "id" : "obj-35", 404 | "maxclass" : "comment", 405 | "numinlets" : 1, 406 | "numoutlets" : 0, 407 | "patching_rect" : [ 402.0, 54.0, 72.0, 20.0 ], 408 | "style" : "", 409 | "text" : "set name" 410 | } 411 | 412 | } 413 | , { 414 | "box" : { 415 | "comment" : "value: send value", 416 | "id" : "obj-34", 417 | "maxclass" : "inlet", 418 | "numinlets" : 0, 419 | "numoutlets" : 1, 420 | "outlettype" : [ "" ], 421 | "patching_rect" : [ 485.0, 101.0, 30.0, 30.0 ], 422 | "style" : "" 423 | } 424 | 425 | } 426 | , { 427 | "box" : { 428 | "comment" : "string: set name", 429 | "id" : "obj-33", 430 | "maxclass" : "inlet", 431 | "numinlets" : 0, 432 | "numoutlets" : 1, 433 | "outlettype" : [ "" ], 434 | "patching_rect" : [ 411.0, 100.0, 30.0, 30.0 ], 435 | "style" : "" 436 | } 437 | 438 | } 439 | , { 440 | "box" : { 441 | "comment" : "int: set port number", 442 | "id" : "obj-31", 443 | "maxclass" : "inlet", 444 | "numinlets" : 0, 445 | "numoutlets" : 1, 446 | "outlettype" : [ "" ], 447 | "patching_rect" : [ 332.0, 100.0, 30.0, 30.0 ], 448 | "style" : "" 449 | } 450 | 451 | } 452 | , { 453 | "box" : { 454 | "comment" : "bang: close connection", 455 | "id" : "obj-27", 456 | "maxclass" : "inlet", 457 | "numinlets" : 0, 458 | "numoutlets" : 1, 459 | "outlettype" : [ "bang" ], 460 | "patching_rect" : [ 241.0, 100.0, 30.0, 30.0 ], 461 | "style" : "" 462 | } 463 | 464 | } 465 | , { 466 | "box" : { 467 | "comment" : "bang: open connection", 468 | "id" : "obj-24", 469 | "maxclass" : "inlet", 470 | "numinlets" : 0, 471 | "numoutlets" : 1, 472 | "outlettype" : [ "bang" ], 473 | "patching_rect" : [ 153.0, 103.0, 30.0, 30.0 ], 474 | "style" : "" 475 | } 476 | 477 | } 478 | , { 479 | "box" : { 480 | "id" : "obj-22", 481 | "maxclass" : "newobj", 482 | "numinlets" : 1, 483 | "numoutlets" : 1, 484 | "outlettype" : [ "int" ], 485 | "patching_rect" : [ 73.0, 216.0, 24.0, 22.0 ], 486 | "style" : "", 487 | "text" : "t 1" 488 | } 489 | 490 | } 491 | , { 492 | "box" : { 493 | "comment" : "bang: read from socket", 494 | "id" : "obj-15", 495 | "maxclass" : "inlet", 496 | "numinlets" : 0, 497 | "numoutlets" : 1, 498 | "outlettype" : [ "bang" ], 499 | "patching_rect" : [ 73.0, 103.0, 30.0, 30.0 ], 500 | "style" : "" 501 | } 502 | 503 | } 504 | , { 505 | "box" : { 506 | "id" : "obj-30", 507 | "maxclass" : "message", 508 | "numinlets" : 2, 509 | "numoutlets" : 1, 510 | "outlettype" : [ "" ], 511 | "patching_rect" : [ 492.0, 261.0, 59.0, 22.0 ], 512 | "style" : "", 513 | "text" : "max_test" 514 | } 515 | 516 | } 517 | , { 518 | "box" : { 519 | "id" : "obj-25", 520 | "maxclass" : "newobj", 521 | "numinlets" : 1, 522 | "numoutlets" : 1, 523 | "outlettype" : [ "" ], 524 | "patching_rect" : [ 411.0, 314.0, 111.0, 22.0 ], 525 | "style" : "", 526 | "text" : "prepend set_name" 527 | } 528 | 529 | } 530 | , { 531 | "box" : { 532 | "id" : "obj-36", 533 | "maxclass" : "newobj", 534 | "numinlets" : 1, 535 | "numoutlets" : 1, 536 | "outlettype" : [ "" ], 537 | "patching_rect" : [ 133.5, 573.0, 73.0, 22.0 ], 538 | "style" : "", 539 | "text" : "fromsymbol" 540 | } 541 | 542 | } 543 | , { 544 | "box" : { 545 | "id" : "obj-29", 546 | "maxclass" : "newobj", 547 | "numinlets" : 2, 548 | "numoutlets" : 2, 549 | "outlettype" : [ "", "" ], 550 | "patching_rect" : [ 133.5, 601.0, 106.0, 22.0 ], 551 | "style" : "", 552 | "text" : "route alpha_value" 553 | } 554 | 555 | } 556 | , { 557 | "box" : { 558 | "format" : 6, 559 | "id" : "obj-28", 560 | "maxclass" : "flonum", 561 | "numinlets" : 1, 562 | "numoutlets" : 2, 563 | "outlettype" : [ "", "bang" ], 564 | "parameter_enable" : 0, 565 | "patching_rect" : [ 133.5, 630.0, 50.0, 22.0 ], 566 | "style" : "" 567 | } 568 | 569 | } 570 | , { 571 | "box" : { 572 | "id" : "obj-20", 573 | "maxclass" : "message", 574 | "numinlets" : 2, 575 | "numoutlets" : 1, 576 | "outlettype" : [ "" ], 577 | "patching_rect" : [ 485.0, 211.0, 77.0, 22.0 ], 578 | "style" : "", 579 | "text" : "to_server $1" 580 | } 581 | 582 | } 583 | , { 584 | "box" : { 585 | "id" : "obj-13", 586 | "linecount" : 2, 587 | "maxclass" : "comment", 588 | "numinlets" : 1, 589 | "numoutlets" : 0, 590 | "patching_rect" : [ 560.0, 54.0, 72.0, 33.0 ], 591 | "style" : "", 592 | "text" : "set hostname" 593 | } 594 | 595 | } 596 | , { 597 | "box" : { 598 | "id" : "obj-5", 599 | "linecount" : 2, 600 | "maxclass" : "comment", 601 | "numinlets" : 1, 602 | "numoutlets" : 0, 603 | "patching_rect" : [ 325.0, 54.0, 72.0, 33.0 ], 604 | "style" : "", 605 | "text" : "set port number" 606 | } 607 | 608 | } 609 | , { 610 | "box" : { 611 | "id" : "obj-19", 612 | "maxclass" : "number", 613 | "numinlets" : 1, 614 | "numoutlets" : 2, 615 | "outlettype" : [ "", "bang" ], 616 | "parameter_enable" : 0, 617 | "patching_rect" : [ 332.0, 147.0, 50.0, 22.0 ], 618 | "style" : "" 619 | } 620 | 621 | } 622 | , { 623 | "box" : { 624 | "id" : "obj-26", 625 | "maxclass" : "message", 626 | "numinlets" : 2, 627 | "numoutlets" : 1, 628 | "outlettype" : [ "" ], 629 | "patching_rect" : [ 560.0, 100.0, 61.0, 22.0 ], 630 | "style" : "", 631 | "text" : "127.0.0.1" 632 | } 633 | 634 | } 635 | , { 636 | "box" : { 637 | "id" : "obj-18", 638 | "maxclass" : "message", 639 | "numinlets" : 2, 640 | "numoutlets" : 1, 641 | "outlettype" : [ "" ], 642 | "patching_rect" : [ 560.0, 147.0, 103.0, 22.0 ], 643 | "style" : "", 644 | "text" : "set_hostname $1" 645 | } 646 | 647 | } 648 | , { 649 | "box" : { 650 | "id" : "obj-17", 651 | "maxclass" : "message", 652 | "numinlets" : 2, 653 | "numoutlets" : 1, 654 | "outlettype" : [ "" ], 655 | "patching_rect" : [ 332.0, 184.0, 71.0, 22.0 ], 656 | "style" : "", 657 | "text" : "set_port $1" 658 | } 659 | 660 | } 661 | , { 662 | "box" : { 663 | "id" : "obj-14", 664 | "maxclass" : "newobj", 665 | "numinlets" : 2, 666 | "numoutlets" : 2, 667 | "outlettype" : [ "", "" ], 668 | "patching_rect" : [ 68.5, 429.0, 64.0, 22.0 ], 669 | "style" : "", 670 | "text" : "route msg" 671 | } 672 | 673 | } 674 | , { 675 | "box" : { 676 | "id" : "obj-16", 677 | "maxclass" : "message", 678 | "numinlets" : 2, 679 | "numoutlets" : 1, 680 | "outlettype" : [ "" ], 681 | "patching_rect" : [ 134.5, 468.0, 52.0, 22.0 ], 682 | "style" : "", 683 | "text" : "compile" 684 | } 685 | 686 | } 687 | , { 688 | "box" : { 689 | "id" : "obj-12", 690 | "maxclass" : "newobj", 691 | "numinlets" : 2, 692 | "numoutlets" : 2, 693 | "outlettype" : [ "", "" ], 694 | "patching_rect" : [ 67.5, 533.0, 85.0, 22.0 ], 695 | "saved_object_attributes" : { 696 | "parameter_enable" : 0 697 | } 698 | , 699 | "style" : "", 700 | "text" : "js tcp_client.js" 701 | } 702 | 703 | } 704 | , { 705 | "box" : { 706 | "id" : "obj-11", 707 | "maxclass" : "message", 708 | "numinlets" : 2, 709 | "numoutlets" : 1, 710 | "outlettype" : [ "" ], 711 | "patching_rect" : [ 161.5, 336.0, 53.0, 22.0 ], 712 | "style" : "", 713 | "text" : "send $1" 714 | } 715 | 716 | } 717 | , { 718 | "box" : { 719 | "id" : "obj-10", 720 | "linecount" : 2, 721 | "maxclass" : "comment", 722 | "numinlets" : 1, 723 | "numoutlets" : 0, 724 | "patching_rect" : [ 241.0, 54.0, 72.0, 33.0 ], 725 | "style" : "", 726 | "text" : "close connection" 727 | } 728 | 729 | } 730 | , { 731 | "box" : { 732 | "id" : "obj-8", 733 | "linecount" : 2, 734 | "maxclass" : "comment", 735 | "numinlets" : 1, 736 | "numoutlets" : 0, 737 | "patching_rect" : [ 153.0, 54.0, 72.0, 33.0 ], 738 | "style" : "", 739 | "text" : "open connection" 740 | } 741 | 742 | } 743 | , { 744 | "box" : { 745 | "id" : "obj-7", 746 | "linecount" : 3, 747 | "maxclass" : "comment", 748 | "numinlets" : 1, 749 | "numoutlets" : 0, 750 | "patching_rect" : [ 50.0, 47.0, 87.0, 47.0 ], 751 | "style" : "", 752 | "text" : "send bangs to read from socket" 753 | } 754 | 755 | } 756 | , { 757 | "box" : { 758 | "id" : "obj-3", 759 | "maxclass" : "newobj", 760 | "numinlets" : 1, 761 | "numoutlets" : 0, 762 | "patching_rect" : [ 161.5, 429.0, 34.0, 22.0 ], 763 | "style" : "", 764 | "text" : "print" 765 | } 766 | 767 | } 768 | , { 769 | "box" : { 770 | "id" : "obj-9", 771 | "maxclass" : "message", 772 | "numinlets" : 2, 773 | "numoutlets" : 1, 774 | "outlettype" : [ "" ], 775 | "patching_rect" : [ 241.0, 157.0, 71.0, 22.0 ], 776 | "style" : "", 777 | "text" : "close_conn" 778 | } 779 | 780 | } 781 | , { 782 | "box" : { 783 | "id" : "obj-6", 784 | "maxclass" : "message", 785 | "numinlets" : 2, 786 | "numoutlets" : 1, 787 | "outlettype" : [ "" ], 788 | "patching_rect" : [ 153.0, 157.0, 70.0, 22.0 ], 789 | "style" : "", 790 | "text" : "open_conn" 791 | } 792 | 793 | } 794 | , { 795 | "box" : { 796 | "id" : "obj-2", 797 | "maxclass" : "newobj", 798 | "numinlets" : 2, 799 | "numoutlets" : 1, 800 | "outlettype" : [ "bang" ], 801 | "patching_rect" : [ 73.0, 261.0, 58.0, 22.0 ], 802 | "style" : "", 803 | "text" : "metro 30" 804 | } 805 | 806 | } 807 | , { 808 | "box" : { 809 | "id" : "obj-1", 810 | "maxclass" : "newobj", 811 | "numinlets" : 1, 812 | "numoutlets" : 2, 813 | "outlettype" : [ "", "" ], 814 | "patching_rect" : [ 68.5, 359.0, 60.0, 22.0 ], 815 | "style" : "", 816 | "text" : "TcpClient" 817 | } 818 | 819 | } 820 | ], 821 | "lines" : [ { 822 | "patchline" : { 823 | "destination" : [ "obj-14", 0 ], 824 | "disabled" : 0, 825 | "hidden" : 0, 826 | "source" : [ "obj-1", 0 ] 827 | } 828 | 829 | } 830 | , { 831 | "patchline" : { 832 | "destination" : [ "obj-3", 0 ], 833 | "disabled" : 0, 834 | "hidden" : 0, 835 | "source" : [ "obj-1", 0 ] 836 | } 837 | 838 | } 839 | , { 840 | "patchline" : { 841 | "destination" : [ "obj-1", 0 ], 842 | "disabled" : 0, 843 | "hidden" : 0, 844 | "source" : [ "obj-11", 0 ] 845 | } 846 | 847 | } 848 | , { 849 | "patchline" : { 850 | "destination" : [ "obj-3", 0 ], 851 | "disabled" : 0, 852 | "hidden" : 0, 853 | "source" : [ "obj-11", 0 ] 854 | } 855 | 856 | } 857 | , { 858 | "patchline" : { 859 | "destination" : [ "obj-11", 0 ], 860 | "disabled" : 0, 861 | "hidden" : 0, 862 | "midpoints" : [ 77.0, 566.0, 223.5, 566.0, 223.5, 322.0, 171.0, 322.0 ], 863 | "source" : [ "obj-12", 0 ] 864 | } 865 | 866 | } 867 | , { 868 | "patchline" : { 869 | "destination" : [ "obj-36", 0 ], 870 | "disabled" : 0, 871 | "hidden" : 0, 872 | "source" : [ "obj-12", 1 ] 873 | } 874 | 875 | } 876 | , { 877 | "patchline" : { 878 | "destination" : [ "obj-12", 0 ], 879 | "disabled" : 0, 880 | "hidden" : 0, 881 | "source" : [ "obj-14", 0 ] 882 | } 883 | 884 | } 885 | , { 886 | "patchline" : { 887 | "destination" : [ "obj-16", 0 ], 888 | "disabled" : 0, 889 | "hidden" : 0, 890 | "source" : [ "obj-15", 0 ] 891 | } 892 | 893 | } 894 | , { 895 | "patchline" : { 896 | "destination" : [ "obj-22", 0 ], 897 | "disabled" : 0, 898 | "hidden" : 0, 899 | "source" : [ "obj-15", 0 ] 900 | } 901 | 902 | } 903 | , { 904 | "patchline" : { 905 | "destination" : [ "obj-12", 0 ], 906 | "disabled" : 0, 907 | "hidden" : 0, 908 | "source" : [ "obj-16", 0 ] 909 | } 910 | 911 | } 912 | , { 913 | "patchline" : { 914 | "destination" : [ "obj-1", 0 ], 915 | "disabled" : 0, 916 | "hidden" : 0, 917 | "source" : [ "obj-17", 0 ] 918 | } 919 | 920 | } 921 | , { 922 | "patchline" : { 923 | "destination" : [ "obj-1", 0 ], 924 | "disabled" : 0, 925 | "hidden" : 0, 926 | "source" : [ "obj-18", 0 ] 927 | } 928 | 929 | } 930 | , { 931 | "patchline" : { 932 | "destination" : [ "obj-17", 0 ], 933 | "disabled" : 0, 934 | "hidden" : 0, 935 | "source" : [ "obj-19", 0 ] 936 | } 937 | 938 | } 939 | , { 940 | "patchline" : { 941 | "destination" : [ "obj-1", 0 ], 942 | "disabled" : 0, 943 | "hidden" : 0, 944 | "source" : [ "obj-2", 0 ] 945 | } 946 | 947 | } 948 | , { 949 | "patchline" : { 950 | "destination" : [ "obj-12", 1 ], 951 | "disabled" : 0, 952 | "hidden" : 0, 953 | "source" : [ "obj-20", 0 ] 954 | } 955 | 956 | } 957 | , { 958 | "patchline" : { 959 | "destination" : [ "obj-2", 0 ], 960 | "disabled" : 0, 961 | "hidden" : 0, 962 | "source" : [ "obj-22", 0 ] 963 | } 964 | 965 | } 966 | , { 967 | "patchline" : { 968 | "destination" : [ "obj-6", 0 ], 969 | "disabled" : 0, 970 | "hidden" : 0, 971 | "source" : [ "obj-24", 0 ] 972 | } 973 | 974 | } 975 | , { 976 | "patchline" : { 977 | "destination" : [ "obj-12", 1 ], 978 | "disabled" : 0, 979 | "hidden" : 0, 980 | "source" : [ "obj-25", 0 ] 981 | } 982 | 983 | } 984 | , { 985 | "patchline" : { 986 | "destination" : [ "obj-18", 0 ], 987 | "disabled" : 0, 988 | "hidden" : 0, 989 | "source" : [ "obj-26", 0 ] 990 | } 991 | 992 | } 993 | , { 994 | "patchline" : { 995 | "destination" : [ "obj-9", 0 ], 996 | "disabled" : 0, 997 | "hidden" : 0, 998 | "source" : [ "obj-27", 0 ] 999 | } 1000 | 1001 | } 1002 | , { 1003 | "patchline" : { 1004 | "destination" : [ "obj-38", 0 ], 1005 | "disabled" : 0, 1006 | "hidden" : 0, 1007 | "source" : [ "obj-28", 0 ] 1008 | } 1009 | 1010 | } 1011 | , { 1012 | "patchline" : { 1013 | "destination" : [ "obj-28", 0 ], 1014 | "disabled" : 0, 1015 | "hidden" : 0, 1016 | "source" : [ "obj-29", 0 ] 1017 | } 1018 | 1019 | } 1020 | , { 1021 | "patchline" : { 1022 | "destination" : [ "obj-25", 0 ], 1023 | "disabled" : 0, 1024 | "hidden" : 0, 1025 | "source" : [ "obj-30", 0 ] 1026 | } 1027 | 1028 | } 1029 | , { 1030 | "patchline" : { 1031 | "destination" : [ "obj-19", 0 ], 1032 | "disabled" : 0, 1033 | "hidden" : 0, 1034 | "source" : [ "obj-31", 0 ] 1035 | } 1036 | 1037 | } 1038 | , { 1039 | "patchline" : { 1040 | "destination" : [ "obj-25", 0 ], 1041 | "disabled" : 0, 1042 | "hidden" : 0, 1043 | "source" : [ "obj-33", 0 ] 1044 | } 1045 | 1046 | } 1047 | , { 1048 | "patchline" : { 1049 | "destination" : [ "obj-20", 0 ], 1050 | "disabled" : 0, 1051 | "hidden" : 0, 1052 | "source" : [ "obj-34", 0 ] 1053 | } 1054 | 1055 | } 1056 | , { 1057 | "patchline" : { 1058 | "destination" : [ "obj-29", 0 ], 1059 | "disabled" : 0, 1060 | "hidden" : 0, 1061 | "source" : [ "obj-36", 0 ] 1062 | } 1063 | 1064 | } 1065 | , { 1066 | "patchline" : { 1067 | "destination" : [ "obj-1", 0 ], 1068 | "disabled" : 0, 1069 | "hidden" : 0, 1070 | "source" : [ "obj-6", 0 ] 1071 | } 1072 | 1073 | } 1074 | , { 1075 | "patchline" : { 1076 | "destination" : [ "obj-1", 0 ], 1077 | "disabled" : 0, 1078 | "hidden" : 0, 1079 | "source" : [ "obj-9", 0 ] 1080 | } 1081 | 1082 | } 1083 | ] 1084 | } 1085 | , 1086 | "patching_rect" : [ 195.0, 327.0, 237.499985, 20.0 ], 1087 | "saved_object_attributes" : { 1088 | "description" : "", 1089 | "digest" : "", 1090 | "globalpatchername" : "", 1091 | "style" : "", 1092 | "tags" : "" 1093 | } 1094 | , 1095 | "style" : "", 1096 | "text" : "p tcp_client" 1097 | } 1098 | 1099 | } 1100 | , { 1101 | "box" : { 1102 | "id" : "obj-20", 1103 | "maxclass" : "newobj", 1104 | "numinlets" : 1, 1105 | "numoutlets" : 1, 1106 | "outlettype" : [ "int" ], 1107 | "patching_rect" : [ 23.0, 247.0, 22.0, 20.0 ], 1108 | "style" : "", 1109 | "text" : "t 1" 1110 | } 1111 | 1112 | } 1113 | , { 1114 | "box" : { 1115 | "id" : "obj-24", 1116 | "maxclass" : "newobj", 1117 | "numinlets" : 2, 1118 | "numoutlets" : 1, 1119 | "outlettype" : [ "bang" ], 1120 | "patching_rect" : [ 23.0, 275.0, 52.0, 20.0 ], 1121 | "style" : "", 1122 | "text" : "metro 30" 1123 | } 1124 | 1125 | } 1126 | , { 1127 | "box" : { 1128 | "fontname" : "Arial Bold", 1129 | "fontsize" : 10.0, 1130 | "id" : "obj-2", 1131 | "maxclass" : "newobj", 1132 | "numinlets" : 2, 1133 | "numoutlets" : 2, 1134 | "outlettype" : [ "signal", "signal" ], 1135 | "patching_rect" : [ 23.0, 366.0, 53.0, 20.0 ], 1136 | "style" : "", 1137 | "text" : "plugout~" 1138 | } 1139 | 1140 | } 1141 | , { 1142 | "box" : { 1143 | "fontname" : "Arial Bold", 1144 | "fontsize" : 10.0, 1145 | "id" : "obj-1", 1146 | "maxclass" : "newobj", 1147 | "numinlets" : 2, 1148 | "numoutlets" : 2, 1149 | "outlettype" : [ "signal", "signal" ], 1150 | "patching_rect" : [ 23.0, 327.0, 53.0, 20.0 ], 1151 | "style" : "", 1152 | "text" : "plugin~" 1153 | } 1154 | 1155 | } 1156 | ], 1157 | "lines" : [ { 1158 | "patchline" : { 1159 | "destination" : [ "obj-2", 1 ], 1160 | "disabled" : 0, 1161 | "hidden" : 0, 1162 | "source" : [ "obj-1", 1 ] 1163 | } 1164 | 1165 | } 1166 | , { 1167 | "patchline" : { 1168 | "destination" : [ "obj-2", 0 ], 1169 | "disabled" : 0, 1170 | "hidden" : 0, 1171 | "source" : [ "obj-1", 0 ] 1172 | } 1173 | 1174 | } 1175 | , { 1176 | "patchline" : { 1177 | "destination" : [ "obj-8", 2 ], 1178 | "disabled" : 0, 1179 | "hidden" : 0, 1180 | "source" : [ "obj-10", 0 ] 1181 | } 1182 | 1183 | } 1184 | , { 1185 | "patchline" : { 1186 | "destination" : [ "obj-8", 5 ], 1187 | "disabled" : 0, 1188 | "hidden" : 0, 1189 | "source" : [ "obj-11", 0 ] 1190 | } 1191 | 1192 | } 1193 | , { 1194 | "patchline" : { 1195 | "destination" : [ "obj-11", 0 ], 1196 | "disabled" : 0, 1197 | "hidden" : 0, 1198 | "source" : [ "obj-12", 0 ] 1199 | } 1200 | 1201 | } 1202 | , { 1203 | "patchline" : { 1204 | "destination" : [ "obj-8", 3 ], 1205 | "disabled" : 0, 1206 | "hidden" : 0, 1207 | "source" : [ "obj-15", 0 ] 1208 | } 1209 | 1210 | } 1211 | , { 1212 | "patchline" : { 1213 | "destination" : [ "obj-30", 0 ], 1214 | "disabled" : 0, 1215 | "hidden" : 0, 1216 | "source" : [ "obj-19", 0 ] 1217 | } 1218 | 1219 | } 1220 | , { 1221 | "patchline" : { 1222 | "destination" : [ "obj-24", 0 ], 1223 | "disabled" : 0, 1224 | "hidden" : 0, 1225 | "source" : [ "obj-20", 0 ] 1226 | } 1227 | 1228 | } 1229 | , { 1230 | "patchline" : { 1231 | "destination" : [ "obj-8", 0 ], 1232 | "disabled" : 0, 1233 | "hidden" : 0, 1234 | "source" : [ "obj-24", 0 ] 1235 | } 1236 | 1237 | } 1238 | , { 1239 | "patchline" : { 1240 | "destination" : [ "obj-20", 0 ], 1241 | "disabled" : 0, 1242 | "hidden" : 0, 1243 | "source" : [ "obj-27", 0 ] 1244 | } 1245 | 1246 | } 1247 | , { 1248 | "patchline" : { 1249 | "destination" : [ "obj-31", 0 ], 1250 | "disabled" : 0, 1251 | "hidden" : 0, 1252 | "source" : [ "obj-30", 0 ] 1253 | } 1254 | 1255 | } 1256 | , { 1257 | "patchline" : { 1258 | "destination" : [ "obj-4", 0 ], 1259 | "disabled" : 0, 1260 | "hidden" : 0, 1261 | "source" : [ "obj-31", 0 ] 1262 | } 1263 | 1264 | } 1265 | , { 1266 | "patchline" : { 1267 | "destination" : [ "obj-43", 0 ], 1268 | "disabled" : 0, 1269 | "hidden" : 0, 1270 | "source" : [ "obj-33", 0 ] 1271 | } 1272 | 1273 | } 1274 | , { 1275 | "patchline" : { 1276 | "destination" : [ "obj-8", 4 ], 1277 | "disabled" : 0, 1278 | "hidden" : 0, 1279 | "source" : [ "obj-43", 0 ] 1280 | } 1281 | 1282 | } 1283 | , { 1284 | "patchline" : { 1285 | "destination" : [ "obj-12", 0 ], 1286 | "disabled" : 0, 1287 | "hidden" : 0, 1288 | "source" : [ "obj-5", 0 ] 1289 | } 1290 | 1291 | } 1292 | , { 1293 | "patchline" : { 1294 | "destination" : [ "obj-5", 0 ], 1295 | "disabled" : 0, 1296 | "hidden" : 0, 1297 | "source" : [ "obj-6", 0 ] 1298 | } 1299 | 1300 | } 1301 | , { 1302 | "patchline" : { 1303 | "destination" : [ "obj-4", 0 ], 1304 | "disabled" : 0, 1305 | "hidden" : 0, 1306 | "source" : [ "obj-8", 0 ] 1307 | } 1308 | 1309 | } 1310 | , { 1311 | "patchline" : { 1312 | "destination" : [ "obj-8", 1 ], 1313 | "disabled" : 0, 1314 | "hidden" : 0, 1315 | "source" : [ "obj-9", 0 ] 1316 | } 1317 | 1318 | } 1319 | ], 1320 | "parameters" : { 1321 | "obj-15" : [ "live.numbox", "live.numbox", 0 ] 1322 | } 1323 | , 1324 | "dependency_cache" : [ { 1325 | "name" : "TcpClient.mxo", 1326 | "type" : "iLaX" 1327 | } 1328 | ], 1329 | "latency" : 0, 1330 | "project" : { 1331 | "version" : 1, 1332 | "creationdate" : -774200786, 1333 | "modificationdate" : -774200786, 1334 | "viewrect" : [ 0.0, 0.0, 300.0, 500.0 ], 1335 | "autoorganize" : 1, 1336 | "hideprojectwindow" : 1, 1337 | "showdependencies" : 1, 1338 | "autolocalize" : 0, 1339 | "contents" : { 1340 | "patchers" : { 1341 | 1342 | } 1343 | , 1344 | "externals" : { 1345 | 1346 | } 1347 | 1348 | } 1349 | , 1350 | "layout" : { 1351 | 1352 | } 1353 | , 1354 | "searchpath" : { 1355 | 1356 | } 1357 | , 1358 | "detailsvisible" : 0, 1359 | "amxdtype" : 1633771873, 1360 | "readonly" : 0 1361 | } 1362 | , 1363 | "embedsnapshot" : 0 1364 | } 1365 | 1366 | } 1367 | -------------------------------------------------------------------------------- /m4l/amxd/to_cinder.amxd: -------------------------------------------------------------------------------- 1 | ampfaaaametaptch){ 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 7, 6 | "minor" : 0, 7 | "revision" : 3, 8 | "architecture" : "x86", 9 | "modernui" : 1 10 | } 11 | , 12 | "rect" : [ 834.0, 153.0, 407.0, 508.0 ], 13 | "openrect" : [ 0.0, 0.0, 0.0, 169.0 ], 14 | "bglocked" : 0, 15 | "openinpresentation" : 1, 16 | "default_fontsize" : 10.0, 17 | "default_fontface" : 0, 18 | "default_fontname" : "Arial Bold", 19 | "gridonopen" : 1, 20 | "gridsize" : [ 8.0, 8.0 ], 21 | "gridsnaponopen" : 1, 22 | "objectsnaponopen" : 1, 23 | "statusbarvisible" : 2, 24 | "toolbarvisible" : 1, 25 | "lefttoolbarpinned" : 0, 26 | "toptoolbarpinned" : 0, 27 | "righttoolbarpinned" : 0, 28 | "bottomtoolbarpinned" : 0, 29 | "toolbars_unpinned_last_save" : 0, 30 | "tallnewobj" : 0, 31 | "boxanimatetime" : 500, 32 | "enablehscroll" : 1, 33 | "enablevscroll" : 1, 34 | "devicewidth" : 0.0, 35 | "description" : "", 36 | "digest" : "", 37 | "tags" : "", 38 | "style" : "", 39 | "subpatcher_template" : "", 40 | "boxes" : [ { 41 | "box" : { 42 | "id" : "obj-7", 43 | "maxclass" : "newobj", 44 | "numinlets" : 1, 45 | "numoutlets" : 3, 46 | "outlettype" : [ "bang", "int", "int" ], 47 | "patching_rect" : [ 19.5, 202.0, 79.0, 20.0 ], 48 | "style" : "", 49 | "text" : "live.thisdevice" 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "id" : "obj-20", 56 | "maxclass" : "message", 57 | "numinlets" : 2, 58 | "numoutlets" : 1, 59 | "outlettype" : [ "" ], 60 | "patching_rect" : [ 146.0, 383.0, 66.0, 20.0 ], 61 | "style" : "", 62 | "text" : "pair_videos" 63 | } 64 | 65 | } 66 | , { 67 | "box" : { 68 | "id" : "obj-18", 69 | "maxclass" : "newobj", 70 | "numinlets" : 1, 71 | "numoutlets" : 1, 72 | "outlettype" : [ "" ], 73 | "patching_rect" : [ 146.0, 418.0, 99.0, 20.0 ], 74 | "style" : "", 75 | "text" : "prepend set_mode" 76 | } 77 | 78 | } 79 | , { 80 | "box" : { 81 | "id" : "obj-9", 82 | "maxclass" : "newobj", 83 | "numinlets" : 1, 84 | "numoutlets" : 2, 85 | "outlettype" : [ "bang", "compile" ], 86 | "patching_rect" : [ 72.0, 293.0, 63.0, 20.0 ], 87 | "style" : "", 88 | "text" : "t b compile" 89 | } 90 | 91 | } 92 | , { 93 | "box" : { 94 | "id" : "obj-13", 95 | "linecount" : 3, 96 | "maxclass" : "message", 97 | "numinlets" : 2, 98 | "numoutlets" : 1, 99 | "outlettype" : [ "" ], 100 | "patching_rect" : [ 224.5, 546.0, 51.0, 42.0 ], 101 | "presentation" : 1, 102 | "presentation_linecount" : 3, 103 | "presentation_rect" : [ 6.0, 84.0, 51.0, 42.0 ], 104 | "style" : "", 105 | "text" : "fire_pair mask_0 rgb_1" 106 | } 107 | 108 | } 109 | , { 110 | "box" : { 111 | "id" : "obj-17", 112 | "linecount" : 3, 113 | "maxclass" : "comment", 114 | "numinlets" : 1, 115 | "numoutlets" : 0, 116 | "patching_rect" : [ 106.5, 202.0, 54.0, 40.0 ], 117 | "presentation" : 1, 118 | "presentation_linecount" : 3, 119 | "presentation_rect" : [ 12.0, 6.0, 49.0, 40.0 ], 120 | "style" : "", 121 | "text" : "reload cue points" 122 | } 123 | 124 | } 125 | , { 126 | "box" : { 127 | "id" : "obj-10", 128 | "maxclass" : "live.button", 129 | "numinlets" : 1, 130 | "numoutlets" : 1, 131 | "outlettype" : [ "" ], 132 | "parameter_enable" : 1, 133 | "patching_rect" : [ 128.0, 255.0, 15.0, 15.0 ], 134 | "presentation" : 1, 135 | "presentation_rect" : [ 23.5, 55.0, 15.0, 15.0 ], 136 | "saved_attribute_attributes" : { 137 | "valueof" : { 138 | "parameter_longname" : "live.button", 139 | "parameter_shortname" : "live.button", 140 | "parameter_type" : 2, 141 | "parameter_mmax" : 1.0, 142 | "parameter_enum" : [ "off", "on" ] 143 | } 144 | 145 | } 146 | , 147 | "varname" : "live.button" 148 | } 149 | 150 | } 151 | , { 152 | "box" : { 153 | "id" : "obj-8", 154 | "maxclass" : "newobj", 155 | "numinlets" : 1, 156 | "numoutlets" : 1, 157 | "outlettype" : [ "" ], 158 | "patching_rect" : [ 279.0, 403.0, 90.0, 20.0 ], 159 | "style" : "", 160 | "text" : "prepend time_ev" 161 | } 162 | 163 | } 164 | , { 165 | "box" : { 166 | "id" : "obj-6", 167 | "maxclass" : "newobj", 168 | "numinlets" : 1, 169 | "numoutlets" : 1, 170 | "outlettype" : [ "" ], 171 | "patching_rect" : [ 116.0, 479.0, 74.0, 20.0 ], 172 | "saved_object_attributes" : { 173 | "filename" : "cue_points", 174 | "parameter_enable" : 0 175 | } 176 | , 177 | "style" : "", 178 | "text" : "js cue_points" 179 | } 180 | 181 | } 182 | , { 183 | "box" : { 184 | "id" : "obj-5", 185 | "maxclass" : "newobj", 186 | "numinlets" : 0, 187 | "numoutlets" : 1, 188 | "outlettype" : [ "" ], 189 | "patching_rect" : [ 279.0, 373.0, 54.0, 20.0 ], 190 | "style" : "", 191 | "text" : "r time_ev" 192 | } 193 | 194 | } 195 | , { 196 | "box" : { 197 | "id" : "obj-16", 198 | "maxclass" : "button", 199 | "numinlets" : 1, 200 | "numoutlets" : 1, 201 | "outlettype" : [ "bang" ], 202 | "patching_rect" : [ 191.5, 210.0, 24.0, 24.0 ], 203 | "style" : "" 204 | } 205 | 206 | } 207 | , { 208 | "box" : { 209 | "id" : "obj-14", 210 | "maxclass" : "message", 211 | "numinlets" : 2, 212 | "numoutlets" : 1, 213 | "outlettype" : [ "" ], 214 | "patching_rect" : [ 303.5, 210.0, 29.5, 20.0 ], 215 | "style" : "", 216 | "text" : "rgb" 217 | } 218 | 219 | } 220 | , { 221 | "box" : { 222 | "id" : "obj-12", 223 | "maxclass" : "newobj", 224 | "numinlets" : 3, 225 | "numoutlets" : 1, 226 | "outlettype" : [ "" ], 227 | "patching_rect" : [ 191.5, 250.0, 131.0, 20.0 ], 228 | "style" : "", 229 | "text" : "pack fire_video i s" 230 | } 231 | 232 | } 233 | , { 234 | "box" : { 235 | "id" : "obj-11", 236 | "maxclass" : "number", 237 | "numinlets" : 1, 238 | "numoutlets" : 2, 239 | "outlettype" : [ "", "bang" ], 240 | "parameter_enable" : 0, 241 | "patching_rect" : [ 235.5, 210.0, 50.0, 20.0 ], 242 | "style" : "" 243 | } 244 | 245 | } 246 | , { 247 | "box" : { 248 | "id" : "obj-4", 249 | "maxclass" : "newobj", 250 | "numinlets" : 1, 251 | "numoutlets" : 1, 252 | "outlettype" : [ "compile" ], 253 | "patching_rect" : [ 22.0, 255.0, 54.0, 20.0 ], 254 | "style" : "", 255 | "text" : "t compile" 256 | } 257 | 258 | } 259 | , { 260 | "box" : { 261 | "id" : "obj-3", 262 | "maxclass" : "newobj", 263 | "numinlets" : 1, 264 | "numoutlets" : 1, 265 | "outlettype" : [ "" ], 266 | "patching_rect" : [ 31.5, 550.0, 67.0, 20.0 ], 267 | "saved_object_attributes" : { 268 | "filename" : "to_cinder.js", 269 | "parameter_enable" : 0 270 | } 271 | , 272 | "style" : "", 273 | "text" : "js to_cinder" 274 | } 275 | 276 | } 277 | , { 278 | "box" : { 279 | "fontname" : "Arial Bold", 280 | "fontsize" : 10.0, 281 | "id" : "obj-2", 282 | "maxclass" : "newobj", 283 | "numinlets" : 2, 284 | "numoutlets" : 2, 285 | "outlettype" : [ "signal", "signal" ], 286 | "patching_rect" : [ 303.5, 505.0, 53.0, 20.0 ], 287 | "style" : "", 288 | "text" : "plugout~" 289 | } 290 | 291 | } 292 | , { 293 | "box" : { 294 | "fontname" : "Arial Bold", 295 | "fontsize" : 10.0, 296 | "id" : "obj-1", 297 | "maxclass" : "newobj", 298 | "numinlets" : 2, 299 | "numoutlets" : 2, 300 | "outlettype" : [ "signal", "signal" ], 301 | "patching_rect" : [ 303.5, 472.0, 53.0, 20.0 ], 302 | "style" : "", 303 | "text" : "plugin~" 304 | } 305 | 306 | } 307 | ], 308 | "lines" : [ { 309 | "patchline" : { 310 | "destination" : [ "obj-2", 1 ], 311 | "disabled" : 0, 312 | "hidden" : 0, 313 | "source" : [ "obj-1", 1 ] 314 | } 315 | 316 | } 317 | , { 318 | "patchline" : { 319 | "destination" : [ "obj-2", 0 ], 320 | "disabled" : 0, 321 | "hidden" : 0, 322 | "source" : [ "obj-1", 0 ] 323 | } 324 | 325 | } 326 | , { 327 | "patchline" : { 328 | "destination" : [ "obj-9", 0 ], 329 | "disabled" : 0, 330 | "hidden" : 0, 331 | "source" : [ "obj-10", 0 ] 332 | } 333 | 334 | } 335 | , { 336 | "patchline" : { 337 | "destination" : [ "obj-12", 1 ], 338 | "disabled" : 0, 339 | "hidden" : 0, 340 | "source" : [ "obj-11", 0 ] 341 | } 342 | 343 | } 344 | , { 345 | "patchline" : { 346 | "destination" : [ "obj-3", 0 ], 347 | "disabled" : 0, 348 | "hidden" : 0, 349 | "source" : [ "obj-12", 0 ] 350 | } 351 | 352 | } 353 | , { 354 | "patchline" : { 355 | "destination" : [ "obj-12", 2 ], 356 | "disabled" : 0, 357 | "hidden" : 0, 358 | "source" : [ "obj-14", 0 ] 359 | } 360 | 361 | } 362 | , { 363 | "patchline" : { 364 | "destination" : [ "obj-12", 0 ], 365 | "disabled" : 0, 366 | "hidden" : 0, 367 | "source" : [ "obj-16", 0 ] 368 | } 369 | 370 | } 371 | , { 372 | "patchline" : { 373 | "destination" : [ "obj-6", 0 ], 374 | "disabled" : 0, 375 | "hidden" : 0, 376 | "source" : [ "obj-18", 0 ] 377 | } 378 | 379 | } 380 | , { 381 | "patchline" : { 382 | "destination" : [ "obj-18", 0 ], 383 | "disabled" : 0, 384 | "hidden" : 0, 385 | "source" : [ "obj-20", 0 ] 386 | } 387 | 388 | } 389 | , { 390 | "patchline" : { 391 | "destination" : [ "obj-3", 0 ], 392 | "disabled" : 0, 393 | "hidden" : 0, 394 | "source" : [ "obj-4", 0 ] 395 | } 396 | 397 | } 398 | , { 399 | "patchline" : { 400 | "destination" : [ "obj-6", 0 ], 401 | "disabled" : 0, 402 | "hidden" : 0, 403 | "source" : [ "obj-4", 0 ] 404 | } 405 | 406 | } 407 | , { 408 | "patchline" : { 409 | "destination" : [ "obj-8", 0 ], 410 | "disabled" : 0, 411 | "hidden" : 0, 412 | "source" : [ "obj-5", 0 ] 413 | } 414 | 415 | } 416 | , { 417 | "patchline" : { 418 | "destination" : [ "obj-13", 1 ], 419 | "disabled" : 0, 420 | "hidden" : 0, 421 | "source" : [ "obj-6", 0 ] 422 | } 423 | 424 | } 425 | , { 426 | "patchline" : { 427 | "destination" : [ "obj-3", 0 ], 428 | "disabled" : 0, 429 | "hidden" : 0, 430 | "source" : [ "obj-6", 0 ] 431 | } 432 | 433 | } 434 | , { 435 | "patchline" : { 436 | "destination" : [ "obj-4", 0 ], 437 | "disabled" : 0, 438 | "hidden" : 0, 439 | "source" : [ "obj-7", 0 ] 440 | } 441 | 442 | } 443 | , { 444 | "patchline" : { 445 | "destination" : [ "obj-6", 0 ], 446 | "disabled" : 0, 447 | "hidden" : 0, 448 | "source" : [ "obj-8", 0 ] 449 | } 450 | 451 | } 452 | , { 453 | "patchline" : { 454 | "destination" : [ "obj-20", 0 ], 455 | "disabled" : 0, 456 | "hidden" : 0, 457 | "source" : [ "obj-9", 0 ] 458 | } 459 | 460 | } 461 | , { 462 | "patchline" : { 463 | "destination" : [ "obj-3", 0 ], 464 | "disabled" : 0, 465 | "hidden" : 0, 466 | "source" : [ "obj-9", 1 ] 467 | } 468 | 469 | } 470 | , { 471 | "patchline" : { 472 | "destination" : [ "obj-6", 0 ], 473 | "disabled" : 0, 474 | "hidden" : 0, 475 | "source" : [ "obj-9", 1 ] 476 | } 477 | 478 | } 479 | ], 480 | "parameters" : { 481 | "obj-10" : [ "live.button", "live.button", 0 ] 482 | } 483 | , 484 | "dependency_cache" : [ { 485 | "name" : "to_cinder.js", 486 | "bootpath" : "~/Music/Ableton/User Library/Presets/Audio Effects/Max Audio Effect/m4l_js2liveAPI/m4l", 487 | "type" : "TEXT", 488 | "implicit" : 1 489 | } 490 | , { 491 | "name" : "cue_points.js", 492 | "bootpath" : "~/Music/Ableton/User Library/Presets/Audio Effects/Max Audio Effect/m4l_js2liveAPI/m4l", 493 | "type" : "TEXT", 494 | "implicit" : 1 495 | } 496 | ], 497 | "latency" : 0, 498 | "project" : { 499 | "version" : 1, 500 | "creationdate" : -773646193, 501 | "modificationdate" : -773646193, 502 | "viewrect" : [ 0.0, 0.0, 300.0, 500.0 ], 503 | "autoorganize" : 1, 504 | "hideprojectwindow" : 1, 505 | "showdependencies" : 1, 506 | "autolocalize" : 0, 507 | "contents" : { 508 | "patchers" : { 509 | 510 | } 511 | , 512 | "code" : { 513 | 514 | } 515 | 516 | } 517 | , 518 | "layout" : { 519 | 520 | } 521 | , 522 | "searchpath" : { 523 | 524 | } 525 | , 526 | "detailsvisible" : 0, 527 | "amxdtype" : 1633771873, 528 | "readonly" : 0 529 | } 530 | , 531 | "embedsnapshot" : 0 532 | } 533 | 534 | } 535 | -------------------------------------------------------------------------------- /m4l/amxd/transport.amxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blm81/m4l_js2liveAPI/a4b615280416ef6926ba4d523710878d0d014c98/m4l/amxd/transport.amxd -------------------------------------------------------------------------------- /m4l/js/clip_listener.js: -------------------------------------------------------------------------------- 1 | /* 2 | listen for clips being triggered 3 | */ 4 | 5 | inlets = 1; 6 | outlets = 2; 7 | 8 | var trackObserver = new LiveAPI( clipTriggerListener, "this_device canonical_parent" ); 9 | trackObserver.property = "playing_slot_index"; 10 | 11 | function clipTriggerListener( args ) 12 | { 13 | /** output object : 14 | type = String 15 | data object : event = String 16 | name : live track name 17 | slotNum : num, number of playing slot 18 | */ 19 | var objOut = { 20 | type : "clip_event", 21 | data : {} 22 | }, 23 | argArr = arrayfromargs( args ); 24 | 25 | //index 1 is the track number 26 | switch( argArr[1] ) { 27 | 28 | //-2 for clip off 29 | case -2: 30 | post( "clip off" + '\n' ); 31 | objOut.data.event = "clip_off"; 32 | objOut.data.name = trackObserver.get( "name" )[0]; 33 | outlet( 1, "bang" ); 34 | break; 35 | default: 36 | post( "clip on: " + argArr[1] + '\n' ); 37 | objOut.data.event = "clip_on"; 38 | objOut.data.name = trackObserver.get( "name" )[0]; 39 | objOut.data.slotNum = argArr[1]; 40 | outlet( 0, argArr[1] ); 41 | break; 42 | } 43 | //receiver name : clip event 44 | messnamed( 'clip_event', JSON.stringify( objOut )); 45 | } -------------------------------------------------------------------------------- /m4l/js/clip_trigger.js: -------------------------------------------------------------------------------- 1 | /* 2 | trigger clips 3 | */ 4 | 5 | inlets = 1; 6 | outlets = 1; 7 | 8 | var live_api = new LiveAPI( "live_set" ), 9 | //random_clip = GM4L.RandomFire( live_api, [ 2, 5, 6 ], [ 11 ] ); 10 | random_clips = [], 11 | clipNames = {}; //TODO think of a better way to track duplicates here 12 | 13 | function anything() 14 | { 15 | var args = arrayfromargs( messagename, arguments ), 16 | str_from_global = "", 17 | event_obj = null; 18 | 19 | switch ( args[0] ) { 20 | case 'event': 21 | try { 22 | event_obj = JSON.parse( args[1] ); 23 | } 24 | catch ( exception ) { 25 | post( "JSON parse exception: ", exception, '\n' ); 26 | return; 27 | } 28 | switch( event_obj.type ) { 29 | //time (meter) based events 30 | case 'time_ev': 31 | trigger_clip( event_obj.data ); 32 | break; //time_ev 33 | } 34 | break; //time_ev 35 | //get an object with track/clip info about live set 36 | case 'get_song_info': 37 | get_song_info(); 38 | break; //get_song_info 39 | 40 | case 'json': 41 | handle_json( args[1] ); 42 | break; //json 43 | } 44 | } 45 | 46 | function get_song_info() 47 | { 48 | var str_from_global = GM4L.get_song_info( live_api ), 49 | song_info; 50 | 51 | try { 52 | song_info = JSON.parse( str_from_global ); 53 | } 54 | catch( exception ) { 55 | post( "JSON parse exception: ", exception, '\n' ); 56 | } 57 | 58 | //print out object contents 59 | for ( var i = 0, il = song_info.tracks.length; i < il; i++ ) { 60 | post( "track ", song_info.tracks[i].index, " ", song_info.tracks[i].name, '\n' ); 61 | for ( var j = 0, jl = song_info.tracks[i].clips.length; j < jl; j++ ) { 62 | post( "clip ", song_info.tracks[i].clips[j].index, " ", song_info.tracks[i].clips[j].name, '\n' ); 63 | } 64 | } 65 | } 66 | 67 | function handle_json( json_in ) 68 | { 69 | var obj_in = null; 70 | 71 | try { 72 | obj_in = JSON.parse( json_in ); 73 | } 74 | catch( exception ) { 75 | post( "JSON handler exception: ", exception, '\n' ); 76 | } 77 | if ( obj_in === null ) 78 | return; 79 | else { 80 | switch( obj_in.type ) { 81 | case 'trigger': 82 | add_trigger( obj_in.data ); 83 | break; //trigger 84 | } 85 | } 86 | } 87 | 88 | /* 89 | takes an array of trigger objects: see sample_trigger_config 90 | */ 91 | function add_trigger( arr_in ) 92 | { 93 | var i, il, 94 | random_clip = null; 95 | 96 | for ( i = 0, il = arr_in.length; i < il; i++ ) { 97 | try { 98 | //create random fire object 99 | if (clipNames[arr_in[i].name]) { 100 | return; 101 | } 102 | if ( arr_in[i].type === 'random_fire' ) { 103 | clipNames[arr_in[i].name] = true; 104 | random_clip = GM4L.RandomFire( 105 | live_api, 106 | arr_in[i].data.trigger, 107 | arr_in[i].data.tracks, 108 | arr_in[i].data.tick_range 109 | ); 110 | //optional parameter for output range: don't use for random output 111 | if ( arr_in[i].data.output_range !== undefined ) 112 | random_clip.output_range = arr_in[i].data.output_range 113 | random_clips.push( random_clip ); 114 | } 115 | } 116 | catch ( exception ) { 117 | post( "add trigger exception: ", exception, '\n' ); 118 | } 119 | } 120 | } 121 | 122 | //update RandomFire objects if they match current event cue 123 | function trigger_clip( str_cue ) 124 | { 125 | for ( var i = 0, il = random_clips.length; i < il; i++ ) { 126 | if ( random_clips[i].get_trigger() === str_cue ) { 127 | random_clips[i].update(); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /m4l/js/config/cp_event.txt: -------------------------------------------------------------------------------- 1 | { 2 | "type" : "config", 3 | "data" : 4 | [ 5 | { 6 | "type" : "beat_callback", 7 | "data" : "function() { 8 | messnamed( 'time_ev', '{ \"type\" : \"time_ev\", \"data\" : \"beat\" }' ); 9 | }" 10 | }, 11 | { 12 | "type" : "bar_callback", 13 | "data" : "function() { 14 | messnamed( 'time_ev', '{ \"type\" : \"time_ev\", \"data\" : \"bar\" }' ); 15 | }" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /m4l/js/config/cp_trigger.txt: -------------------------------------------------------------------------------- 1 | { 2 | "type" : "trigger", 3 | "data" : 4 | [ 5 | { 6 | "type" : "random_fire", 7 | "data" : { 8 | "trigger" : "beat", 9 | "tracks" : [ 2, 5, 6 ], 10 | "tick_range" : [ 11 ] 11 | } 12 | }, 13 | { 14 | "type" : "random_fire", 15 | "data" : { 16 | "trigger" : "bar", 17 | "tracks" : [ 3, 4 ], 18 | "tick_range" : [ 2 ] 19 | } 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /m4l/js/config/sample_event_config.txt: -------------------------------------------------------------------------------- 1 | //Sample configuration for config_loader.js 2 | //any of the _global_ max methods are fair game here 3 | //use everything below this line as a template 4 | { 5 | "type" : "config", 6 | "data" : 7 | [ 8 | { 9 | "type" : "beat_callback", 10 | "data" : "function() { 11 | post( 'beat callback', '\\n' ); 12 | messnamed( 'receive_object', 'beat changed' ); 13 | }" 14 | }, 15 | { 16 | "type" : "bar_callback", 17 | "data" : "function() { 18 | post( 'bar callback', '\\n' ); 19 | messnamed( 'receive_object', 'bar changed' ); 20 | }" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /m4l/js/config/sample_trigger_config.txt: -------------------------------------------------------------------------------- 1 | /* 2 | sample configuration for trigger events: an array of trigger objects 3 | type : "random_fire", data: 4 | @param trigger {string} cue to trigger clip update 5 | @param track_num: {array} track number(s), if multiple, will choose random track 6 | @param tick_range: {array} low [0] and high [1] range for fire time 7 | if only 1 arg, then clip will fire at that interval 8 | @param out_range: {array} optional *breaks random track* output range low [0] high [1] 9 | */ 10 | 11 | { 12 | "type" : "trigger", 13 | "data" : 14 | [ 15 | { 16 | "type" : "random_fire", 17 | "data" : { 18 | "trigger" : "beat", 19 | "tracks" : [ 1, 2, 3, 5, 7 ], 20 | "tick_range" : [ 4, 8 ], 21 | "output_range" : [ 0, 5 ] 22 | } 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /m4l/js/config_loader.js: -------------------------------------------------------------------------------- 1 | /* 2 | load JSON configuration text (.txt) file 3 | */ 4 | 5 | inlets = 1; 6 | outlets = 1; 7 | 8 | //load external text file (with .txt extension) 9 | function load_file( file_path ) 10 | { 11 | var ret_val = ""; 12 | 13 | //max-specific variables 14 | filename = file_path; 15 | access = "readwrite"; 16 | typelist = new Array("iLaF" , "maxb" , "TEXT" ); 17 | 18 | //loop through file and add contents to return string 19 | file = new File( filename, access, typelist ); 20 | 21 | while( file.isopen && file.position < file.eof ){ 22 | ret_val += file.readline().trim(); //trim whitespace and special chars 23 | } 24 | 25 | file.close(); 26 | 27 | return ret_val; 28 | } 29 | 30 | function anything() 31 | { 32 | var args = arrayfromargs( messagename, arguments ); 33 | 34 | switch( args[0] ) { 35 | 36 | //output json from config file 37 | case 'read': 38 | 39 | //optional third argument to route output 40 | if ( args[2] !== undefined ) 41 | outlet( 0, args[2], load_file( args[1] ) ); 42 | else 43 | outlet( 0, load_file( args[1] ) ); 44 | break; 45 | } 46 | } -------------------------------------------------------------------------------- /m4l/js/cue_points.js: -------------------------------------------------------------------------------- 1 | /* 2 | observe and get info on cue points 3 | */ 4 | 5 | inlets = 1; 6 | outlets = 1; 7 | autowatch = 1; 8 | 9 | var api_track = new LiveAPI( get_cuepoint_info ), //track observer for cuepoints 10 | api_clip = new LiveAPI(), //for getting info on clips 11 | api_time = new LiveAPI( "live_set" ), //for getting current time in beats 12 | cue_points, //array of cue objects 13 | mode = null; //specify output mode 14 | 15 | //set to observe cue points in track 16 | api_track.path = "live_set"; 17 | api_track.property = "cue_points"; 18 | 19 | function get_cuepoint_info( args ) { 20 | 21 | var arg_arr = arrayfromargs( args ), //id's of cue points 22 | arg_len, //the actual number of clips 23 | cue; //object to contain cue info 24 | 25 | if ( arg_arr[0] === "cue_points" ) { 26 | 27 | cue_points = []; 28 | arg_len = ( arg_arr.length - 1 ) / 2; //subtract one because the 1st index is always "cue points" 29 | 30 | for ( var i = 0; i < arg_len; i++ ) { 31 | cue = {}; 32 | api_clip.goto( "live_set cue_points " + i ); 33 | cue.name = api_clip.get( "name" ); //TO DO: figure out why name is "1" when cue point added 34 | cue.time = api_clip.get( "time" ); 35 | cue_points.push( cue ); 36 | post( "cue: ", cue.name, " ", cue.time, '\n' ); 37 | } 38 | } 39 | } 40 | 41 | function anything() 42 | { 43 | var args = arrayfromargs( messagename, arguments ), 44 | obj_in, 45 | song_time, 46 | output; 47 | 48 | switch( args[0] ) { 49 | 50 | case 'set_mode': 51 | 52 | mode = args[1]; 53 | post( "mode is: ", mode, '\n' ); 54 | 55 | break; //set_mode 56 | 57 | case 'time_ev': 58 | 59 | try { 60 | obj_in = JSON.parse( args[1] ) 61 | } 62 | catch( exception ) { post( "JSON parse error: ", exception, '\n' ); } 63 | 64 | if ( obj_in.data === "beat" ) { 65 | 66 | //get song time in beats 67 | song_time = Math.round( api_time.get( "current_song_time" ) ); 68 | 69 | //compare to cue points, if match, then send fire message to server 70 | for ( var i = 0, il = cue_points.length; i < il; i++ ) { 71 | if( song_time === +cue_points[i].time ) { 72 | if( mode !== null ) { 73 | switch( mode ) { 74 | case 'single_video': 75 | fire_videos( cue_points[i], "fire_video" ); 76 | break; //single_video 77 | 78 | case 'pair_videos': 79 | fire_videos( cue_points[i], "fire_pair" ); 80 | break; //pair videos 81 | default: 82 | post( "the cue point event mode set is not valid", '\n' ); 83 | break; 84 | } 85 | } 86 | else 87 | post( "cue point event output mode is not set", '\n' ); 88 | } 89 | } 90 | } 91 | 92 | break; //time_ev 93 | } 94 | } 95 | 96 | function fire_videos( cue_point, mode_id ) { 97 | var name_str = cue_point.name.toString(); 98 | output = name_str.split( " " ); 99 | outlet( 0, mode_id, output[0], output[1] ); 100 | } -------------------------------------------------------------------------------- /m4l/js/folder_traversal.js: -------------------------------------------------------------------------------- 1 | /* 2 | traverse files in a folder (right now just supports AIFF), 3 | output JSON with array of filenames 4 | */ 5 | 6 | inlets = 1; 7 | outlets = 1; 8 | 9 | var folder, 10 | objOut = {}; 11 | 12 | function anything() 13 | { 14 | var a = arrayfromargs( messagename, arguments ); 15 | 16 | switch( a[0] ) { 17 | 18 | case "set_folder": 19 | post( "opening folder: " + a[1] + '\n' ); 20 | folder = new Folder( a[1] ); 21 | folder.typelist = [ "AIFF" ]; 22 | objOut.filenames = []; 23 | 24 | while ( !folder.end ) { 25 | //filter out empty string 26 | //TODO figure out why this is happening 27 | if ( folder.filename !== "" ) { 28 | objOut.filenames.push( folder.filename ); 29 | } 30 | folder.next(); 31 | } 32 | 33 | outlet( 0, "ft_json", JSON.stringify( objOut )); 34 | 35 | break; 36 | 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /m4l/js/global_m4l.js: -------------------------------------------------------------------------------- 1 | 2 | /* global javascript classes for max for live by Blake McConnell 2013-15 3 | can be acessed from anywhere in your live set 4 | make sure you send a "compile" message to this file, 5 | then to all other js objects to initialize them within live. 6 | drunk walk function makes use of banksean's implementation of Perlin 7 | Simplex noise: https://gist.github.com/banksean/304522. 8 | */ 9 | 10 | GM4L = new Global("m4l"); 11 | autowatch = 1; 12 | post("global m4l is loaded"); 13 | 14 | GM4L.GetDateTime = function() { 15 | var today = new Date(); 16 | var date = today.getFullYear() + "-" + (today.getMonth()+1) + "-" + today.getDate(); 17 | var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); 18 | return dateTime = date + "::" + time; 19 | } 20 | 21 | GM4L.LogToFile = function( msgStr ) 22 | { 23 | messnamed("console", GM4L.GetDateTime() + ": " + msgStr + "\n"); 24 | } 25 | 26 | //performs a drunk walk, arguments are min and max of output 27 | GM4L.Drunk = function( min_out, max_out ) { 28 | this.prev_val = ( min_out + max_out ) / 2; 29 | this.min_out = min_out; 30 | this.max_out = max_out; 31 | this.sim_noise = new gp.SimplexNoise(); 32 | } 33 | //arguments set max and min step size 34 | GM4L.Drunk.prototype.step = function( min_step, max_step ) { 35 | var current_val, 36 | today = new Date(), 37 | today_ms = today.getTime(), 38 | noise = this.sim_noise.noise( today_ms, today_ms ), 39 | rand_val = noise * ( max_step - min_step ) + min_step, 40 | sign = noise && noise / Math.abs( noise ); //TODO move this to its own function 41 | rand_val = rand_val * sign; //give random val the sign of the seed 42 | 43 | //keep values from getting stuck at the edges of range 44 | if ( rand_val + this.prev_val < this.min_out || rand_val + this.prev_val > this.max_out ) 45 | rand_val = rand_val * -1; 46 | current_val = rand_val + this.prev_val; 47 | 48 | //make sure value does not exceed bounds of range 49 | if ( current_val < this.min_out ) 50 | current_val = this.min_out; 51 | else if ( current_val > this.max_out ) 52 | current_val = this.max_out; 53 | 54 | this.prev_val = current_val; //keep track of previous value 55 | return current_val; 56 | } 57 | 58 | GM4L.Drunk.prototype.setMinOut = function( minOut ) 59 | { 60 | this.min_out = minOut; 61 | } 62 | 63 | GM4L.Drunk.prototype.setMaxOut = function( maxOut ) 64 | { 65 | this.max_out = maxOut; 66 | } 67 | 68 | //implementation of common easing functions 69 | GM4L.Easing = function( total_time, rate, start_val, end_val ) { 70 | this.total_time = total_time; 71 | this.rate = rate; //rate of bangs sent to js object 72 | this.duration = Math.floor(total_time/rate); 73 | this.counter = (total_time/rate) + 1; 74 | this.last_map_val = 0; 75 | this.start_val = start_val; 76 | this.end_val = end_val; 77 | } 78 | 79 | GM4L.Easing.prototype.start = function() { 80 | this.counter = 0; 81 | } 82 | 83 | //arguments: easing_function(counter/duration, start_val, end_val), end val 84 | GM4L.Easing.prototype.move = function( easing_function ) { 85 | var mapped_value; 86 | if (this.counter < this.duration) { 87 | mapped_value = easing_function( this.counter / this.duration, this.start_val, this.end_val ); 88 | this.counter ++; 89 | } 90 | else if (this.counter == this.duration) { 91 | mapped_value = this.end_val; 92 | this.last_map_val = mapped_value; 93 | } 94 | else { 95 | mapped_value = this.last_map_val; 96 | } 97 | return mapped_value; 98 | } 99 | 100 | GM4L.Easing.prototype.set_rate = function(new_rate) { 101 | this.rate = new_rate; 102 | this.duration = this.total_time/this.rate; 103 | this.counter = (this.total_time/this.rate) + 1; 104 | } 105 | 106 | GM4L.Easing.prototype.linear = function( t, v1, v2 ) { 107 | return v1 + t * (v2 - v1); 108 | } 109 | 110 | GM4L.Easing.prototype.easeIn = function( t, v1, v2 ) { 111 | return v1 + (t * t * t) * (v2 - v1); 112 | } 113 | 114 | GM4L.Easing.prototype.easeOut = function( t, v1, v2 ) { 115 | return v1 + (((t-1) * (t-1) * (t-1)) + 1) * (v2 - v1); 116 | } 117 | 118 | GM4L.Easing.prototype.easeInOut = function( t, v1, v2 ) { 119 | if ((t * 2) < 1) { 120 | return v1 + ((t * 2) * (t * 2) * (t * 2)) * (v2 - v1) / 2.0; 121 | } 122 | else { 123 | return v1 + ((t * 2 - 2) * (t * 2 - 2) * (t * 2 - 2) + 2) * (v2 - v1) / 2.0; 124 | } 125 | } 126 | 127 | /* get JSON object containing an array of track objects 128 | that each have an array of clip objects */ 129 | GM4L.get_song_info = function( api_object ) { 130 | 131 | var song_info = { 132 | tracks : [] 133 | }; 134 | 135 | //get tracks 136 | api_object.goto( "live_set" ); 137 | var tracks = arrayfromargs( api_object.get( "tracks" ) ); 138 | //loop through half the length as "id" and "number" each have own array index 139 | for ( var i = 0; i < tracks.length / 2; i++ ) { 140 | api_object.goto( "live_set tracks " + i ); 141 | //make track object 142 | var track = { 143 | index : i, 144 | name : api_object.get( "name" )[0], 145 | clips : [] 146 | }; 147 | 148 | //get clips 149 | api_object.goto( "live_set tracks " + i ); 150 | var clips = arrayfromargs( api_object.get( "clip_slots" ) ); 151 | for ( var j =0; j < clips.length / 2; j++ ) { 152 | api_object.goto( "live_set tracks " + i + " clip_slots " + j ); 153 | 154 | //check if clip slot actally has a clip, if so, add 155 | if ( api_object.get( "has_clip" ) == 1 ) { 156 | api_object.goto( "live_set tracks " + i + " clip_slots " + j + " clip" ); 157 | var clip = { 158 | index : j, 159 | name : api_object.get( "name" )[0] 160 | } 161 | track.clips.push( clip ); 162 | } 163 | } 164 | song_info.tracks.push( track ); 165 | } 166 | 167 | return JSON.stringify( song_info ); 168 | } 169 | 170 | //change parameters of live devices 171 | GM4L.ParamChange = function( device ) { 172 | this.devices = device; 173 | this.parameters = null; 174 | this.min = 0; 175 | this.max = 0; 176 | } 177 | //use parameter list to populate umenu, or print names to console 178 | GM4L.ParamChange.prototype.list_params = function(api_object) { //pass name of api object 179 | api_object.goto("this_device canonical_parent devices " + this.devices); 180 | var args = arrayfromargs( api_object.get ( "parameters" ) ); 181 | var output = {}; 182 | //initialize umenu-loading array with "clear" message 183 | output.umenu = [ "clear" ]; 184 | output.id_num = []; 185 | for ( var i = 0; i < args.length; i++ ) { 186 | //since "get" lists ids with commas between "id" and id # 187 | //divide by 2 to get total # of params 188 | if ( i < args.length / 2 ) { 189 | api_object.goto("this_device canonical_parent devices " + this.devices + " parameters " + i); 190 | //get parameter name and prepare it for umenu entry 191 | var param_name = api_object.get( "name" ); 192 | var item = "insert " + i + " " + param_name; 193 | output.umenu.push( item ); 194 | } 195 | //get device's numerical id and push to id number array 196 | if ( i % 2 != 0 ) { 197 | var param_id = {}; 198 | param_id.index = Math.floor( i / 2 ); //match the index in the umenu array 199 | param_id.id = args[i]; 200 | output.id_num.push( param_id ); 201 | } 202 | } 203 | output = JSON.stringify( output ); 204 | return output; 205 | } 206 | 207 | GM4L.ParamChange.prototype.set_devices = function(device_number) { 208 | this.devices = device_number; 209 | } 210 | 211 | GM4L.ParamChange.prototype.set_param = function( api_object, param_number ) { 212 | this.parameters = param_number; 213 | this.set_bounds( api_object ); 214 | } 215 | 216 | //set minimum and maximum value, use for scaling 217 | GM4L.ParamChange.prototype.set_bounds = function( api_object ) { 218 | api_object.goto("this_device canonical_parent devices " + this.devices + " parameters " + this.parameters); 219 | this.min = api_object.get("min"); 220 | this.max = api_object.get("max"); 221 | } 222 | 223 | GM4L.ParamChange.prototype.set_value = function(api_object, value) { 224 | api_object.goto("this_device canonical_parent devices " + this.devices + " parameters " + this.parameters); 225 | api_object.set("value", value); 226 | } 227 | 228 | /* 229 | fire a random clip 230 | 231 | @param api_obj {obj} api instance 232 | @param trigger {string} cue to trigger clip update 233 | @param track_num: {array} track number(s), if multiple, will choose random track 234 | @param tick_range: {array} low [0] and high [1] range for fire time 235 | if only 1 arg, then clip will fire at that interval 236 | @param out_range: {array} optional *breaks random track* output range low [0] high [1] 237 | */ 238 | GM4L.RandomFire = function( api_obj, trigger, tracks, tick_range, output_range ) { 239 | var _counter = 0, 240 | _ticks, 241 | _output, 242 | _trigger = trigger, 243 | _song_info = null; 244 | 245 | set_all(); 246 | 247 | function set_ticks() { 248 | if ( tick_range[1] === undefined ) 249 | _ticks = tick_range[0]; 250 | else 251 | _ticks = random_range( tick_range[0], tick_range[1] ); 252 | post( "ticks set to: ", _ticks ); 253 | } 254 | 255 | function set_track() { 256 | _track = tracks[ random_range( -1, tracks.length ) ]; 257 | post( "track set to: ", _track ); 258 | } 259 | 260 | function set_output() { 261 | _output = random_range( output_range[0], output_range[1] ); 262 | } 263 | 264 | function get_trigger() { return _trigger; } 265 | 266 | function set_all() { 267 | set_ticks(); 268 | set_track(); 269 | 270 | var clips_idx, 271 | str_song_info; 272 | 273 | //if there's an output range specified, choose a random index 274 | if ( output_range !== undefined ) 275 | set_output(); 276 | 277 | //otherwise, get the tracks clips and select a random index from them 278 | else { 279 | 280 | //make sure that the song info has been aquired 281 | if ( _song_info === null ) { 282 | str_song_info = GM4L.get_song_info( api_obj ) 283 | _song_info = JSON.parse( str_song_info ); 284 | } 285 | 286 | //get clips for the current track and set a randomly chosen one as output 287 | for ( var i = 0, il = _song_info.tracks.length; i < il; i++ ) { 288 | if ( _song_info.tracks[i].index === _track ) { 289 | clips_idx = random_range( -1, _song_info.tracks[i].clips.length ); 290 | post( "output track: ", _song_info.tracks[i].clips[ clips_idx ].name, '\n' ); 291 | _output = _song_info.tracks[i].clips[ clips_idx ].index; 292 | } 293 | } 294 | } 295 | } 296 | 297 | function update() { 298 | if( _counter === _ticks ) { 299 | //select and fire clip 300 | api_obj.goto( "live_set tracks " + _track + " clip_slots " + _output ); 301 | api_obj.call( "fire" ); 302 | //reset for next round 303 | set_all(); 304 | _counter = 0; 305 | } 306 | _counter++; 307 | } 308 | 309 | //get random int within a specified range 310 | function random_range( upper, lower ) { 311 | return Math.floor( Math.random() * ( upper - lower + 1) ) + lower; 312 | } 313 | 314 | return { 315 | get_trigger : get_trigger, 316 | update : update 317 | } 318 | } 319 | 320 | /*js version of transport, still a little wonky 321 | initialize api object: var tempo = api.get("tempo");*/ 322 | GM4L.Transport = function(tempo) { 323 | this.last_bar = 0; 324 | this.last_beat = 0; 325 | this.bpm_ms = 60000./tempo; 326 | } 327 | 328 | //get current time: api.call("get_current_beats_song_time"); 329 | GM4L.Transport.prototype.beat_bang = function(cur_bt_st) { 330 | var song_time = cur_bt_st.split("."); 331 | var beat_change; 332 | if (song_time[1] !== this.last_beat){ 333 | beat_change = true; 334 | this.last_beat = song_time[1]; 335 | } 336 | else { 337 | beat_change = false; 338 | } 339 | return beat_change; 340 | } 341 | 342 | GM4L.Transport.prototype.bar_bang = function(cur_bt_st) { 343 | var song_time = cur_bt_st.split("."); 344 | var bar_change; 345 | if (song_time[0] !== this.last_bar){ 346 | bar_change = true; 347 | this.last_bar = song_time[0]; 348 | } 349 | else { 350 | bar_change = false; 351 | } 352 | return bar_change; 353 | } 354 | -------------------------------------------------------------------------------- /m4l/js/live_time_events.js: -------------------------------------------------------------------------------- 1 | /* 2 | dispatch events from Live to server 3 | */ 4 | 5 | inlets = 1; 6 | outlets = 1; 7 | 8 | var availableEvents = { 9 | beat_callback : function() { 10 | var msgOut = { 11 | type : "time_ev", 12 | data : "beat" 13 | }; 14 | messnamed( "time_ev", JSON.stringify( msgOut )); 15 | }, 16 | bar_callback : function() { 17 | var msgOut = { 18 | type : "time_ev", 19 | data : "bar" 20 | }; 21 | messnamed( 'time_ev', JSON.stringify( msgOut )); 22 | } 23 | } 24 | 25 | //change in bar or beat 26 | function MeterEvent( name, callback ) 27 | { 28 | var _name = name, 29 | _prev_value = null, 30 | _callback = callback; 31 | 32 | function get_name() { 33 | return this.name; 34 | } 35 | 36 | function set_callback( callback ) { 37 | _callback = callback; 38 | } 39 | 40 | //returns true if current value is different than previous 41 | function is_event( value ) { 42 | if ( this._prev_value != null && value != this._prev_value ) { 43 | this._prev_value = value; 44 | if ( _callback !== null ) { 45 | _callback(); 46 | } 47 | else { 48 | post("cb is null" + "\n"); 49 | } 50 | return true; 51 | } 52 | else { 53 | this._prev_value = value; 54 | return false; 55 | } 56 | } 57 | 58 | return { 59 | get_name : get_name, 60 | set_callback : set_callback, 61 | is_event : is_event 62 | } 63 | } 64 | 65 | //returns true is "type" and "data" keys found in input JSON 66 | function check_keys( json_input ) { 67 | if ( !json_input.hasOwnProperty( "type" ) || !json_input.hasOwnProperty( "data" ) ) { 68 | post( "json must contain 'type' and 'data' keys", '\n'); 69 | return false; 70 | } 71 | return true; 72 | } 73 | 74 | var output = {}, 75 | beat_change = null, 76 | bar_change = null; 77 | 78 | function anything() 79 | { 80 | var args = arrayfromargs( messagename, arguments ); 81 | 82 | //first arg should be the type of input 83 | switch( args[0] ) { 84 | case 'json': 85 | var jsonInput; 86 | //first, check if json is valid 87 | try { 88 | var jsonInput = JSON.parse( args[1] ); 89 | } 90 | catch ( exception ) { 91 | post( "invalid json: " + exception, '\n' ); 92 | return; 93 | } 94 | 95 | //then, make sure json has "type" and "data" keys 96 | if ( !check_keys( jsonInput ) ) 97 | return; 98 | 99 | var dataObj = jsonInput.data; 100 | //evaluate the json 101 | switch( jsonInput.type ) { 102 | //transport object 103 | case 'transport': 104 | //beat change event check 105 | if ( beat_change !== null && beat_change.is_event( dataObj.beat_count )) 106 | outlet(0, "beat_change" ); 107 | //bar change event check 108 | if ( bar_change !== null && bar_change.is_event( dataObj.bar_count )) 109 | outlet(0, "bar_change" ); 110 | break; //case 'transport' 111 | 112 | //external configuration 113 | case 'config': 114 | //loop through array of objects where data = the callback function 115 | for ( var i = 0, il = dataObj.length; i < il; i++ ) { 116 | //make sure each object has "type" and "data" keys 117 | /*if ( !check_keys( obj_array[i] ) ) 118 | continue;*/ 119 | 120 | switch( dataObj[i].type ) { 121 | //set meter event callbacks 122 | case 'bar_callback': 123 | bar_change = MeterEvent( "bar_change", availableEvents.bar_callback ); 124 | break; 125 | case 'beat_callback': 126 | beat_change = MeterEvent( "beat_change", availableEvents.beat_callback ); 127 | break; 128 | } 129 | } 130 | break; //case 'config' 131 | } 132 | break; //case 'json' 133 | } 134 | } -------------------------------------------------------------------------------- /m4l/js/param_changer.js: -------------------------------------------------------------------------------- 1 | /* 2 | set parameters using global m4l ParamChange 3 | */ 4 | 5 | var param_change = null; 6 | 7 | inlets = 1; 8 | 9 | var api = new LiveAPI( "live_set" ); 10 | 11 | function anything() 12 | { 13 | var a = arrayfromargs( messagename, arguments ); 14 | //set the device for which to change parameter 15 | if ( a[0] == "set_device" ) { 16 | if ( a[1] ) 17 | param_change = new GM4L.ParamChange( a[1] ); 18 | else 19 | post( "you must specify a device" ); 20 | } 21 | if ( param_change != null ) { 22 | switch( a[0] ) { 23 | //list parameters for current device 24 | case "list_params": 25 | var params_obj = JSON.parse( param_change.list_params( api ) ); 26 | for( var i = 0; i < params_obj.umenu.length; i++ ) 27 | outlet( 0, params_obj.umenu[i] ); 28 | break; 29 | //set the current parameter 30 | case "set_param": 31 | if ( a[1] ) 32 | param_change.set_param( api, a[1] ); 33 | else 34 | post( "set param called with no arguments", '\n' ); 35 | break; 36 | //set parameter value directly 37 | case "set_value": 38 | if ( a[1] ) 39 | param_change.set_value( api, a[1] ); 40 | else 41 | post( "set value called with no arguments", '\n' ); 42 | break; 43 | //set parameter value as a percentage 44 | case "set_percent_value": 45 | if ( a[1] ) 46 | param_change.set_value( api, map( a[1], 0.0, 1.0, param_change.min, param_change.max ) ); 47 | else 48 | post( "normalized set value called with no arguments", '\n' ); 49 | break; 50 | } 51 | } 52 | } 53 | 54 | //map input range to output range 55 | function map( input, in_min, in_max, out_min, out_max ) { 56 | if ( input > in_max || input < in_min ) 57 | post( "input is out of range" ); 58 | else 59 | return ( input - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + parseInt( out_min ); 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /m4l/js/parse_chord.js: -------------------------------------------------------------------------------- 1 | /* 2 | keeps track of and sorts notes being played 3 | intended to drive live resonator 4 | */ 5 | 6 | inlets = 1; 7 | outlets = 4; 8 | 9 | var rootNote, 10 | chordNotes = []; 11 | 12 | function anything() 13 | { 14 | var a = arrayfromargs( messagename, arguments ); 15 | 16 | switch( a[0] ) { 17 | 18 | case "note_event": 19 | //notes including and above middle C 20 | if ( a[1] >= 60 ) { 21 | if ( a[2] > 0 ) { 22 | chordNotes.push( a[1] ); 23 | chordNotes.sort(); 24 | post( "chord notes: " + chordNotes + '\n' ); 25 | outputNotes( chordNotes, false ); 26 | } 27 | else { 28 | chordNotes.splice( chordNotes.indexOf( a[1] ), 1 ); 29 | } 30 | } 31 | //notes below middle C 32 | else { 33 | if ( a[2] > 0 ) { 34 | rootNote = a[1]; 35 | post( "root note: " + rootNote + '\n' ); 36 | outputNotes( rootNote, true ); 37 | } 38 | } 39 | break; 40 | } 41 | } 42 | 43 | /** 44 | output note values to correct outlets 45 | 0 is root 46 | 1-3 are chord notes with 1 being lowest 47 | */ 48 | function outputNotes( notes, bIsRoot ) 49 | { 50 | if ( bIsRoot ) { 51 | outlet( 0, notes ); 52 | } 53 | else { 54 | for ( var i = 0, il = notes.length; i < il; i++ ) { 55 | outlet( i + 1, notes[i] ); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /m4l/js/ramp_in_range.js: -------------------------------------------------------------------------------- 1 | /* 2 | generates an eased ramp of a specified duration 3 | destination value is generated via drunk walk number generator 4 | */ 5 | 6 | inlets = 1; 7 | outlets = 1; 8 | 9 | var centerVal = 0.9, //center value of total output range 10 | lastVal = centerVal, 11 | range = 0.2, //total output range 12 | rate = 30, //rate / duration are in milliseconds 13 | duration = 1000, 14 | drunk = new GM4L.Drunk( centerVal - ( range / 2 ), centerVal + ( range / 2 )), 15 | easing = new GM4L.Easing( duration, rate ); 16 | 17 | function anything() 18 | { 19 | var a = arrayfromargs( messagename, arguments ); 20 | 21 | switch( a[0] ) { 22 | 23 | //start ramp 24 | case "start": 25 | easing.start_val = lastVal; 26 | easing.end_val = drunk.step( 0.01, 0.05 ); //TODO set this dynamically 27 | lastVal = easing.end_val; 28 | easing.start(); 29 | break; 30 | 31 | case "set_center_val": 32 | if ( a[1] ) { 33 | centerVal = a[1]; 34 | resetDrunk(); 35 | } 36 | else { 37 | post( "you must supply an argument to set center value" ); 38 | } 39 | break; 40 | 41 | case "set_range": 42 | if ( a[1] ) { 43 | range = a[1]; 44 | resetDrunk(); 45 | } 46 | else { 47 | post( "you must supply an argument to set the range" ); 48 | } 49 | break; 50 | } 51 | } 52 | 53 | function bang() 54 | { 55 | easedVal = easing.move( easing.easeIn ); 56 | if ( easing.end_val && easedVal !== easing.end_val ) { 57 | outlet( 0, easedVal ); 58 | } 59 | } 60 | 61 | function resetDrunk() 62 | { 63 | drunk.setMinOut( centerVal - ( range / 2 )); 64 | drunk.setMaxOut( centerVal + ( range / 2 )); 65 | } -------------------------------------------------------------------------------- /m4l/js/set_specific/15_11_14knife.js: -------------------------------------------------------------------------------- 1 | /* 2 | listen for clips being triggered 3 | */ 4 | 5 | inlets = 1; 6 | outlets = 1; 7 | 8 | //60 / BPM * 100 = ms => BPM 9 | var barMs = ( 4 * ( 60000 / 133 )), 10 | easing = new GM4L.Easing( barMs, 30, 0, 100 ); 11 | 12 | post( "bar ms: " + barMs + " duration: " + easing.duration + '\n' ); 13 | 14 | function anything() 15 | { 16 | var jsonIn, 17 | easedVal, 18 | argArr = arrayfromargs( messagename, arguments ); 19 | 20 | switch ( argArr[0] ) { 21 | 22 | case 'move': 23 | easedVal = easing.move( easing.easeIn ); 24 | if ( easedVal !== 0 && easedVal !== 100 ) { 25 | post( "move: " + easing.move( easing.easeIn ) + '\n' ); 26 | } 27 | break; 28 | 29 | case 'start': 30 | easing.start(); 31 | break; 32 | 33 | case 'clip_event': 34 | //post( argArr[1] + '\n' ); 35 | 36 | jsonIn = JSON.parse( argArr[1] ); 37 | 38 | if ( jsonIn.data.event === "clip_on" && jsonIn.data.name === "knife" ) { 39 | easing.start(); 40 | } 41 | /*post( "json data event: " + jsonIn.data.event + '\n' ); 42 | if ( jsonIn.data.event == "clip_on" ) { 43 | var randNum = random_range( -1, 5 ); 44 | outlet( 0, notes[ randNum ]); 45 | }*/ 46 | break; 47 | } 48 | } 49 | 50 | function random_range( upper, lower ) { 51 | return Math.floor( Math.random() * ( upper - lower + 1) ) + lower; 52 | } -------------------------------------------------------------------------------- /m4l/js/sfplay_driver.js: -------------------------------------------------------------------------------- 1 | /* 2 | takes input from folder_traversal.js to create list of files to play 3 | */ 4 | 5 | inlets = 1; 6 | outlets = 1; 7 | 8 | var fromJson, 9 | folderPath, 10 | regexMatch, 11 | filtered, 12 | playingIndex = 0; 13 | 14 | function anything() 15 | { 16 | var a = arrayfromargs( messagename, arguments ); 17 | 18 | switch( a[0] ) { 19 | 20 | //parse json from folder_traversal.js 21 | case "ft_json": 22 | try { 23 | fromJson = JSON.parse( a[1] ); 24 | } 25 | catch ( exception ) { 26 | post( "sfplay_driver exception: " + exception + '\n' ); 27 | } 28 | break; 29 | 30 | //set the folder path to files to play 31 | case "set_folder": 32 | if ( a[1] ) { 33 | folderPath = a[1] + "/"; 34 | } 35 | else { 36 | post( "folder path must be provided" ); 37 | return; 38 | } 39 | break; 40 | 41 | //filter list of files based on supplied string 42 | case "filter": 43 | //ensure that string to match in filenames has been provided 44 | if ( a[1] ) { 45 | regexMatch = new RegExp( a[1], "i" ); 46 | } 47 | else { 48 | post( "please provide a string to filter filenames by" ); 49 | return; 50 | } 51 | 52 | //push filenames that match regex to filtered array 53 | filtered = []; 54 | for ( var i = 0, il = fromJson.filenames.length; i < il; i++ ) { 55 | if ( fromJson.filenames[i].match( regexMatch ) !== null ) { 56 | filtered.push( fromJson.filenames[i] ); 57 | } 58 | } 59 | break; 60 | 61 | //play next file in sequence 62 | case "play_next": 63 | if ( filtered ) { 64 | outlet( 0, "open", folderPath + filtered[ playingIndex ]); 65 | } 66 | else { 67 | post( "filtered filename list is empty" ); 68 | return; 69 | } 70 | playingIndex < filtered.length - 1 ? playingIndex++ : playingIndex = 0; 71 | break; 72 | 73 | //play random file in sequence 74 | case "play_random": 75 | if ( filtered ) { 76 | outlet( 0, "open", folderPath + filtered[ random_range( -1, filtered.length )]); 77 | } 78 | else { 79 | post( "filtered filename list is empty" ); 80 | return; 81 | } 82 | break; 83 | } 84 | } 85 | 86 | function random_range( upper, lower ) { 87 | return Math.floor( Math.random() * ( upper - lower + 1) ) + lower; 88 | } -------------------------------------------------------------------------------- /m4l/js/to_cinder.js: -------------------------------------------------------------------------------- 1 | /* 2 | send instructions via TCP server to cinder 3 | */ 4 | 5 | inlets = 1; 6 | outlets = 1; 7 | autowatch = 1; 8 | 9 | var send_to = "to_server"; //name of receive object 10 | 11 | function anything() 12 | { 13 | var args = arrayfromargs( messagename, arguments ), 14 | output = null, 15 | output_arr = []; 16 | 17 | switch( args[0] ) { 18 | 19 | case 'alpha_mod': 20 | 21 | output = {}; 22 | output.type = "set_alpha"; 23 | output.data = +args[1].toFixed( 3 ); 24 | 25 | break; //alpha_mod 26 | 27 | case 'fire_video': 28 | 29 | output = {}; 30 | output.type = "fire_video"; 31 | output.data = {}; 32 | output.data.dir = args[1]; //name of video directory 33 | output.data.idx = +args[2]; //the index of the video in directory 34 | 35 | break; //fire_video 36 | 37 | case 'fire_pair': 38 | 39 | output = {}; 40 | //TO DO: refactor this so less redundant 41 | output_arr[0] = args[1].split( "_" ); 42 | output_arr[1] = args[2].split( "_" ); 43 | output.type = "fire_pair"; 44 | output.data = [ 45 | { 46 | dir : output_arr[0][0], 47 | idx : +output_arr[0][1] 48 | }, 49 | { 50 | dir : output_arr[1][0], 51 | idx : +output_arr[1][1] 52 | } 53 | ]; 54 | 55 | break; 56 | } 57 | 58 | if ( output !== null ) { 59 | messnamed( send_to, JSON.stringify( output ) ); 60 | } 61 | else 62 | post( "output message to cinder is not valid", '\n' ); 63 | } 64 | -------------------------------------------------------------------------------- /m4l/js/transport.js: -------------------------------------------------------------------------------- 1 | /* 2 | packs Live transport data from Max plugsync~ object 3 | */ 4 | 5 | inlets = 1; 6 | outlets = 1; 7 | 8 | var transport_obj = { 9 | //all possible params, init as null 10 | 'state' : null, 11 | 'bar_count' : null, 12 | 'beat_count' : null, 13 | 'ticks_beat' : null, 14 | 'time_sig' : null, 15 | 'ticks' : null, 16 | 'tempo' : null, 17 | 'sample_count' : null, 18 | 'flags' : null 19 | }; 20 | 21 | function anything() 22 | { 23 | var args = arrayfromargs( messagename, arguments ), 24 | valid_arg = 0; 25 | 26 | for ( var i = 0, il = args.length; i < il; i += 2 ) { 27 | 28 | //loop through properties 29 | for ( var prop in transport_obj ) { 30 | //check that current argument is valid property 31 | if ( prop === args[i] ) { 32 | transport_obj[ prop ] = args[ i + 1 ]; 33 | valid_arg++; 34 | } 35 | } 36 | 37 | //if current arguement is not valid, log error 38 | if ( valid_arg === 0 ) 39 | post( args[i] + " is not a valid arg", '\n' ); 40 | } 41 | } 42 | 43 | function bang() 44 | { 45 | //check if any transport parameters are null 46 | var null_count = 0; 47 | for ( var prop in transport_obj ) { 48 | if ( transport_obj[ prop ] === null ) 49 | null_count++; 50 | } 51 | 52 | //if all parameters are set, output transport object 53 | if ( null_count === 0 ) { 54 | var output = { 55 | type : "transport", 56 | data : transport_obj 57 | }; 58 | outlet( 0, JSON.stringify( output ) ); 59 | } 60 | else 61 | post( "at least one required property is not set", '\n' ); 62 | } -------------------------------------------------------------------------------- /tcpServer/connection_handler.js: -------------------------------------------------------------------------------- 1 | var clients = [], 2 | MessageHandler = require('./message_handler.js'), 3 | msgHandler = new MessageHandler(); 4 | 5 | //route incoming messages through message handler 6 | exports.handle_incoming = function( socket, obj ) { 7 | obj.sender = get_name( socket ); 8 | msgHandler.handle_incoming( obj ); 9 | } 10 | 11 | //send message from handler to client(s) 12 | msgHandler.on( 'write', function( msg ) { 13 | //send message to correct recipients 14 | for ( var i = 0, il = msg.recipients.length; i < il; i++ ) { 15 | for ( var j = 0, jl = clients.length; j < jl; j++ ) { 16 | if ( msg.recipients[i] == clients[j].name ) { 17 | clients[j].conn.write( JSON.stringify( msg ) ); 18 | } 19 | } 20 | } 21 | }); 22 | 23 | //check if the client is in the list, DEPRECATED 24 | var get_name = function( socket ) { 25 | for ( var i = 0, il = clients.length; i < il; i++ ) { 26 | if ( clients[i].conn === socket ) 27 | return clients[i].name; 28 | } 29 | } 30 | 31 | //request that the newly connected client identify itself 32 | exports.request_ident = function( socket ) { 33 | //send identification request 34 | var conn_request = {}; 35 | conn_request.type = "request_ident"; 36 | conn_request.data = null; 37 | socket.write( JSON.stringify( conn_request ) ); 38 | } 39 | 40 | //add client to list 41 | exports.add_client = function( socket, name ) { 42 | //add to client list 43 | var client = {}; 44 | client.conn = socket; 45 | client.name = name; 46 | console.log( name + " " + socket.remoteAddress + " " + socket.remotePort + " has been added" ); 47 | clients.push( client ); 48 | var outgoing = {}; 49 | outgoing.type = "status"; 50 | outgoing.data = "connected as " + name; 51 | return JSON.stringify( outgoing ); 52 | } 53 | 54 | exports.remove_client = function( socket ) { 55 | var match_counter = 0; 56 | for ( var i = 0, il = clients.length; i < il; i++ ) { 57 | if ( clients[i].conn === socket ) { 58 | console.log( clients[i].name + " disconnected" ); 59 | clients.splice( clients[i], 1 ); 60 | match_counter ++; 61 | } 62 | } 63 | if ( match_counter == 0 ) 64 | console.log( "disconnecting client was not found in connection list" ); 65 | } -------------------------------------------------------------------------------- /tcpServer/message_handler.js: -------------------------------------------------------------------------------- 1 | var util = require( 'util' ), 2 | EventEmitter = require( 'events' ).EventEmitter; 3 | 4 | //construct message handler with event emitter 5 | function MessageHandler() { 6 | EventEmitter.call( this ); 7 | } 8 | 9 | //make message handler inherit event emitter 10 | util.inherits( MessageHandler, EventEmitter ); 11 | 12 | //handle incoming messages from server 13 | MessageHandler.prototype.handle_incoming = function( obj ) { 14 | console.log( "received msg: ", obj, "from sender: ", obj.sender ); 15 | var recipients = []; 16 | var outgoing = {}; 17 | outgoing.type = null; 18 | //handle messages with destination cinder 19 | if ( obj.type == "to_cinder" ) { 20 | recipients.push( "cinder" ); 21 | outgoing.type = "from_max"; 22 | outgoing.data = obj.data; 23 | if ( obj.data_type ) 24 | outgoing.data_type = obj.data_type; 25 | } 26 | //handle messages with destination max 27 | else if ( obj.type == "to_max" ) { 28 | recipients.push( "max" ); 29 | outgoing = obj; 30 | outgoing.type = "from_cinder"; 31 | //console.log( "sending message: ", obj ); 32 | } 33 | //filter malformed messages 34 | if ( outgoing.type != null ) { 35 | outgoing.recipients = recipients; 36 | try { 37 | this.write( outgoing ); 38 | } 39 | catch ( exception ) { 40 | console.log( "socket write exception: ", exception ); 41 | } 42 | } 43 | } 44 | 45 | //emit write message to connection handler which owns connections 46 | MessageHandler.prototype.write = function( output ) { 47 | this.emit( "write", output ); 48 | } 49 | 50 | module.exports = MessageHandler; -------------------------------------------------------------------------------- /tcpServer/tcp_server.js: -------------------------------------------------------------------------------- 1 | var net = require('net'), //load tcp library 2 | conn_handler = require('./connection_handler.js'); 3 | 4 | //start TCP Server 5 | var server = net.createServer(function ( socket ) { 6 | 7 | this.once( 'connection', function( socket ) { 8 | conn_handler.request_ident( socket ); 9 | }); 10 | 11 | //handle incoming messages from clients. 12 | //connection request = @type: "ident", @name: "client_friendly_name" 13 | socket.on( 'data', function ( data ) { 14 | try { 15 | var obj = JSON.parse( data ); 16 | } 17 | catch ( exception ) { 18 | console.log( "Json parse error: " + exception ); 19 | return; 20 | } 21 | if ( obj.type === "ident" ) 22 | socket.write( conn_handler.add_client( socket, obj.data ) ); 23 | else 24 | conn_handler.handle_incoming( socket, obj ); 25 | }); 26 | 27 | //handle client removal 28 | socket.on('end', function() { 29 | conn_handler.remove_client( socket ); 30 | }); 31 | 32 | }).listen(1234); 33 | --------------------------------------------------------------------------------