add: purest_json lib

This commit is contained in:
Arthur Santos 2024-09-18 21:11:11 -03:00
parent e29aa19b01
commit f9badbe6f6
69 changed files with 6421 additions and 0 deletions

180
purest_json/Changelog.txt Normal file
View File

@ -0,0 +1,180 @@
Changelog
---------
2.0.0: Medea
- BREAKING; [oauth], [rest], [json-decode]: Change outlet order to Pd standard order
-- right outlet outputs on error
-- middle outlet outputs data
-- left outlet outputs bang on done
- deken packages include dependencies for all systems, including Linux
- Updated help files and examples
- [Mac]; [rest], [oauth]: OS X now uses system certificate authority information
- [Mac] Support for newer OS X versions
- [Linux] arm64 packages
- Support for multiinstance Pd on compile time added
- Bug fixes:
-- [json-encode]: Can read files again
-- [rest], [oauth]: Fixed crash on closing patch while waiting for data
-- [Windows]; [rest], [oauth]: Cancelling requests on Windows working,
although not as fast as on true POSIX compliant systems
- Internal: Switch to Circle CI for compilation
1.4.3: Y U no stable API
- Bug fix: compilation works with json-c >= 0.13
- Bug fix: remove boilerplate display in Pd console
1.4.2: Argo in Shipyard
- Update of build scripts and documentation
- Usage of CI for build
1.4.1: Orpheus's Lyre
- Bug fix:
-- [json-encode] and [json-decode]: Correctly freeing JSON object
memory
- Removed Google API calls from help
- Switch Makefile to pd-lib-builder
- Remove building of own Debian packages
- [Mac] Add liboauth build as homebrew script
1.4.0: My neighbor TOR
- [rest] and [oauth]: proxy enabled
- updated manual
1.3.0: Trickle down theory
- [json-encode] and [urlparams]: optimisation of logic
- [rest] and [oauth]: HTTP streaming enabled
- Rewrite of manual
- Bug fix:
-- [oauth]: unitialised object does not request data
- Refactoring of source code:
-- moved source to subfolders
-- static analysis of source code
1.2.0: OAuth rly
- [oauth]: PATCH, TRACE and OPTIONS request implemented
1.1.0: Wow! Much request! Such test!
- [rest]: HEAD, PATCH, TRACE and OPTIONS request implemented
- [oauth]: HEAD request implemented
- Bug fixes:
-- [rest] and [oauth]: Mac OS X needs cacert.pem
-- [json-encode]: differentiate between float and integer values
- unit tests for [json-decode], [json-encode], [urlparams]
1.0.0: Pendulum
- Info for users while loading object
- Bug fixes in [json-encode]:
-- array handling
-- number handling
- Refactoring
0.15.0: The API they are a-changing
- Cancellation is now faster
- Switch to json-c 0.11
- Refactoring of code
- Breaking changes:
-- [oauth] and [rest]:
* [write( method is now called [file(
* [url( method is now called [init(
* init errors only output to console
* changes to status outlet:
** on success output bang
** on HTTP error output numerical HTTP status
** on cURL error output list: error code and message
-- [rest-json] has been removed
-- [json-decode]:
* string values will not be checked for numbers or boolean
0.14.0: Davo
- Downloading to file
- Cancelling requests
- Switch to libcurl multi interface
0.13.0: heady stuff
- Setting HTTP headers possible
- Cancelling of requests possible while waiting (experimental)
- Switched Makefile to libary template 1.0.14
- Semantic versioning
0.12.1: I accidentally the whole cookie
- Bugfix: Cookie authentication is working again.
0.12: The multitude came together
- Disabling checking peer for SSL requests in [rest] and [oauth] possible
- [urlparams] does now overwrite previously set parameters
- RSA-SHA1 signature possible, otherwise info message is posted to Pd console
- Bugfixes:
-- SSL requests on Windows possible
-- regression fixed for PUT requests
0.11: long string is long
- symbols can be longer than MAXPDLENGTH (1024 characters)
- [json-decode] works with lists and any other data type as well
- Setting request timeout for [rest] and [oauth] possible
- Bugfixes:
-- [oauth] posts data again
-- Fixed segfault in Windows at errors
- Cleaning up of source code and help files
0.10:
- no version 0.10 due to problems in Pd (cuts off trailing 0)
0.9: sailing to Colchis
- [json-encode] writes and reads JSON data to and from files
- [oauth] does not use deprecated functions from liboauth 1.0
- [oauth] and [rest] share functions
- [json-encode] and [urlparams] share functions
- Bugfixes:
-- POST sends correct parameter data
-- HTTP errors are displayed with error code
0.8: I did, I did taw a putty tat
- Added objects: [oauth] [urlparams] [rest]
- [rest-json] is now an abstraction
- Bugfixes
- Better examples and help patches
0.7.1: Cookie monster on the couch
- Unlocking [rest-json] when HTTP status is not 200.
- Fix for segfault at json_object_put().
0.7: Cookie monster on the couch
- Cookie authentication, useful for CouchDB login
- [rest-json] has a third outlet
- Refactoring
0.6:
- Lots of bugfixes
0.5:
- Locking [rest-json] more restrictively
- Makefile is now ready for packaging
- Debian package is available
0.4.1:
- Hopefully fixed threading issues
0.4:
- Fixed cross-thread access to rest object
- Fixed stack overflow issue of threads
- Refactoring
0.3:
- Fixed memory leaks
- Added manual
0.2.1:
- Added this Changelog
0.2:
- Renamed library to purest_json
- Outputting nested JSON objects and arrays as strings
- Outputting JSON arrays as a series of objects
- Using threading for HTTP requests
- Using Pd-extended library template
0.1:
- Basic operations for connection to CouchDB
- Basic JSON encoding and decoding

45
purest_json/LICENSE.txt Normal file
View File

@ -0,0 +1,45 @@
Author:
Thomas Mayer <thomas@residuum.org>
Copyright:
(c) 2011-2022 Thomas Mayer
(c) 2012 Hans-Christoph Steiner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Copyright (c) 2005-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

70
purest_json/README.md Normal file
View File

@ -0,0 +1,70 @@
_____ _____ ______ _____ _______ _ _____ ____ _ _
| __ \ | __ \| ____|/ ____|__ __| | |/ ____|/ __ \| \ | |
| |__) |_ _| |__) | |__ | (___ | | | | (___ | | | | \| |
| ___/| | | | _ /| __| \___ \ | | _ | |\___ \| | | | . ` |
| | | |_| | | \ \| |____ ____) | | | | |__| |____) | |__| | |\ |
|_| \__,_|_| \_\______|_____/ |_| \____/|_____/ \____/|_| \_|
PuREST JSON is a library for connecting Puredata (Pd) to HTTP services
and encoding and decoding JSON data.
The library can issue GET, POST, PUT and DELETE statements, so consumation
of RESTful services is possible, e.g. CouchDB.
## About Puredata (From the official website)
Pd (aka Pure Data) is a real-time graphical programming environment for
audio, video, and graphical processing. It is the third major branch
of the family of patcher programming languages known as Max (Max/FTS,
ISPW Max, Max/MSP, jMax, etc.) originally developed by Miller Puckette
and company at IRCAM. The core of Pd is written and maintained by Miller
Puckette and includes the work of many developers, making the whole
package very much a community effort.
## Externals in the library
### `[rest]`
Object for issuing HTTP request.
### `[oauth]`
Object for issuing HTTP requests with OAUTH.
### `[json-encode]`
Object for encoding data to JSON.
### `[json-decode]`
Object for decoding JSON data.
### `[urlparams]`
Object for url encoding and concatenating url parameters.
For the usage of the externals see the help patches for the objects.
## Installation from package repositories
Downloads are available via [deken](https://github.com/pure-data/deken)
which is included in Pd since version 0.47. Packages for Debian and Ubuntu
are available as `pd-purest-json`.
## Downloads of development versions
For each commit, a build in [Circle CI](https://app.circleci.com/pipelines/github/residuum/PuRestJson)
is triggered. These builds generate deken-like packages, that are available
from https://cloud.residuum.org/index.php/s/380C60JAabnO7jk
The format for the files is `<Circle-CI-job-number>_<Date-in-YYYY-MM-DD>_<dekenfilename>`.
Those downloads may not work, but represent the current state of development.
## How to build PuREST JSON
The library uses the template for Pd-extended. Drop the library in a
new folder `purest_json` in the "external" path of the Pd-extended
source code and run make in the folder. libcurl and json-c is needed.
Details can be found at
https://github.com/residuum/PuRestJson/wiki/Compilation
If you encouter bugs or feel like a feature is missing, have a look
the bug tracker at
https://github.com/residuum/PuRestJson/issues

View File

@ -0,0 +1,11 @@
#N canvas 758 280 510 363 10;
#X obj 48 283 rest;
#X msg 87 39 GET http://ix.residuum.org/pd/abstractions/sample-looper.png
;
#X obj 58 323 print;
#X msg 49 7 file /tmp/test.png;
#X msg 139 77 file;
#X connect 0 1 2 0;
#X connect 1 0 0 0;
#X connect 3 0 0 0;
#X connect 4 0 0 0;

View File

@ -0,0 +1,139 @@
#N canvas 46 68 1298 769 10;
#X declare -path purest_json -stdlib zexy;
#X obj 415 136 json-encode;
#X msg 876 36 bang;
#X msg 874 82 clear;
#X obj 454 185 print json-encoded data;
#X obj 434 254 json-decode;
#X msg 309 42 add value 440;
#X obj 207 529 line;
#X floatatom 207 556 5 0 0 0 - - - 0;
#X obj 206 476 pack f f f;
#X msg 206 504 \$1 \, \$2 \$3;
#X msg 424 93 add start 10;
#X obj 237 372 list trim;
#X obj 349 449 print id;
#X obj 206 448 f;
#X msg 526 63 add name first note;
#X obj 411 450 print name;
#X msg 381 70 add duration 1000;
#X msg 503 30 add name wrong name;
#X obj 237 400 route start value duration _id name on;
#X msg 698 92 add on TRUE;
#X msg 140 75 PUT test;
#X msg 206 111 GET test;
#X msg 286 269 DELETE test;
#X msg 286 242 GET test/1;
#X msg 287 212 PUT test/1 \$1;
#X msg 535 91 array var yabba;
#X msg 668 30 array var dabba;
#X msg 692 61 array var doo;
#X msg 604 296 GET _uuids?count=4;
#X obj 714 397 route uuids;
#X obj 714 370 list trim;
#X obj 714 450 json-decode;
#N canvas 82 61 1112 677 webservices 0;
#X obj 170 455 list trim;
#X obj 170 538 json-decode;
#X obj 20 571 print array-done;
#X obj 201 571 print array-decode;
#X msg 129 130 GET http://www.reddit.com/r/all/search.json?q=puredata
;
#X msg 179 160 GET http://en.wikipedia.org/w/api.php?action=query&titles=Puredata&prop=info|links&format=json
;
#X obj 170 485 route results;
#X obj 129 351 rest;
#X obj 139 410 json-decode;
#X obj 15 390 print rest-status;
#X obj 242 411 print raw-data;
#X obj 11 471 print decode-done;
#X connect 0 0 6 0;
#X connect 1 0 2 0;
#X connect 1 1 3 0;
#X connect 4 0 7 0;
#X connect 5 0 7 0;
#X connect 6 0 1 0;
#X connect 7 0 9 0;
#X connect 7 1 8 0;
#X connect 7 1 10 0;
#X connect 8 0 11 0;
#X connect 8 1 0 0;
#X restore 10 467 pd webservices;
#X obj 4 381 print couchdb_return;
#X obj 434 287 print decode_json_data;
#X obj 714 423 l2s;
#X obj 304 373 print status_messages;
#X obj 415 159 t a a a;
#X msg 61 38 init http://127.0.0.1:5984/;
#X obj 683 346 json-decode;
#X obj 604 319 rest http://127.0.0.1:5984/;
#X obj 206 329 json-decode;
#X obj 194 292 rest;
#X obj 714 483 print array-done;
#X obj 860 483 print array-decode;
#X obj 888 549 declare -path purest_json -stdlib zexy;
#N canvas 198 282 778 533 github 0;
#X obj 116 137 rest;
#X obj 203 204 print data;
#X msg 116 108 GET https://api.github.com/repos/residuum/PuRestJson/commits
;
#X obj 126 172 t a a;
#X obj 126 218 json-decode;
#X obj 157 243 list trim;
#X msg 95 67 header User-Agent: My User Agent;
#X obj 49 275 print array-done;
#X obj 157 275 print array-decoded;
#X connect 0 1 3 0;
#X connect 2 0 0 0;
#X connect 3 0 4 0;
#X connect 3 1 1 0;
#X connect 4 0 7 0;
#X connect 4 1 5 0;
#X connect 5 0 8 0;
#X connect 6 0 0 0;
#X restore 8 506 pd github;
#X connect 0 0 37 0;
#X connect 1 0 0 0;
#X connect 2 0 0 0;
#X connect 4 1 34 0;
#X connect 5 0 0 0;
#X connect 6 0 7 0;
#X connect 8 0 9 0;
#X connect 9 0 6 0;
#X connect 10 0 0 0;
#X connect 11 0 18 0;
#X connect 13 0 8 0;
#X connect 14 0 0 0;
#X connect 16 0 0 0;
#X connect 17 0 0 0;
#X connect 18 0 13 1;
#X connect 18 1 8 1;
#X connect 18 2 8 2;
#X connect 18 3 12 0;
#X connect 18 4 15 0;
#X connect 19 0 0 0;
#X connect 20 0 42 0;
#X connect 21 0 42 0;
#X connect 22 0 42 0;
#X connect 23 0 42 0;
#X connect 24 0 42 0;
#X connect 25 0 0 0;
#X connect 26 0 0 0;
#X connect 27 0 0 0;
#X connect 28 0 40 0;
#X connect 29 0 35 0;
#X connect 30 0 29 0;
#X connect 31 0 43 0;
#X connect 31 1 44 0;
#X connect 35 0 31 0;
#X connect 37 0 24 0;
#X connect 37 1 4 0;
#X connect 37 2 3 0;
#X connect 38 0 42 0;
#X connect 39 1 30 0;
#X connect 40 1 39 0;
#X connect 41 0 13 0;
#X connect 41 1 11 0;
#X connect 42 1 41 0;
#X connect 42 1 33 0;
#X connect 42 2 36 0;

View File

@ -0,0 +1,116 @@
#N canvas 220 101 523 589 10;
#X declare -path purest_json;
#X obj 196 482 dac~;
#X obj 203 428 *~ 0;
#X obj 204 452 *~ 0;
#X obj 306 276 vsl 15 128 0 1 0 0 empty empty volume 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X obj 174 73 rest;
#X obj 20 77 tgl 15 0 empty empty Print\ to\ console 17 7 0 10 #fcfcfc #000000 #000000 0 1;
#X floatatom 99 266 7 0 0 3 exchange\ rate - - 0;
#X symbolatom 11 265 13 0 0 3 Date - - 0;
#X obj 202 402 osc~;
#N canvas 626 288 864 436 print-to-console 0;
#X obj 28 17 inlet;
#X obj 308 26 inlet;
#X obj 172 28 inlet;
#X obj 431 18 inlet;
#X obj 308 135 print decoded-data;
#X obj 28 101 spigot;
#X obj 308 106 spigot;
#X obj 28 128 print complete-data;
#X obj 172 131 print decoding-done;
#X obj 172 100 spigot;
#X connect 0 0 5 0;
#X connect 1 0 6 0;
#X connect 2 0 9 0;
#X connect 3 0 9 1;
#X connect 3 0 5 1;
#X connect 3 0 6 1;
#X connect 5 0 7 0;
#X connect 6 0 4 0;
#X connect 9 0 8 0;
#X restore 12 161 pd print-to-console;
#N canvas 772 407 388 274 stepper 0;
#X obj 17 19 inlet;
#X obj 51 215 outlet;
#X obj 96 217 outlet;
#X obj 17 184 unpack f s f;
#X obj 17 150 text sequence \$0-sequence;
#X obj 192 224 outlet;
#X msg 192 84 1;
#X msg 164 185 0;
#X obj 17 90 metro 20;
#X msg 223 185 stop;
#X obj 17 42 t b b b;
#X msg 74 111 line 0;
#X msg 17 113 step;
#X connect 0 0 10 0;
#X connect 3 1 1 0;
#X connect 3 2 2 0;
#X connect 4 0 3 0;
#X connect 4 1 7 0;
#X connect 4 1 9 0;
#X connect 6 0 5 0;
#X connect 7 0 5 0;
#X connect 8 0 12 0;
#X connect 9 0 8 0;
#X connect 10 0 8 0;
#X connect 10 1 11 0;
#X connect 10 2 6 0;
#X connect 11 0 4 0;
#X connect 12 0 4 0;
#X restore 174 232 pd stepper;
#X obj 184 110 json-decode, f 12;
#X msg 174 44 GET https://ix.residuum.org/pd/currency_example.php;
#X obj 202 357 mtof;
#X obj 202 380 line \$1 5;
#X obj 202 304 * 32;
#X obj 202 329 + 32;
#X text 15 6 Gets the complete exchange rate history of USD to EUR and drives a sine oscillator with the rates, f 78;
#X obj 17 524 text define \$0-sequence;
#N canvas 766 104 365 231 store-data 0;
#X obj 103 66 list trim;
#X obj 103 18 inlet;
#X obj 55 18 inlet;
#X obj 103 94 route day rate;
#X obj 55 41 t b b;
#X obj 55 182 text set \$0-sequence;
#X msg 213 123 1e+15;
#X obj 103 117 symbol;
#X obj 55 157 pack f s f;
#X connect 0 0 3 0;
#X connect 1 0 0 0;
#X connect 2 0 4 0;
#X connect 3 0 7 0;
#X connect 3 1 8 2;
#X connect 4 0 8 0;
#X connect 4 1 6 0;
#X connect 6 0 5 1;
#X connect 7 0 8 1;
#X connect 8 0 5 0;
#X restore 184 149 pd store-data;
#X obj 191 190 bng 18 250 50 0 empty empty start\ sequence\ again 0 -9 0 10 #fcfcfc #000000 #000000;
#X obj 15 557 declare -path purest_json;
#X connect 1 0 2 0;
#X connect 2 0 0 1;
#X connect 2 0 0 0;
#X connect 3 0 2 1;
#X connect 4 0 10 0;
#X connect 4 1 11 0;
#X connect 4 1 9 0;
#X connect 5 0 9 3;
#X connect 8 0 1 0;
#X connect 10 0 7 0;
#X connect 10 1 15 0;
#X connect 10 1 6 0;
#X connect 10 2 1 1;
#X connect 11 0 9 1;
#X connect 11 0 19 0;
#X connect 11 1 9 2;
#X connect 11 1 19 1;
#X connect 12 0 4 0;
#X connect 13 0 14 0;
#X connect 14 0 8 0;
#X connect 15 0 16 0;
#X connect 16 0 13 0;
#X connect 20 0 10 0;

View File

@ -0,0 +1,195 @@
#N canvas 508 175 974 536 10;
#X declare -path purest_json -stdlib zexy -stdpath cyclone;
#N canvas 975 249 726 490 authorize 0;
#X msg 24 36 POST /oauth/request_token;
#X obj 178 255 print data1;
#X obj 333 253 print status1;
#X obj 24 193 oauth https://api.twitter.com SEJpJksCRpcgyoP4nk73Ng
FEHGi9k8jF3zTPrBLbnBonF94gbUGZLrGKMgl4Td5bc;
#X msg 73 83 init https://api.twitter.com SEJpJksCRpcgyoP4nk73Ng FEHGi9k8jF3zTPrBLbnBonF94gbUGZLrGKMgl4Td5bc
YOUR_TEMP_TOKEN YOUR_TEMP_SECRET;
#X msg 296 154 POST /oauth/access_token oauth_verifier=YOUR_PIN;
#X connect 0 0 3 0;
#X connect 3 1 1 0;
#X connect 3 2 2 0;
#X connect 4 0 3 0;
#X connect 5 0 3 0;
#X restore 29 287 pd authorize;
#N canvas 1071 303 520 438 simple-operations 0;
#X obj 379 187 print urlparams;
#X msg 109 62 GET /1.1/statuses/home_timeline.json;
#X msg 115 188 POST /1.1/statuses/update.json \$1;
#X obj 115 154 urlparams;
#X obj 61 232 oauth;
#X text 106 46 Get your timeline;
#X msg 115 103 clear \, add status I can haz my own twitter client
#Pd #Puredata \, bang;
#X text 132 86 Tweet;
#X obj 74 321 print data2;
#X obj 125 277 print status2;
#X obj 61 37 inlet;
#X connect 1 0 4 0;
#X connect 2 0 4 0;
#X connect 3 0 2 0;
#X connect 3 0 0 0;
#X connect 4 1 8 0;
#X connect 4 2 9 0;
#X connect 6 0 3 0;
#X connect 10 0 4 0;
#X restore 159 257 pd simple-operations;
#N canvas 855 130 931 760 sonify-it 0;
#X obj 29 129 oauth;
#X obj 29 28 inlet;
#X text 118 66 Search;
#X obj 42 226 fifop;
#X obj 42 191 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000
#000000;
#X obj 73 569 *~ 0;
#X obj 73 511 osc~;
#X obj 73 481 mtof;
#X obj 73 642 dac~;
#X obj 74 605 *~ 0;
#X obj 832 332 vsl 15 128 0 1 0 0 empty empty empty 0 -9 0 10 #fcfcfc
#000000 #000000 0 1;
#X msg 123 466 0;
#X symbolatom 229 326 38 0 0 0 - - - 0;
#X symbolatom 229 340 80 0 0 0 - - - 0;
#X obj 179 464 f;
#X obj 42 262 unpack f s s s;
#X symbolatom 509 326 40 0 0 0 - - - 0;
#X obj 74 539 *~;
#X obj 335 433 osc~;
#N canvas 1432 61 437 398 tweet-text-analysis 0;
#X obj 95 138 fifop;
#X obj 63 40 t b s;
#X obj 93 287 line;
#X msg 93 261 \$1 10;
#X obj 148 193 t f b;
#X obj 95 165 moses 33;
#X obj 13 76 metro 80;
#X obj 93 235 - 32;
#X obj 95 102 cyclone/spell;
#X obj 63 14 inlet;
#X obj 93 331 outlet;
#X obj 180 333 outlet;
#X obj 278 333 outlet;
#X obj 362 332 outlet;
#X connect 0 0 5 0;
#X connect 0 1 13 0;
#X connect 1 0 6 0;
#X connect 1 1 8 0;
#X connect 2 0 10 0;
#X connect 3 0 2 0;
#X connect 4 0 7 0;
#X connect 4 1 11 0;
#X connect 5 0 12 0;
#X connect 5 1 4 0;
#X connect 6 0 0 0;
#X connect 7 0 3 0;
#X connect 8 0 0 0;
#X connect 9 0 1 0;
#X restore 73 295 pd tweet-text-analysis;
#N canvas 987 61 448 398 data-tranformation 0;
#X obj 84 62 json-decode;
#X obj 115 90 list trim;
#X obj 115 113 route statuses;
#X obj 115 137 json-decode;
#X obj 146 191 route text user;
#X obj 146 161 list trim;
#X obj 146 219 l2s;
#X obj 228 242 list trim;
#X obj 197 216 json-decode;
#X obj 228 288 l2s;
#X obj 228 265 route name screen_name;
#X obj 303 289 l2s;
#X obj 113 318 pack f s s s;
#X obj 84 36 inlet;
#X obj 113 347 outlet;
#X obj 64 347 outlet;
#X connect 0 0 15 0;
#X connect 0 1 1 0;
#X connect 1 0 2 0;
#X connect 2 0 3 0;
#X connect 3 0 12 0;
#X connect 3 1 5 0;
#X connect 4 0 6 0;
#X connect 4 1 8 0;
#X connect 5 0 4 0;
#X connect 6 0 12 1;
#X connect 7 0 10 0;
#X connect 8 1 7 0;
#X connect 9 0 12 2;
#X connect 10 0 9 0;
#X connect 10 1 11 0;
#X connect 11 0 12 3;
#X connect 12 0 14 0;
#X connect 13 0 0 0;
#X restore 42 153 pd data-tranformation;
#N canvas 984 503 403 299 name-analysis 0;
#X obj 112 54 loadbang;
#X msg 112 82 symbol;
#X obj 94 110 s2l;
#X obj 94 134 list length;
#X obj 94 159 / 32;
#X obj 58 55 inlet;
#X obj 94 201 outlet;
#X connect 0 0 1 0;
#X connect 1 0 2 1;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 4 0 6 0;
#X connect 5 0 2 0;
#X restore 180 398 pd name-analysis;
#N canvas 1389 500 399 209 username-analysis 0;
#X obj 74 13 loadbang;
#X msg 74 41 symbol;
#X obj 46 84 s2l;
#X obj 45 107 list length;
#X obj 45 137 / 5;
#X obj 14 13 inlet;
#X obj 45 166 outlet;
#X connect 0 0 1 0;
#X connect 1 0 2 1;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 4 0 6 0;
#X connect 5 0 2 0;
#X restore 335 405 pd username-analysis;
#X msg 117 85 GET /1.1/search/tweets.json?q=%23Puredata&count=15;
#X connect 0 1 20 0;
#X connect 1 0 0 0;
#X connect 3 0 15 0;
#X connect 3 1 11 0;
#X connect 4 0 3 0;
#X connect 5 0 9 0;
#X connect 6 0 17 0;
#X connect 7 0 6 0;
#X connect 9 0 8 0;
#X connect 9 0 8 1;
#X connect 10 0 9 1;
#X connect 11 0 5 1;
#X connect 14 0 5 1;
#X connect 15 1 13 0;
#X connect 15 1 19 0;
#X connect 15 2 12 0;
#X connect 15 2 21 0;
#X connect 15 3 16 0;
#X connect 15 3 22 0;
#X connect 17 0 5 0;
#X connect 18 0 17 1;
#X connect 19 0 7 0;
#X connect 19 1 14 0;
#X connect 19 2 11 0;
#X connect 19 3 4 0;
#X connect 20 0 4 0;
#X connect 20 1 3 0;
#X connect 21 0 14 0;
#X connect 22 0 18 0;
#X connect 23 0 0 0;
#X restore 375 261 pd sonify-it;
#X msg 228 56 init https://api.twitter.com SEJpJksCRpcgyoP4nk73Ng FEHGi9k8jF3zTPrBLbnBonF94gbUGZLrGKMgl4Td5bc
YOUR_AUTH_TOKEN YOUR_AUTH_SECRET;
#X obj 618 479 declare -path purest_json -stdlib zexy -stdpath cyclone
;
#X connect 3 0 1 0;
#X connect 3 0 2 0;

BIN
purest_json/json-decode.pd_linux Executable file

Binary file not shown.

BIN
purest_json/json-encode.pd_linux Executable file

Binary file not shown.

208
purest_json/json-help.pd Normal file
View File

@ -0,0 +1,208 @@
#N canvas 79 63 1064 678 10;
#X declare -path purest_json;
#X obj 565 357 json-encode;
#X obj 565 459 json-decode;
#X obj 6 161 json-encode;
#X obj 6 182 json-decode;
#X text 81 163 - encodes data into a JSON string.;
#X text 81 181 - decodes a JSON string to lists.;
#X msg 543 25 add id 1;
#X text 543 6 Will add key id and value of 1 to object;
#X text 585 57 This will add a string with the spaces intact to the JSON object, f 69;
#X msg 634 207 add id 2;
#X text 637 186 adding a different value will overwrite the previously stored one, f 68;
#X msg 488 284 clear;
#X text 390 260 This will clear the object;
#X text 694 222 output the value;
#X msg 694 241 bang;
#N canvas 85 61 536 476 nested-objects 0;
#X obj 76 244 json-encode;
#X obj 76 352 json-decode;
#X msg 76 197 bang;
#X obj 142 153 json-encode;
#X msg 142 199 add newest \$1;
#X obj 76 26 bng 15 250 50 0 empty empty Click_to_create_a_nested_object 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 76 56 t b b b;
#X obj 76 270 t a a;
#X obj 161 352 print JSON_string;
#X obj 76 432 print decoding_done;
#X obj 207 431 print decoded_pair;
#X obj 161 327 spigot;
#X obj 194 301 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X msg 254 199 add name Aphex Twin;
#X msg 142 119 add album Syro \, add year 2014 \, bang \,;
#X obj 207 407 spigot;
#X obj 240 381 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X connect 0 0 7 0;
#X connect 1 0 9 0;
#X connect 1 1 15 0;
#X connect 2 0 0 0;
#X connect 3 0 4 0;
#X connect 4 0 0 0;
#X connect 5 0 6 0;
#X connect 6 0 2 0;
#X connect 6 1 14 0;
#X connect 6 2 13 0;
#X connect 7 0 1 0;
#X connect 7 1 11 0;
#X connect 11 0 8 0;
#X connect 12 0 11 1;
#X connect 13 0 0 0;
#X connect 14 0 3 0;
#X connect 15 0 10 0;
#X connect 16 0 15 1;
#X restore 9 579 pd nested-objects;
#X obj 565 378 t a a;
#N canvas 312 61 801 648 about-decoded-json-strings 0;
#X obj 388 205 json-encode;
#X obj 164 334 json-decode;
#X msg 388 158 bang;
#X obj 388 8 bng 15 250 50 0 empty empty Click_to_create_an_object 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 388 38 t b b b b;
#X msg 439 74 add duration 3000;
#X obj 388 231 t a a a;
#X obj 407 333 json-decode;
#X obj 438 477 line;
#X floatatom 438 510 5 0 0 0 - - - 0;
#X msg 438 457 \$1 \, \$2 \$3;
#X obj 438 392 route start end duration;
#X text 419 312 wrong;
#X obj 227 492 line;
#X floatatom 227 525 5 0 0 0 - - - 0;
#X obj 227 391 route start end duration;
#X obj 227 362 list trim;
#X obj 438 363 list trim;
#X obj 438 435 pack 0 0 0;
#X msg 422 104 add start 100;
#X msg 405 135 add end 500;
#X obj 212 421 f;
#X obj 227 450 pack 0 0 0;
#X msg 227 472 \$1 \, \$2 \$3;
#X text 11 111 This will give you a chance to wait for other data from the JSON object.;
#X obj 473 303 print JSON_string;
#X text 175 299 correct;
#X text 11 13 You should not assume too much about the order of keys and values in a JSON object. In this example \, a JSON string is decoded to drive a [line] object from start to stop using [route] and [pack]. When using [pack] you should not feed the left-most inlet with data immediately \, but store a value \, e.g. in a [f] and bang the store \, with the left outlet of [json-decode].;
#X obj 473 278 spigot;
#X obj 506 252 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X connect 0 0 6 0;
#X connect 1 0 21 0;
#X connect 1 1 16 0;
#X connect 2 0 0 0;
#X connect 3 0 4 0;
#X connect 4 0 2 0;
#X connect 4 1 20 0;
#X connect 4 2 19 0;
#X connect 4 3 5 0;
#X connect 5 0 0 0;
#X connect 6 0 1 0;
#X connect 6 1 7 0;
#X connect 6 2 28 0;
#X connect 7 1 17 0;
#X connect 8 0 9 0;
#X connect 10 0 8 0;
#X connect 11 0 18 0;
#X connect 11 1 18 1;
#X connect 11 2 18 2;
#X connect 13 0 14 0;
#X connect 15 0 21 1;
#X connect 15 1 22 1;
#X connect 15 2 22 2;
#X connect 16 0 15 0;
#X connect 17 0 11 0;
#X connect 18 0 10 0;
#X connect 19 0 0 0;
#X connect 20 0 0 0;
#X connect 21 0 22 0;
#X connect 22 0 23 0;
#X connect 23 0 13 0;
#X connect 28 0 25 0;
#X connect 29 0 28 1;
#X restore 9 600 pd about-decoded-json-strings;
#N canvas 44 61 450 465 json-arrays 0;
#X obj 42 73 json-encode;
#X msg 42 33 clear \, array storage textfile \, array storage couchdb \, array storage array \, bang;
#X obj 42 179 json-decode;
#X obj 42 112 t a a;
#X text 49 11 This will construct a json array.;
#X obj 73 216 list trim;
#X obj 73 243 route storage;
#X obj 73 334 json-decode;
#X obj 73 271 t a a;
#X obj 132 180 print JSON_object_string;
#X obj 158 334 print JSON_array;
#X obj 136 370 print decoded;
#X obj 73 395 print array_member_done;
#X obj 158 304 spigot;
#X obj 191 278 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X obj 132 155 spigot;
#X obj 165 129 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X connect 0 0 3 0;
#X connect 1 0 0 0;
#X connect 2 1 5 0;
#X connect 3 0 2 0;
#X connect 3 1 15 0;
#X connect 5 0 6 0;
#X connect 6 0 8 0;
#X connect 7 0 12 0;
#X connect 7 1 11 0;
#X connect 8 0 7 0;
#X connect 8 1 13 0;
#X connect 13 0 10 0;
#X connect 14 0 13 1;
#X connect 15 0 9 0;
#X connect 16 0 15 1;
#X restore 9 622 pd json-arrays;
#X text 6 559 [json-decode] treats json arrays as a series of objects.;
#X obj 669 477 print JSON_string;
#X msg 699 284 write /tmp/test.json;
#X msg 704 325 read test.json;
#X text 698 267 write the content as JSON to a file;
#X text 703 308 read data from a JSON file;
#X text 6 202 [json-encode] has six methods: add \, array \, clear \, bang \, write and read.;
#X text 6 277 array adds a new value to an array.;
#X text 6 295 clear clears the internally stored object.;
#X text 6 313 bang outputs the stored object as a JSON string.;
#X text 6 233 add adds a new key/value pair to the internally stored object. If you call add with a value that is already a JSON string \, then the object will be added as a nested object.;
#X text 6 331 read reads JSON data from a file. This file must contain exactly one JSON object \, as [json-encode] only stores one object internally.;
#X text 6 375 write writes the internally stored data as JSON to a file.;
#X obj 264 394 qlist;
#X text 6 393 add \, read and write methods work analog to;
#X obj 468 587 print decoding_done;
#X obj 596 587 print decoded_data;
#X obj 719 587 print not-a-json-object;
#X msg 449 417 no json;
#X text 6 411 [json-decode] will accept a JSON string at its input and will output the decoded object as a series of lists of key/value pairs on the middle outlet. Boolean values of TRUE/FALSE will be translated to 1 or 0 \, float and integer values will be output as floats. Nested objects and arrays are output as strings \, that can be parsed. After the object is fully parsed \, the left outlet will issue a bang \, so that you can differenciate between subsequent objects. The messages will come as list key value. If the string cannot be decoded as JSON \, then the right outlet will output a bang.;
#X obj 9 648 declare -path purest_json;
#X obj 596 564 spigot;
#X obj 629 542 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X obj 669 456 spigot;
#X obj 702 433 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X text 6 6 WARNING: [Print]ing JSON values to console may lead to undesired behaviour \, because it usually contains special characters such as curly braces \, backslashes \, or quotation marks that may be interpreted as tcl commands and therefore break the console or even crash Pd.;
#X text 6 76 To mitigate that \, set the [spigot]s only to 1 \, if running Pd with the command line switch -stderr \, that will direct the output to the command line instead of the Pd console.;
#X obj 409 641 text define \$0-example;
#X obj 659 409 text insert \$0-example;
#X text 6 117 Another strategy can be to use [text] for storing data for inspection.;
#X msg 588 77 add name Aphex Twin;
#X msg 614 107 add album drukqs;
#X msg 634 155 add year 2001;
#X connect 0 0 16 0;
#X connect 1 0 34 0;
#X connect 1 1 40 0;
#X connect 1 2 36 0;
#X connect 6 0 0 0;
#X connect 9 0 0 0;
#X connect 11 0 0 0;
#X connect 14 0 0 0;
#X connect 16 0 1 0;
#X connect 16 1 42 0;
#X connect 16 1 47 0;
#X connect 21 0 0 0;
#X connect 22 0 0 0;
#X connect 37 0 1 0;
#X connect 40 0 35 0;
#X connect 41 0 40 1;
#X connect 42 0 20 0;
#X connect 43 0 42 1;
#X connect 49 0 0 0;
#X connect 50 0 0 0;
#X connect 51 0 0 0;

BIN
purest_json/libasn1.so.8 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
purest_json/libcrypt.so.1 Normal file

Binary file not shown.

Binary file not shown.

BIN
purest_json/libcurl.so.4 Normal file

Binary file not shown.

BIN
purest_json/libgssapi.so.3 Normal file

Binary file not shown.

Binary file not shown.

BIN
purest_json/libhcrypto.so.4 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
purest_json/libhx509.so.5 Normal file

Binary file not shown.

BIN
purest_json/libjson-c.so.4 Normal file

Binary file not shown.

Binary file not shown.

BIN
purest_json/libkrb5.so.26 Normal file

Binary file not shown.

BIN
purest_json/libkrb5.so.3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
purest_json/libnettle.so.7 Normal file

Binary file not shown.

Binary file not shown.

BIN
purest_json/libnspr4.so Normal file

Binary file not shown.

BIN
purest_json/libnss3.so Normal file

Binary file not shown.

BIN
purest_json/libnssutil3.so Normal file

Binary file not shown.

BIN
purest_json/liboauth.so.0 Normal file

Binary file not shown.

BIN
purest_json/libplc4.so Normal file

Binary file not shown.

BIN
purest_json/libplds4.so Normal file

Binary file not shown.

BIN
purest_json/libpsl.so.5 Normal file

Binary file not shown.

BIN
purest_json/libroken.so.18 Normal file

Binary file not shown.

BIN
purest_json/libsasl2.so.2 Normal file

Binary file not shown.

BIN
purest_json/libsqlite3.so.0 Normal file

Binary file not shown.

BIN
purest_json/libssh.so.4 Normal file

Binary file not shown.

BIN
purest_json/libwind.so.0 Normal file

Binary file not shown.

View File

@ -0,0 +1,248 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
Basic Usage
</title>
<style>
/* Page tweaks */
.preview-page {
margin-top: 64px;
margin-bottom: 21px;
}
/* User-content tweaks */
.timeline-comment-wrapper > .timeline-comment:after,
.timeline-comment-wrapper > .timeline-comment:before {
content: none;
}
/* User-content overrides */
.discussion-timeline.wide {
width: 920px;
}
</style>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
<div class="preview-page" data-autorefresh-url="" id="preview-page">
<main id="js-repo-pjax-container">
<div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5">
<div class="repository-content">
<div class="clearfix">
<div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end">
<div class="Layout-main">
<div class="Box md Box--responsive" id="readme">
<div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2">
<div class="d-flex flex-items-center">
<h2 class="Box-title">
Basic Usage
</h2>
</div>
</div>
<div class="Box-body px-5 pb-5">
<article class="markdown-body entry-content container-lg" id="grip-content">
<p>
The following examples are in the patch
<code>
examples/purest-json-test.pd
</code>
.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#querying-webservices" id="user-content-querying-webservices">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Querying Webservices
</h2>
<p>
You can use
<code>
[rest]
</code>
to query webservices. I will explain this querying the history of the Makefile in the repository. You will see the handling of arrays in this example.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="Webservice Example" src="webservice-example.png" style="max-width: 100%;"/>
</a>
</p>
<p>
As you can see, the webservice from Github returns an object with only one array. This array is then parsed by an instance of
<code>
[json-decode]
</code>
.
</p>
<p>
<code>
data: symbol [{"sha":"c505f1bbc72a73ceff447686db4c3c33f3bf3488"\,"node_id":"C_kwDOACK909oAKGM1MDVmMWJiYzcyYTczY2VmZjQ0NzY4NmRiNGMzYzMzZjNiZjM0ODg"\,"commit":{"author":{"name":"Thomas\ Mayer"\,"email":"thomas@residuum.org"\,"date":"2022-05-06T00:31:32Z"}\,"committer":{"name":"Thomas\ Mayer"\,"email":"thomas@residuum.org"\,"date":"2022-05-06T00:31:32Z"}\,"message":"Replace\ [import]\ with\ [declare]\ in\ examples.\\n\\nFixes\ #61"\,"tree":{"sha":"1a3c399407bb25f3976166e13f996b930df3b531"\,"url":"https://api.github.com/repos/residuum/PuRestJson/git/trees/1a3c399407bb25f3976166e13f996b930df3b531"}\,"url":"https://api.github.com/repos/residuum/PuRestJson/git/commits/c505f1bbc72a73ceff447686db4c3c33f3bf3488"\,"comment_count":0\,"verification":{"verified":false\,"reason":"unsigned"\,"signature":null\,"payload":null}}\,"url":"https://api.github.com/repos/residuum/PuRestJson/commits/c505f1bbc72a73ceff447686db4c3c33f3bf3488"\,"html_url":"https://github.com/residuum/PuRestJson/commit/c505f1bbc72a73ceff4476
</code>
</p>
<p>
Each array member is then parsed individually by
<code>
[json-decode]
</code>
, i.e. each member of the object is then output as list on the middle outlet, followed by a bang on the left outlet.
</p>
<pre><code>array-decoded: sha c505f1bbc72a73ceff447686db4c3c33f3bf3488
array-decoded: node_id C_kwDOACK909oAKGM1MDVmMWJiYzcyYTczY2VmZjQ0NzY4NmRiNGMzYzMzZjNiZjM0ODg
array-decoded: commit {\ "author":\ {\ "name":\ "Thomas\ Mayer"\,\ "email":\ "thomas@residuum.org"\,\ "date":\ "2022-05-06T00:31:32Z"\ }\,\ "committer":\ {\ "name":\ "Thomas\ Mayer"\,\ "email":\ "thomas@residuum.org"\,\ "date":\ "2022-05-06T00:31:32Z"\ }\,\ "message":\ "Replace\ [import]\ with\ [declare]\ in\ examples.\\n\\nFixes\ #61"\,\ "tree":\ {\ "sha":\ "1a3c399407bb25f3976166e13f996b930df3b531"\,\ "url":\ "https:\\/\\/api.github.com\\/repos\\/residuum\\/PuRestJson\\/git\\/trees\\/1a3c399407bb25f3976166e13f996b930df3b531"\ }\,\ "url":\ "https:\\/\\/api.github.com\\/repos\\/residuum\\/PuRestJson\\/git\\/commits\\/c505f1bbc72a73ceff447686db4c3c33f3bf3488"\,\ "comment_count":\ 0\,\ "verification":\ {\ "verified":\ false\,\ "reason":\ "unsigned"\,\ "signature":\ null\,\ "payload":\ null\ }\ }
array-decoded: url https://api.github.com/repos/residuum/PuRestJson/commits/c505f1bbc72a73ceff447686db4c3c33f3bf3488
array-decoded: html_url https://github.com/residuum/PuRestJson/commit/c505f1bbc72a73ceff447686db4c3c33f3bf3488
array-decoded: comments_url https://api.github.com/repos/residuum/PuRestJson/commits/c505f1bbc72a73ceff447686db4c3c33f3bf3488/comments
array-decoded: author {\ "login":\ "residuum"\,\ "id":\ 136216\,\ "node_id":\ "MDQ6VXNlcjEzNjIxNg=="\,\ "avatar_url":\ "https:\\/\\/avatars.githubusercontent.com\\/u\\/136216?v=4"\,\ "gravatar_id":\ ""\,\ "url":\ "https:\\/\\/api.github.com\\/users\\/residuum"\,\ "html_url":\ "https:\\/\\/github.com\\/residuum"\,\ "followers_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/followers"\,\ "following_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/following{\\/other_user}"\,\ "gists_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/gists{\\/gist_id}"\,\ "starred_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/starred{\\/owner}{\\/repo}"\,\ "subscriptions_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/subscriptions"\,\ "organizations_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/orgs"\,\ "repos_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/repos"\,\ "events_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/events{\\/privacy}"\,\ "received_events
array-decoded: committer {\ "login":\ "residuum"\,\ "id":\ 136216\,\ "node_id":\ "MDQ6VXNlcjEzNjIxNg=="\,\ "avatar_url":\ "https:\\/\\/avatars.githubusercontent.com\\/u\\/136216?v=4"\,\ "gravatar_id":\ ""\,\ "url":\ "https:\\/\\/api.github.com\\/users\\/residuum"\,\ "html_url":\ "https:\\/\\/github.com\\/residuum"\,\ "followers_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/followers"\,\ "following_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/following{\\/other_user}"\,\ "gists_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/gists{\\/gist_id}"\,\ "starred_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/starred{\\/owner}{\\/repo}"\,\ "subscriptions_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/subscriptions"\,\ "organizations_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/orgs"\,\ "repos_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/repos"\,\ "events_url":\ "https:\\/\\/api.github.com\\/users\\/residuum\\/events{\\/privacy}"\,\ "received_events
array-decoded: parents [\ {\ "sha":\ "b1c602e3d73a9088e951181bea0a500e49223c8e"\,\ "url":\ "https:\\/\\/api.github.com\\/repos\\/residuum\\/PuRestJson\\/commits\\/b1c602e3d73a9088e951181bea0a500e49223c8e"\,\ "html_url":\ "https:\\/\\/github.com\\/residuum\\/PuRestJson\\/commit\\/b1c602e3d73a9088e951181bea0a500e49223c8e"\ }\ ]
array-done: bang
...
</code></pre>
<h2>
<a aria-hidden="true" class="anchor" href="#using-couchdb" id="user-content-using-couchdb">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Using CouchDB
</h2>
<p>
This example will show the usage of diverse HTTP request methods, GET, PUT, and DELETE. You will also see, how you can add data to PUT requests.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="CouchDB Example" src="couchdb-example.png" style="max-width: 100%;"/>
</a>
</p>
<p>
A CouchDB running on the same computer is implied.
</p>
<p>
Here is the output from the main example in examples/purest-json-test.pd with explanations.
</p>
<p>
First, we create the database and get info about the database:
</p>
<pre><code>couchdb return: list ok 1
couchdb return: list db_name test
couchdb return: list doc_count 0
couchdb return: list doc_del_count 0
couchdb return: list update_seq 0
couchdb return: list purge_seq 0
couchdb return: list compact_running 0
couchdb return: list disk_size 79
couchdb return: list instance_start_time 1.31733e+15
couchdb return: list disk_format_version 5
couchdb return: list committed_update_seq 0
</code></pre>
<p>
After that, we build a JSON document and store it in the database:
</p>
<pre><code>json-encoded data: symbol \{ "value": "440"\\, "duration": "1000"\\, "start": "10"\\, "name": "first note"\\, "var": [ "yabba"\\, "dabba"\\, "doo" ]\\, "on": "TRUE" \}
decode json data: list value 440
decode json data: list duration 1000
decode json data: list start 10
decode json data: list name first note
decode json data: list var [ "yabba"\\, "dabba"\\, "doo" ]
decode json data: list on 1
couchdb return: list ok 1
couchdb return: list id 1
couchdb return: list rev 1-b7a3cb13c20812a4c7845e9a86f92099`
</code></pre>
<p>
Then we query the database for the stored document and use it to drive a simple ramp:
</p>
<pre><code>id: 1
couchdb return: list _id 1
couchdb return: list _rev 1-b7a3cb13c20812a4c7845e9a86f92099
couchdb return: list value 440
couchdb return: list duration 1000
couchdb return: list start 10
name: first note
couchdb return: list name first note
couchdb return: list var [ "yabba"\\, "dabba"\\, "doo" ]
couchdb return: list on 1
</code></pre>
<p>
In the end we delete the database:
</p>
<pre><code>couchdb return: list ok 1
</code></pre>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
function showCanonicalImages() {
var images = document.getElementsByTagName('img');
if (!images) {
return;
}
for (var index = 0; index < images.length; index++) {
var image = images[index];
if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) {
image.src = image.getAttribute('data-canonical-src');
}
}
}
function scrollToHash() {
if (location.hash && !document.querySelector(':target')) {
var element = document.getElementById('user-content-' + location.hash.slice(1));
if (element) {
element.scrollIntoView();
}
}
}
function autorefreshContent(eventSourceUrl) {
var initialTitle = document.title;
var contentElement = document.getElementById('grip-content');
var source = new EventSource(eventSourceUrl);
var isRendering = false;
source.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if (msg.updating) {
isRendering = true;
document.title = '(Rendering) ' + document.title;
} else {
isRendering = false;
document.title = initialTitle;
contentElement.innerHTML = msg.content;
showCanonicalImages();
}
}
source.onerror = function(e) {
if (e.readyState === EventSource.CLOSED && isRendering) {
isRendering = false;
document.title = initialTitle;
}
}
}
window.onhashchange = function() {
scrollToHash();
}
window.onload = function() {
scrollToHash();
}
showCanonicalImages();
var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url');
if (autorefreshUrl) {
autorefreshContent(autorefreshUrl);
}
</script>
</body>
</html>

View File

@ -0,0 +1,496 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
Compilation
</title>
<style>
/* Page tweaks */
.preview-page {
margin-top: 64px;
margin-bottom: 21px;
}
/* User-content tweaks */
.timeline-comment-wrapper > .timeline-comment:after,
.timeline-comment-wrapper > .timeline-comment:before {
content: none;
}
/* User-content overrides */
.discussion-timeline.wide {
width: 920px;
}
</style>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
<div class="preview-page" data-autorefresh-url="" id="preview-page">
<main id="js-repo-pjax-container">
<div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5">
<div class="repository-content">
<div class="clearfix">
<div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end">
<div class="Layout-main">
<div class="Box md Box--responsive" id="readme">
<div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2">
<div class="d-flex flex-items-center">
<h2 class="Box-title">
Compilation
</h2>
</div>
</div>
<div class="Box-body px-5 pb-5">
<article class="markdown-body entry-content container-lg" id="grip-content">
<p>
Compilation should be working on Linux, Windows with MinGW and Mac OS X. You will need header files of Puredata, as well as
<a href="http://curl.haxx.se/" rel="nofollow">
libcurl
</a>
,
<a href="https://github.com/json-c/json-c">
json-c
</a>
, and
<a href="http://liboauth.sourceforge.net/" rel="nofollow">
liboauth
</a>
.
</p>
<p>
The package build script uses the Makefile template from
<a href="https://github.com/pure-data/pd-lib-builder">
pd-lib-builder
</a>
.
</p>
<p>
To enable multi-instance support, add
<code>
multi=true
</code>
to the make command.
</p>
<p>
If you have gotten the source code from git, you will first have to init the
<a href="http://troydhanson.github.io/uthash/" rel="nofollow">
uthash
</a>
and pd-lib-builder submodule by running
<code>
git submodule update --init
</code>
.
</p>
<p>
OS X and Linux build scripts do not include dependencies in the resulting pd_linux or pd_darwin files. For making a distributable version of the library, there is a collection of bash scripts for the different platforms.
</p>
<p>
The manual is generated from the
<a href="https://github.com/residuum/PuRestJson/wiki">
Github wiki
</a>
. To generate it as well, a copy of the wiki is necessary (get it via
<code>
git clone https://github.com/residuum/PuRestJson.wiki.git
</code>
). The python script is called
<code>
create_manual.py
</code>
and needs
<a href="https://github.com/joeyespo/grip">
grip
</a>
and
<a href="https://pypi.python.org/pypi/BeautifulSoup" rel="nofollow">
BeautifulSoup
</a>
. Install those via
<code>
pip install grip beautifulsoup lxml
</code>
.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#circle-ci-builds---general-information" id="user-content-circle-ci-builds---general-information">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Circle CI Builds - General Information
</h2>
<p>
PuREST JSON is configured to build on
<a href="https://app.circleci.com/pipelines/github/residuum/PuRestJson" rel="nofollow">
Circle CI
</a>
. The bash scripts in the folder
<code>
circleci-scripts
</code>
may serve as secondary documentation for building:
</p>
<ul>
<li>
<code>
*/before_install.sh
</code>
sets up the build environment
</li>
<li>
<code>
*/script.sh
</code>
is the command to build the binaries
</li>
<li>
<code>
*/pack.sh
</code>
generates the manual and creates deken packages
</li>
<li>
<code>
upload.sh
</code>
uploads the resulting package to my personal ownCloud instance
</li>
</ul>
<h2>
<a aria-hidden="true" class="anchor" href="#linux" id="user-content-linux">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Linux
</h2>
<p>
As a guideline, look at the scripts in the
<code>
circleci-scripts/linux-amd64
</code>
folder, as the scripts in forder
<code>
linux-i386
</code>
are used to build 32 bit i386 packages on a 64 bit amd64 system.
</p>
<ol>
<li>
You need build-essentials, header files for puredata, libjson-c, libcurl4, liboauth. If you have Debian or a derivative (e.g. Ubuntu, Linux Mint), you can install the build utils and needed headers with
<code>
apt-get install build-essential puredata-dev libjson-c-dev libcurl4-openssl-dev liboauth-dev
</code>
. If you are not root, prefix the command with
<code>
sudo
</code>
.
</li>
<li>
Drop the sources in a directory and run
<code>
make
</code>
. You will get files with a suffix of pd_linux for each object (json-decode.pd_linux, json-encode.pd_linux, rest.pd_linux, oauth.pd_linux). These are needed to use the library.
</li>
<li>
(optional) To create a distributable version, you have to install patchelf, e.g.
<code>
apt-get install patchelf
</code>
. Run
<code>
bash dependencies/linux.sh *.pdlinux
</code>
. This will copy dependencies to the current folder and rewrite linking information in the files to point to these dependencies.
</li>
</ol>
<h3>
<a aria-hidden="true" class="anchor" href="#building-for-different-architectures" id="user-content-building-for-different-architectures">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Building for Different Architectures
</h3>
<p>
Building for different architectures is possible. I will outline a way to do it on Debian based systems, e.g. Ubuntu.
</p>
<ol>
<li>
Install debootstrap, e.g. via
<code>
apt-get install debootstrap
</code>
.
</li>
<li>
Set up a directory as the root for your new chroot, e.g. for
<code>
/tmp/buildroot
</code>
on Ubuntu Trusty for i386 with
</li>
</ol>
<pre><code> sudo debootstrap \
--variant=buildd \
--include=build-essential \
--arch=i386 \
trusty /tmp/buildroot http://archive.ubuntu.com/ubuntu/
</code></pre>
<ol start="3">
<li>
Install the basic build system in that directory, and install the necessary dependencies for that architecture e.g. with
</li>
</ol>
<pre><code> echo deb http://archive.ubuntu.com/ubuntu/ \
$DIST restricted universe multiverse \
| sudo tee -a /tmp/buildroot/etc/apt/sources.list
sudo chroot /tmp/buildroot bash -c "apt-get update"
sudo chroot /tmp/buildroot bash -c "apt-get install -qq -y build-essential \
puredata-dev libjson-c-dev libcurl4-nss-dev liboauth-dev"
</code></pre>
<ol start="4">
<li>
Copy the files to a subfolder in the chroot folder, e.g.
<code>
/tmp/buildroot/PuRestJson
</code>
</li>
<li>
Run
<code>
make
</code>
via chroot:
</li>
</ol>
<pre><code> sudo chroot /tmp/buildroot bash -c "cd PuRestJson &amp;&amp; make"
</code></pre>
<ol start="6">
<li>
(optional) To create a distributable version, you have to install patchelf, e.g.
<code>
sudo chroot /tmp/buildroot bash -c "apt-get install patchelf"
</code>
. Run
<code>
sudo chroot ${CHROOTDIR} bash -c "cd PuRestJson &amp;&amp; bash ./dependencies/linux.sh *.pd_linux"
</code>
. This will copy dependencies to the /tmp/buildroot and rewrite linking information in the files to point to these dependencies.
</li>
</ol>
<h2>
<a aria-hidden="true" class="anchor" href="#windows-with-mingw" id="user-content-windows-with-mingw">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Windows with MinGW
</h2>
<p>
This is possible, but I have given up on it, and only cross-compile the library with MXE.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#compilation-on-mac-os-x" id="user-content-compilation-on-mac-os-x">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Compilation on Mac OS X
</h2>
<p>
As a guideline, look at the scripts in the
<code>
circleci-scripts/osx
</code>
folder.
</p>
<ol>
<li>
Install
<a href="https://developer.apple.com/xcode/" rel="nofollow">
XCode
</a>
, and
<a href="http://stackoverflow.com/a/9353468/124983" rel="nofollow">
install the command line tools
</a>
to get
<code>
gcc
</code>
and
<code>
otool
</code>
.
</li>
<li>
Install
<a href="http://brew.sh/" rel="nofollow">
Homebrew
</a>
to later install the dependencies.
</li>
<li>
Install dependencies via Homebrew:
</li>
</ol>
<pre><code> brew update
brew install json-c curl liboauth --universal
</code></pre>
<ol start="4">
<li>
Find the path to Pd.
</li>
<li>
Drop the sources in a directory and run
<code>
make pdincludepath=/path/to/pd/Contents/Resources/src
</code>
</li>
<li>
(optional) You are now able to use the library on a machine, if the dependencies are installed via Homebrew. To move the necessary dylibs to the current directory and change the links of the pd_darwin files, run
<code>
./dependencies/osx.sh
</code>
. This makes the whole folder distributable.
</li>
</ol>
<h2>
<a aria-hidden="true" class="anchor" href="#cross-compilation-for-windows-on-unix-like-systems-linux--bsd--mac-os-x-with-mxe" id="user-content-cross-compilation-for-windows-on-unix-like-systems-linux--bsd--mac-os-x-with-mxe">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Cross-compilation for Windows on UNIX-like systems (Linux / *BSD / Mac OS X) with MXE
</h2>
<p>
As a guideline, look at the scripts in the
<code>
circleci-scripts/windows32
</code>
folder.
</p>
<ol>
<li>
Get the development version of MXE from
<a href="https://github.com/mxe/mxe">
their Github repository
</a>
and setup MXE, so that the cross compilation tools are in your PATH environmental variable.
</li>
<li>
Build the required libraries by running
<code>
make curl json-c liboauth pthreads
</code>
.
</li>
<li>
Download the Windows version of Pd and unzip it in a folder. You should have the following structure of files:
</li>
</ol>
<pre><code> pd/src/(source files including m_pd.h)
pd/bin/pd.dll
</code></pre>
<ol start="4">
<li>
Run
<code>
make
</code>
with some environmental variables to tell the compiler to use the cross compiler, and where to find the Pd source and pd.dll. Here is an example from my setup:
</li>
</ol>
<pre><code> #!/bin/bash
MXE_DIR=/usr/lib/mxe
MXE_GCC=${MXE_DIR}/usr/bin/i686-w64-mingw32.static-gcc
PD_DIR=/tmp/pd
make \
system=Windows \
machine=i386 \
uname=MINGW \
pdincludepath=${PD_DIR}/src \
pdbinpath=${PD_DIR}/bin \
CC=${MXE_GCC} \
arch.c.flags='-march=pentium4 -msse -msse2 -mfpmath=sse -I \
"/usr/lib/mxe/usr/i686-w64-mingw32.static/include"' \
ldflags='-L "/usr/lib/mxe/usr/i686-w64-mingw32.static/lib"'
</code></pre>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
function showCanonicalImages() {
var images = document.getElementsByTagName('img');
if (!images) {
return;
}
for (var index = 0; index < images.length; index++) {
var image = images[index];
if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) {
image.src = image.getAttribute('data-canonical-src');
}
}
}
function scrollToHash() {
if (location.hash && !document.querySelector(':target')) {
var element = document.getElementById('user-content-' + location.hash.slice(1));
if (element) {
element.scrollIntoView();
}
}
}
function autorefreshContent(eventSourceUrl) {
var initialTitle = document.title;
var contentElement = document.getElementById('grip-content');
var source = new EventSource(eventSourceUrl);
var isRendering = false;
source.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if (msg.updating) {
isRendering = true;
document.title = '(Rendering) ' + document.title;
} else {
isRendering = false;
document.title = initialTitle;
contentElement.innerHTML = msg.content;
showCanonicalImages();
}
}
source.onerror = function(e) {
if (e.readyState === EventSource.CLOSED && isRendering) {
isRendering = false;
document.title = initialTitle;
}
}
}
window.onhashchange = function() {
scrollToHash();
}
window.onload = function() {
scrollToHash();
}
showCanonicalImages();
var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url');
if (autorefreshUrl) {
autorefreshContent(autorefreshUrl);
}
</script>
</body>
</html>

View File

@ -0,0 +1,844 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
Contributing and Code Documentation
</title>
<style>
/* Page tweaks */
.preview-page {
margin-top: 64px;
margin-bottom: 21px;
}
/* User-content tweaks */
.timeline-comment-wrapper > .timeline-comment:after,
.timeline-comment-wrapper > .timeline-comment:before {
content: none;
}
/* User-content overrides */
.discussion-timeline.wide {
width: 920px;
}
</style>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
<div class="preview-page" data-autorefresh-url="" id="preview-page">
<main id="js-repo-pjax-container">
<div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5">
<div class="repository-content">
<div class="clearfix">
<div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end">
<div class="Layout-main">
<div class="Box md Box--responsive" id="readme">
<div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2">
<div class="d-flex flex-items-center">
<h2 class="Box-title">
Contributing and Code Documentation
</h2>
</div>
</div>
<div class="Box-body px-5 pb-5">
<article class="markdown-body entry-content container-lg" id="grip-content">
<p>
If you want to contribute to the development of the software, every help is much appreciated.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#bugs-and-wishes" id="user-content-bugs-and-wishes">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Bugs And Wishes
</h2>
<p>
If you found any bugs in the software or would like a feature implemented, please open a new issue on
<a href="https://github.com/residuum/PuRestJson/issues">
the bug tracker
</a>
or send an email to
<a href="mailto:purest-json-bugs@ix.residuum.org">
purest-json-bugs@ix.residuum.org
</a>
.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#development" id="user-content-development">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Development
</h2>
<p>
Feel free to fork the project and submit pull requests, if you want to implement some features or fix some bugs. If possible, please open a new issue on
<a href="https://github.com/residuum/PuRestJson/issues">
the bug tracker
</a>
, so that noone else tries to fix or implement the same issue.
</p>
<p>
If you need some help with writing externals for Pd, read the
<a href="http://iem.at/pd/externals-HOWTO/" rel="nofollow">
excellent how-to on that subject
</a>
.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#code-structure" id="user-content-code-structure">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Code structure
</h3>
<p>
The whole project in written in C99. C code is in subfolder
<code>
src/
</code>
. Every object and the library itself has a .c and a corresponding .h file.
<code>
purest_json.c
</code>
is only used to setup the library.
<code>
#define
</code>
s are done only in the .h files.
<code>
purest_json.h
</code>
is
<code>
#include
</code>
d in all objects.
</p>
<p>
Every object contains functions with a structure of
<code>
&lt;OBJECT&gt;_&lt;FUNCTION&gt;
</code>
with the exception of setup functions. Only functions that Pd needs to call are exported, and only exported functions are declared in the .h file, all other functions are static.
</p>
<p>
Shared functions used by more than one object are in directory
<code>
src/inc
</code>
. The functions are prefixed with the name of the file, e.g.
<code>
ctw.c
</code>
includes functions named
<code>
ctw_&lt;FUNCTION&gt;
</code>
.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#order-of-functions-and-declarations-in-c-files" id="user-content-order-of-functions-and-declarations-in-c-files">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Order of Functions And Declarations in .c Files
</h3>
<ol>
<li>
<code>
#include
</code>
s
</li>
<li>
<code>
t_class
</code>
declaration
</li>
<li>
<code>
struct
</code>
declarations
</li>
<li>
prototypes for static functions
</li>
<li>
implementation of static functions
</li>
<li>
setup functions
</li>
<li>
functions reacting to messages
</li>
<li>
constructor function
</li>
<li>
destructor function
</li>
</ol>
<h3>
<a aria-hidden="true" class="anchor" href="#names-of-setup-functions" id="user-content-names-of-setup-functions">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Names of Setup Functions
</h3>
<p>
When Pd tries to load an object, it is looking for the file with the correct platform specific suffix (.pd_linux, .pd_darwin, .dll, .pd_freebsd) and the same name, e.g. to create
<code>
[json-encode]
</code>
, Pd on Windows looks for a file
<code>
json-encode.dll
</code>
.
</p>
<p>
In this library file, Pd looks for a setup function according, depending on the name of the object:
</p>
<ul>
<li>
If the name contains a special character, that cannot be used in a C symbol (
<code>
-
</code>
,
<code>
~
</code>
,
<code>
.
</code>
, etc.), then this special character is converted to a hex representation using
<code>
sprintf(symname+i, "0x%02x", c);
</code>
where
<code>
c
</code>
is the special character. This resulting name is prefixed by
<code>
setup_
</code>
. So the function for creating
<code>
[json-encode]
</code>
must be called
<code>
setup_json0x2dencode
</code>
.
</li>
<li>
If the name can be converted to a C symbol, then the setup function must be the object name suffixed with
<code>
_setup
</code>
. So the function for creating
<code>
[urlparams]
</code>
must be called
<code>
urlparams_setup
</code>
.
</li>
</ul>
<h3>
<a aria-hidden="true" class="anchor" href="#names-of-other-exported-functions" id="user-content-names-of-other-exported-functions">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Names of Other Exported Functions
</h3>
<p>
If an object has a hyphen (
<code>
-
</code>
) in its name, then this is replaced by an underscore (
<code>
_
</code>
)
</p>
<ul>
<li>
Creation functions:
<code>
&lt;OBJECT&gt;_new
</code>
, e.g.
<code>
rest_new
</code>
.
</li>
<li>
Destruction functions:
<code>
&lt;OBJECT&gt;_free
</code>
, e.g.
<code>
rest_free
</code>
. Not every object needs to clean up on destruction, do not create this function then.
</li>
<li>
Generic message functions: If the function should be called based on the type of content, then the corresponding function is
<code>
&lt;OBJECT&gt;_&lt;TYPE&gt;
</code>
, e.g.
<code>
json_decode_symbol
</code>
,
<code>
json_encode_bang
</code>
.
</li>
<li>
HTTP request messages
<code>
[GET(
</code>
,
<code>
[POST(
</code>
,
<code>
[PUT(
</code>
,
<code>
[DELETE(
</code>
,
<code>
[HEAD(
</code>
,
<code>
[PATCH(
</code>
,
<code>
[TRACE(
</code>
, and
<code>
[OPTIONS(
</code>
:
<code>
&lt;OBJECT&gt;_command
</code>
, e.g.
<code>
[GET(
</code>
on
<code>
[rest]
</code>
calls
<code>
rest_command
</code>
.
</li>
<li>
Message functions: Every
<code>
[MESSAGE(
</code>
for the object has a corresponding function
<code>
&lt;OBJECT&gt;_&lt;MESSAGE&gt;
</code>
, e.g.
<code>
[cancel(
</code>
on
<code>
[oauth]
</code>
calls the function
<code>
oauth_cancel
</code>
.
</li>
</ul>
<h3>
<a aria-hidden="true" class="anchor" href="#names-of-static-functions" id="user-content-names-of-static-functions">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Names of Static Functions
</h3>
<p>
Static functions are prefixed with the name of the corresponding file without the .c extension, and an underscore. Function prototypes are declared in .c files before implemtations. Sometimes, the object names are abbreviated:
</p>
<ul>
<li>
<code>
json-decode.c
</code>
=&gt;
<code>
jdec_
</code>
</li>
<li>
<code>
json-encode.c
</code>
=&gt;
<code>
jenc_
</code>
</li>
<li>
<code>
oauth.c
</code>
=&gt;
<code>
oauth_
</code>
</li>
<li>
<code>
rest.c
</code>
=&gt;
<code>
rest_
</code>
</li>
<li>
<code>
urlparams.c
</code>
=&gt;
<code>
urlp_
</code>
</li>
</ul>
<h3>
<a aria-hidden="true" class="anchor" href="#content-of-included-files" id="user-content-content-of-included-files">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Content of Included Files
</h3>
<p>
All .c files that do not have a matching .h file contain only static functions and are
<code>
#include
</code>
d in files defining the objects. These source files are in subfolder
<code>
src/inc/
</code>
. They have the following properties:
</p>
<h4>
<a aria-hidden="true" class="anchor" href="#ctwc" id="user-content-ctwc">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
ctw.c
</h4>
<p>
ctw is short for
<strong>
c
</strong>
url
<strong>
t
</strong>
hread
<strong>
w
</strong>
rapper. As the name suggests, it contain functions for using threading for making requests with libcurl.
</p>
<p>
This file is used in
<code>
[oauth]
</code>
and
<code>
[rest]
</code>
. In both objects, a
<code>
struct _ctw
</code>
is the first member, so that casting is possible.
</p>
<p>
All functions are prefixed with
<code>
ctw_
</code>
.
</p>
<h4>
<a aria-hidden="true" class="anchor" href="#kvpc" id="user-content-kvpc">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
kvp.c
</h4>
<p>
kvp is short for
<strong>
k
</strong>
ey
<strong>
v
</strong>
alue
<strong>
p
</strong>
air. Three structs are defined in this file,
<code>
struct _v
</code>
,
<code>
struct _kvp
</code>
, and
<code>
struct _kvp_store
</code>
.
<code>
struct _kvp
</code>
is a key value pair, while
<code>
struct _kvp_store
</code>
includes a hash table of key value pair.
<code>
struct _v
</code>
is a value, containing a union of
<code>
t_float
</code>
,
<code>
char *
</code>
and
<code>
int
</code>
to distinguish between floats, strings and integers for JSON.
</p>
<p>
This file is used in
<code>
[json-encode]
</code>
and
<code>
[urlparams]
</code>
. In both objects, a
<code>
struct _kvp_store
</code>
is the first member, so that casting is possible.
</p>
<p>
All functions are prefixed with
<code>
kvp_
</code>
.
</p>
<h4>
<a aria-hidden="true" class="anchor" href="#stringc" id="user-content-stringc">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
string.c
</h4>
<p>
Utility functions for creating and freeing memory for
<code>
char *
</code>
and the corresponding
<code>
size_t
</code>
.
</p>
<p>
This file is used in
<code>
[json-decode]
</code>
,
<code>
[json-encode]
</code>
,
<code>
[oauth]
</code>
,
<code>
[rest]
</code>
, and
<code>
[urlparams]
</code>
.
</p>
<p>
All functions are prefixed with
<code>
string_
</code>
.
</p>
<h4>
<a aria-hidden="true" class="anchor" href="#strlistc" id="user-content-strlistc">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
strlist.c
</h4>
<p>
Utility functions for creating and freeing memory for a linked list of
<code>
char *
</code>
and the corresponding
<code>
size_t
</code>
.
</p>
<p>
This file is used in
<code>
[oauth]
</code>
and
<code>
[rest]
</code>
.
</p>
<p>
All functions are prefixed with
<code>
strlist_
</code>
.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#reasons-for-using-c99" id="user-content-reasons-for-using-c99">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Reasons for using C99
</h3>
<ul>
<li>
Variadic macros
</li>
<li>
In older implementations
<code>
json_object_object_foreach
</code>
requires C99:
<a href="https://github.com/json-c/json-c/pull/73">
https://github.com/json-c/json-c/pull/73
</a>
</li>
<li>
C99 forces the memory layout for using casting to structs:
<a href="http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf" rel="nofollow">
§ 6.2.5, 20 of the standard
</a>
:
</li>
</ul>
<blockquote>
<p>
A structure type describes a sequentially allocated nonempty set of member objects
(and, in certain circumstances, an incomplete array), each of which has an optionally
specified name and possibly distinct type.
</p>
</blockquote>
<h3>
<a aria-hidden="true" class="anchor" href="#special-cases" id="user-content-special-cases">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Special Cases
</h3>
<ul>
<li>
<code>
static char *string_remove_backslashes(char *source_string, size_t *memsize)
</code>
in
<code>
string.c
</code>
is surrounded by a
<code>
#ifndef NO_BACKSLASHES
</code>
. This function is not needed for
<code>
[urlparams]
</code>
, and therefore this is used to not get warnings on compilation.
</li>
<li>
There are only a few platform specific
<code>
#define
</code>
s, those are all declared in
<code>
purest_json.h
</code>
.
</li>
<li>
<code>
[json-encode]
</code>
can contain arrays, while
<code>
[urlparams]
</code>
cannot, so a
<code>
#define
</code>
is used in
<code>
kvp.c
</code>
to remove array functions and struct members for
<code>
[urlparams]
</code>
.
</li>
</ul>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
function showCanonicalImages() {
var images = document.getElementsByTagName('img');
if (!images) {
return;
}
for (var index = 0; index < images.length; index++) {
var image = images[index];
if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) {
image.src = image.getAttribute('data-canonical-src');
}
}
}
function scrollToHash() {
if (location.hash && !document.querySelector(':target')) {
var element = document.getElementById('user-content-' + location.hash.slice(1));
if (element) {
element.scrollIntoView();
}
}
}
function autorefreshContent(eventSourceUrl) {
var initialTitle = document.title;
var contentElement = document.getElementById('grip-content');
var source = new EventSource(eventSourceUrl);
var isRendering = false;
source.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if (msg.updating) {
isRendering = true;
document.title = '(Rendering) ' + document.title;
} else {
isRendering = false;
document.title = initialTitle;
contentElement.innerHTML = msg.content;
showCanonicalImages();
}
}
source.onerror = function(e) {
if (e.readyState === EventSource.CLOSED && isRendering) {
isRendering = false;
document.title = initialTitle;
}
}
}
window.onhashchange = function() {
scrollToHash();
}
window.onload = function() {
scrollToHash();
}
showCanonicalImages();
var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url');
if (autorefreshUrl) {
autorefreshContent(autorefreshUrl);
}
</script>
</body>
</html>

View File

@ -0,0 +1,315 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
Using JSON Data as Pitch Generator
</title>
<style>
/* Page tweaks */
.preview-page {
margin-top: 64px;
margin-bottom: 21px;
}
/* User-content tweaks */
.timeline-comment-wrapper > .timeline-comment:after,
.timeline-comment-wrapper > .timeline-comment:before {
content: none;
}
/* User-content overrides */
.discussion-timeline.wide {
width: 920px;
}
</style>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
<div class="preview-page" data-autorefresh-url="" id="preview-page">
<main id="js-repo-pjax-container">
<div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5">
<div class="repository-content">
<div class="clearfix">
<div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end">
<div class="Layout-main">
<div class="Box md Box--responsive" id="readme">
<div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2">
<div class="d-flex flex-items-center">
<h2 class="Box-title">
Using JSON Data as Pitch Generator
</h2>
</div>
</div>
<div class="Box-body px-5 pb-5">
<article class="markdown-body entry-content container-lg" id="grip-content">
<p>
This tutorial will show you, how you can get data from a simple RESTful webservice and generate sound from it.
</p>
<p>
In this tutorial, I will use the following notation:
</p>
<ul>
<li>
<code>
[my object]
</code>
: an object with the name "my-object".
</li>
<li>
<code>
[my own message(
</code>
: a message with the content "my own message".
</li>
</ul>
<h2>
<a aria-hidden="true" class="anchor" href="#getting-the-data" id="user-content-getting-the-data">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Getting the Data
</h2>
<p>
This example gets the conversion rates between US Dollar und Euro from the
<a href="https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/usd.xml" rel="nofollow">
European central bank
</a>
, which on the server is converted from XML to JSON.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="The patch" src="currency-full.png" style="max-width: 100%;"/>
</a>
</p>
<p>
The data from the script on the website looks something like this:
</p>
<pre><code>[
{"day":"1999-01-04","rate":1.1789},
{"day":"1999-01-05","rate":1.179},
{"day":"1999-01-06","rate":1.1743},
{"day":"1999-01-07","rate":1.1632}
]
</code></pre>
<p>
When the data is received, the returned value is fed into
<code>
[json-decode]
</code>
. As the symbol atom from
<code>
[rest]
</code>
will be a JSON array, we will get messages for each JSON object on the middle outlet followed by a bang on the left outlet.
</p>
<p>
A sequence of messages for an object looks like this:
</p>
<pre><code>list day 1999-01-04
list rate 1.1789
</code></pre>
<h2>
<a aria-hidden="true" class="anchor" href="#storing-the-data" id="user-content-storing-the-data">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Storing the Data
</h2>
<p>
This section discusses the operations in the subpatch
<code>
[pd store-data]
</code>
.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="pd process-data" src="currency-data-processing.png" style="max-width: 100%;"/>
</a>
</p>
<p>
In this subpatch, the incoming lists from
<code>
[json-decode]
</code>
are taken and packed into one list for each JSON object in the array.
</p>
<p>
First, we remove the
<code>
list
</code>
prefix from each message, then pack those messages, and use the bang message from the left outlet of
<code>
[json-decode]
</code>
that is emitted after each decoded array member to trigger the output of
<code>
[pack]
</code>
. The transformed message for each JSON object then looks like:
</p>
<pre><code>0 1999-01-04 1.1789
</code></pre>
<p>
Notes:
</p>
<ul>
<li>
The date will not come out as a symbol. Conversion is done with a
<code>
[symbol]
</code>
object.
</li>
<li>
Each output from
<code>
[pack f s f]
</code>
starts with a
<code>
0
</code>
, as we only use the bang on the first inlet of
<code>
[pack]
</code>
to trigger the output.
</li>
</ul>
<p>
We then use
<code>
[text]
</code>
to store the value. We use a very high number for the position
<code>
1e+15
</code>
, to ensure that new values are appended without a counter before.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#sequencing-the-values" id="user-content-sequencing-the-values">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Sequencing the values
</h2>
<p>
This section discusses the operations in the subpatch
<code>
[pd stepper]
</code>
.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="pd stepper" src="currency-stepper.png" style="max-width: 100%;"/>
</a>
</p>
<p>
This subpatch starts a
<code>
[metro]
</code>
after all data is stored. This is basically just the sequencer example from the
<code>
[text]
</code>
help file.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#generating-sound" id="user-content-generating-sound">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Generating sound
</h2>
<p>
Sound generation is the bottom part of the main patch.
</p>
<p>
The exchange rates between US Dollar and Euro is varying very narrowly around 1. The value is multiplied by a fixed number and with an offset interpreted as MIDI notes, such that a change of 0.03 in the exchange rate will result in a change of the tone of 1 semitone.
</p>
<p>
Different data might benefit from other scaling methods, linear, logarithmic, exponential, or poynomial.
</p>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
function showCanonicalImages() {
var images = document.getElementsByTagName('img');
if (!images) {
return;
}
for (var index = 0; index < images.length; index++) {
var image = images[index];
if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) {
image.src = image.getAttribute('data-canonical-src');
}
}
}
function scrollToHash() {
if (location.hash && !document.querySelector(':target')) {
var element = document.getElementById('user-content-' + location.hash.slice(1));
if (element) {
element.scrollIntoView();
}
}
}
function autorefreshContent(eventSourceUrl) {
var initialTitle = document.title;
var contentElement = document.getElementById('grip-content');
var source = new EventSource(eventSourceUrl);
var isRendering = false;
source.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if (msg.updating) {
isRendering = true;
document.title = '(Rendering) ' + document.title;
} else {
isRendering = false;
document.title = initialTitle;
contentElement.innerHTML = msg.content;
showCanonicalImages();
}
}
source.onerror = function(e) {
if (e.readyState === EventSource.CLOSED && isRendering) {
isRendering = false;
document.title = initialTitle;
}
}
}
window.onhashchange = function() {
scrollToHash();
}
window.onload = function() {
scrollToHash();
}
showCanonicalImages();
var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url');
if (autorefreshUrl) {
autorefreshContent(autorefreshUrl);
}
</script>
</body>
</html>

View File

@ -0,0 +1,737 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
Using Pd as Twitter Client
</title>
<style>
/* Page tweaks */
.preview-page {
margin-top: 64px;
margin-bottom: 21px;
}
/* User-content tweaks */
.timeline-comment-wrapper > .timeline-comment:after,
.timeline-comment-wrapper > .timeline-comment:before {
content: none;
}
/* User-content overrides */
.discussion-timeline.wide {
width: 920px;
}
</style>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
<div class="preview-page" data-autorefresh-url="" id="preview-page">
<main id="js-repo-pjax-container">
<div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5">
<div class="repository-content">
<div class="clearfix">
<div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end">
<div class="Layout-main">
<div class="Box md Box--responsive" id="readme">
<div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2">
<div class="d-flex flex-items-center">
<h2 class="Box-title">
Using Pd as Twitter Client
</h2>
</div>
</div>
<div class="Box-body px-5 pb-5">
<article class="markdown-body entry-content container-lg" id="grip-content">
<p>
This tutorial will show you, how you can create your own Twitter client for Pd. You will learn how to use PuREST JSON for OAuth authentication, and you will be able to apply the methodology to create clients for other webservices.
</p>
<p>
In the examples folder, you can find the patch
<code>
twitter-client.pd
</code>
. You will only need to fill in your credentials, that you will get with the patch itself.
</p>
<p>
In this tutorial, I will use the following notation:
</p>
<ul>
<li>
<code>
[my object]
</code>
: an object with the name "my-object".
</li>
<li>
<code>
[my own message(
</code>
: a message with the content "my own message".
</li>
</ul>
<h2>
<a aria-hidden="true" class="anchor" href="#basic-explanation-of-oauth" id="user-content-basic-explanation-of-oauth">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Basic Explanation of OAuth
</h2>
<p>
With OAuth, a user can give an application (here: Puredata) access to a webservice (here: Twitter) without giving the application your login to the service.
</p>
<p>
To do so, the application needs its own token and secret (client credentials, consumer key and consumer secret), as well as the user's (token credentials, access token and access token secret). The token credentials are different to the login name and password for the service.
</p>
<p>
As the token credentials are different from login name and password, the webservice and / or user can restrict the application, so that it may only perform certain actions, but not all (e.g. only read access, not showing sensitive informations).
</p>
<p>
When the application has both tokens and secrets, it needs to sign each request to the service with these.
Most of these is done under the hood of
<code>
[oauth]
</code>
. What you will learn in this tutorial, is how to get your application token and secret, the user's token and secret, and how to read developer documentation. The latter skill is important for creating your own clients for other services.
</p>
<p>
<strong>
Caveat!
</strong>
This document makes some assumptions, which were true at the time of the last edit (May 2015): My client credentials are still valid, despite me giving it away in the example patch. Twitter have not changed their API, or the API is still supported.
</p>
<p>
This document goes through the file
<code>
twitter-client.pd
</code>
in the examples step by step.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#setting-up-your-application" id="user-content-setting-up-your-application">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Setting Up Your Application
</h2>
<p>
All information about the Twitter API can be found at
<a href="https://dev.twitter.com/" rel="nofollow">
https://dev.twitter.com/
</a>
.
</p>
<p>
For this tutorial, we will use PuREST JSON as a registered application. This application has both read and write access. If you want to reliably use Pd as a Twitter client, and / or want to restrict your client to read access only, you will need to register your client.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#registering-your-client" id="user-content-registering-your-client">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Registering Your Client
</h3>
<p>
Login at
<a href="https://dev.twitter.com/" rel="nofollow">
https://dev.twitter.com/
</a>
with your Twitter login. Click on the
<em>
create your application
</em>
and create your application. Leave the field
<em>
Callback URL
</em>
empty.
</p>
<p>
After registering your application, you get your consumer key and secret. These are needed for any communication with twitter.
</p>
<p>
On that page, you can also create your own access token and access token secret.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#getting-access-token-and-access-token-secret" id="user-content-getting-access-token-and-access-token-secret">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Getting Access Token and Access Token Secret
</h3>
<p>
This section discusses the operations in the subpatch
<code>
[pd authorize]
</code>
.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="pd authorize" src="twitter-authorize.png" style="max-width: 100%;"/>
</a>
</p>
<p>
You may skip this step, if you created your own access token and access token secret at the Twitter website.
</p>
<p>
Initialize
<code>
[oauth]
</code>
with the base URL, consumer key, and consumer secret (the instance of
<code>
[oauth]
</code>
already uses the PuREST JSON credentials).
</p>
<p>
Use
<code>
[POST /oauth/request_token(
</code>
method at
<code>
[oauth]
</code>
.
<code>
[oauth]
</code>
will issue a request to
<a href="https://api.twitter.com/oauth/request_token" rel="nofollow">
https://api.twitter.com/oauth/request_token
</a>
and sign the request with the consumer credentials.
</p>
<p>
In your Pd console, you will hopefully get something similar to this:
</p>
<pre><code>data1: symbol oauth_token=(YOUR_TEMP_TOKEN)&amp;amp;oauth_token_secret=(YOUR_TEMP_TOKEN_SECRET)&amp;amp;oauth_callback_confirmed=true
status1: list oauth bang
</code></pre>
<p>
Now we have an temporary access token / secret pair. With this pair, we need to tell our user (YOU!) to go to Twitter and get a PIN to generate the real access token / secret pair.
</p>
<p>
Open a web browser and go to
<a href="https://api.twitter.com/oauth/authorize?oauth_token=(YOUR_TEMP_TOKEN)&amp;amp;oauth_token_secret=(YOUR_TEMP_TOKEN_SECRET)&amp;amp;oauth_callback_confirmed=true" rel="nofollow">
https://api.twitter.com/oauth/authorize?oauth_token=(YOUR_TEMP_TOKEN)&amp;amp;oauth_token_secret=(YOUR_TEMP_TOKEN_SECRET)&amp;amp;oauth_callback_confirmed=true
</a>
. This will get you to a website, where you can authorize PuREST JSON for using the Twitter API. After authorization, you will see YOUR_PIN in large friendly letters printed on a web page. We will need these for the next step.
</p>
<p>
Now you get a PIN. This PIN will enable you to create your access token and access token key.
</p>
<p>
First, we have to tell
<code>
[oauth]
</code>
to use your new oauth access token and credentials. To do so, we will need to use the temporary access token / secret pair for signing the next OAuth request. We can do this either by editing the creation values of
<code>
[oauth]
</code>
or by sending a
<code>
[init BASE_URL CONSUMER_KEY CONSUMER_SECRET YOUR_TEMP_TOKEN YOUR_TEMP_TOKEN_SECRET(
</code>
to it. Use your return values from before.
Now send the PIN to Twitter to finally generate the read access token / secret pair. Use
<code>
[POST access_token oauth_identifier=YOUR_PIN(
</code>
for
<code>
[oauth]
</code>
to do so.
</p>
<p>
Hopefully, you get a message similar to this in your Pd console:
</p>
<pre><code>data1: symbol oauth_token=(YOUR_ACCESS_TOKEN)&amp;amp;oauth_token_secret=(YOUR_ACCESS_TOKEN_SECRET)&amp;amp;user_id=(YOUR_USER_ID)&amp;amp;screen_name=(YOUR_TWITTER_SCREEN_NAME)
</code></pre>
<h3>
<a aria-hidden="true" class="anchor" href="#test-your-twitter-client" id="user-content-test-your-twitter-client">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Test Your Twitter Client
</h3>
<p>
This section describes the subpatch
<code>
[pd simple-operations]
</code>
.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="pd simple-operations" src="twitter-simple.png" style="max-width: 100%;"/>
</a>
</p>
<p>
You will need to tell
<code>
[oauth]
</code>
to use a) consumer key / secret pair and b) access token / secret pair. To do so, either set these (with the base url for all requests) in the creation arguments, or send these to it with the
<code>
[init(
</code>
message. Do this with the right instance of
<code>
[oauth]
</code>
.
</p>
<p>
Now, get your home timeline by issuing
<code>
[GET /1.1/statuses/home_timeline.json(
</code>
to
<code>
[oauth]
</code>
. Does your timeline appear in the Pd console? Great!
</p>
<p>
Now you can even send tweets from inside Pd. To do so, POST your status update. Two things must be considered: The message must be correctly URL encoded using
<code>
[urlparams]
</code>
. This example only sets the text, for more parameters,
<a href="https://dev.twitter.com/rest/reference/post/statuses/update" rel="nofollow">
see the documentation
</a>
.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#lets-search-and-sonify-tweets" id="user-content-lets-search-and-sonify-tweets">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Let's Search and Sonify Tweets
</h2>
<p>
This section discusses the subpatch
<code>
[pd sonify-it]
</code>
and includes operations on JSON data.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="pd sonify-it" src="twitter-sonify.png" style="max-width: 100%;"/>
</a>
</p>
<p>
As this example is quite complicated, this is seperated in diverse subpatches.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#search-for-data" id="user-content-search-for-data">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Search for Data
</h3>
<p>
The
<a href="https://dev.twitter.com/rest/public/search" rel="nofollow">
search API is extensively documented
</a>
. In our case we search for tweets containing the hashtag
<code>
#Puredata
</code>
. This leads to an output similar to the following on the end of
<code>
[oauth]
</code>
.
</p>
<pre><code>\{"statuses":[\{"metadata":\{"iso_language_code":"en"\\,"result_type":"recent"\}\\,"created_at":"Thu Apr 09 21:33:41 +0000 1970"\\,"id":111\\,"id_str":"111"\\,"text":"#PureData
</code></pre>
<p>
The next logical step is disecting the message and finding suitable data for sonification. This example settles on the tweet message, user name and display name.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#transform-the-json-string-to-pd-symbols" id="user-content-transform-the-json-string-to-pd-symbols">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Transform the JSON string to Pd symbols
</h3>
<p>
This section discusses the subpatch
<code>
[pd data-transform]
</code>
.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="Transforming the JSON data" src="twitter-json.png" style="max-width: 100%;"/>
</a>
</p>
<p>
We first feed the output of
<code>
[oauth]
</code>
to the first instance of
<code>
[json-decode]
</code>
. This will generate a sequence of lists on the middle output. After removing the list keyword using
<code>
[list trim]
</code>
, we can select only the symbol following the
<code>
statuses
</code>
beginning. This contains the status data.
</p>
<p>
Using the second
<code>
[json-decode]
</code>
we decode the statuses. This is a JSON array, so we get a sequence of several objects that are decoded. We strip off the list keyword, and route our status members
<code>
text
</code>
and
<code>
user
</code>
.
<code>
user
</code>
is a JSON object itself, so we need another instance of
<code>
[json-decode]
</code>
to get
<code>
name
</code>
and
<code>
screen_name
</code>
from the object. As the output may contain spaces, instances of
<code>
[list2symbol]
</code>
or
<code>
[l2s]
</code>
from zexy are used to generate correct symbols.
</p>
<p>
We pack these objects while not using the first inlet of
<code>
[pack]
</code>
for data. This gets connected to the left outlet of the second
<code>
[json-decode]
</code>
, so that after each array of the
<code>
statuses
</code>
array something like the following list is sent to the right outlet of the subpatch:
</p>
<pre><code>0 #Puredata\ is\ Turing\ complete!\ Yay Joe\ Doe joedoe1
</code></pre>
<p>
Beware:
<code>
\
</code>
is the escape character in Pd, so that the space following it is not a separator between two atoms but part of the symbol. This translates to: The user
<code>
Joe Doe
</code>
with the Twitter handle
<code>
joedoe1
</code>
has tweeted
<code>
#Puredata is Turing complete! Yay
</code>
.
</p>
<p>
After everything is analysed, the first
<code>
[json-decode]
</code>
is done and outputs a bang on its left outlet, which is connected to the left outlet of the subpatch.
</p>
<p>
Directly after the subpatch,
<code>
[fifop]
</code>
from zexy is used to store all lists of atoms. Using the bang from the left outlet of the subpatch, we can retrieve the first list and process it, beginning with
<code>
[unpack]
</code>
ing the list. Notice, that the first outlet is discarded, as this contains always
<code>
0
</code>
.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#sonifying-the-data" id="user-content-sonifying-the-data">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Sonifying the Data
</h3>
<p>
This is just a rough sketch of what else is going on in the patch.
</p>
<p>
The tweet text is subsequently split into a sequence of the ASCII codes of the characters using
<code>
[spell]
</code>
from cyclone. Another FIFO buffer is used to store this sequence and is triggered by a metro. As the first ASCII codes 0x00 - 0x32 are non-printable characters, we do not generate a sound for those. The rest of the ASCII codes are interpreted as MIDI notes.
</p>
<p>
For the name, we find the length of the symbol by using
<code>
[symbol2list]
</code>
or
<code>
[s2l]
</code>
from zexy with an empty separator. Counting the length of the resulting list with
<code>
[list length]
</code>
, we get the symbol length. The length of the name is used to determine the volume of the tweet sonification.
</p>
<p>
Lastly we take the length of the username and use it to modify the frequency of an LFO.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#whats-up-with-the-base-url-stuff-why-is-it-used-as-the-first-parameter-to-everything" id="user-content-whats-up-with-the-base-url-stuff-why-is-it-used-as-the-first-parameter-to-everything">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
What's up with the Base URL stuff? Why Is It Used as the First Parameter to Everything?
</h2>
<p>
Consumer key and secret as well as access token and secret are sensitive data. Anybody getting the consumer key / secret pair in their hands can pose as that application to the webservice. Likewise, anybody getting their hand on the access token / secret pair
<strong>
can use the webservice with the provided accessibilty
</strong>
.
That means, if you send your OAuth request to the wrong webservice provider, you will get a 404 error back - in the best of all cases.
</p>
<p>
In the worst case, the wrong webservice provider is malicious and guesses, that you wanted to use Twitter and use your credentials to
<strong>
pose as your application with your access credentials
</strong>
.
</p>
<p>
Now, if you set base URL to
<a href="http://example.com" rel="nofollow">
http://example.com
</a>
and issue a
<code>
[GET http://example.org/test(
</code>
,
<code>
[oauth]
</code>
will perform a GET request to
<a href="http://example.comhttp://example.org/test" rel="nofollow">
http://example.comhttp://example.org/test
</a>
, something not existant.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#what-else-can-i-do-now-or-how-to-read-the-api-documentation" id="user-content-what-else-can-i-do-now-or-how-to-read-the-api-documentation">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
What Else Can I Do Now? Or: How to Read the API Documentation
</h2>
<p>
This section assumes, that you are not a professional programmer or do not have much experience in reading API reference documents.
</p>
<p>
Now, that we have a functional Twitter client, what are the possibilities? And how can I get information on how to use OAuth with other webservices?
</p>
<p>
Well, first go to
<a href="https://dev.twitter.com/docs" rel="nofollow">
the documentation from Twitter
</a>
themselves. All you need to know is there.
</p>
<p>
OK, just joking. As this library is called PuREST JSON and
<code>
[oauth]
</code>
is used for OAuth signed RESTful requests, we need to read the
<a href="https://dev.twitter.com/docs/api/1.1" rel="nofollow">
REST API documention
</a>
"only".
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#how-do-i-know-the-right-steps-to-get-my-login-information" id="user-content-how-do-i-know-the-right-steps-to-get-my-login-information">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
How Do I Know the Right Steps to Get My Login Information?
</h3>
<p>
Take the documentation for any method, e.g.
<a href="https://dev.twitter.com/docs/api/1.1/get/statuses/mentions_timeline" rel="nofollow">
GET statuses/mentions_timeline
</a>
.
</p>
<p>
On the right side, you see a section "Resource Information", which contains "Authentication: Requires user context" as a link.
</p>
<p>
So, we click on that link, and go to a page that tells us about OAuth authentication. We will need to use OAuth, so there is the link "Using OAuth" that gets us to another overview page. We will need to get an access token, which leads us to
<a href="https://dev.twitter.com/docs/auth/obtaining-access-tokens" rel="nofollow">
this wonderful selection page
</a>
.
</p>
<p>
What do we want to do? We have a (kind of) desktop app, that can't access a browser, so we will need to use ...
<a href="https://dev.twitter.com/docs/auth/pin-based-authorization" rel="nofollow">
PIN-based authorization
</a>
. And now, all the steps are linked from there.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#how-do-i-read-a-documentation-entry" id="user-content-how-do-i-read-a-documentation-entry">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
How Do I Read A Documentation Entry?
</h3>
<p>
OK, now that we have found our method to call, we need to know how to do our call.
</p>
<p>
Let's say, you want to tweet from Pd and have already found the method
<a href="https://dev.twitter.com/docs/api/1.1/post/statuses/update" rel="nofollow">
POST statuses/update
</a>
.
</p>
<p>
<a rel="noopener noreferrer nofollow" target="_blank">
<img alt="Screenshot from Twitter website" src="twitter-documentation.png" style="max-width: 100%;"/>
</a>
</p>
<p>
The important parts are marked with yellow by me. On the bottom of the page you can see examples, that tell you how to use the method.
</p>
<p>
That's all there is, there's no inherent magic.
</p>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
function showCanonicalImages() {
var images = document.getElementsByTagName('img');
if (!images) {
return;
}
for (var index = 0; index < images.length; index++) {
var image = images[index];
if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) {
image.src = image.getAttribute('data-canonical-src');
}
}
}
function scrollToHash() {
if (location.hash && !document.querySelector(':target')) {
var element = document.getElementById('user-content-' + location.hash.slice(1));
if (element) {
element.scrollIntoView();
}
}
}
function autorefreshContent(eventSourceUrl) {
var initialTitle = document.title;
var contentElement = document.getElementById('grip-content');
var source = new EventSource(eventSourceUrl);
var isRendering = false;
source.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if (msg.updating) {
isRendering = true;
document.title = '(Rendering) ' + document.title;
} else {
isRendering = false;
document.title = initialTitle;
contentElement.innerHTML = msg.content;
showCanonicalImages();
}
}
source.onerror = function(e) {
if (e.readyState === EventSource.CLOSED && isRendering) {
isRendering = false;
document.title = initialTitle;
}
}
}
window.onhashchange = function() {
scrollToHash();
}
window.onload = function() {
scrollToHash();
}
showCanonicalImages();
var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url');
if (autorefreshUrl) {
autorefreshContent(autorefreshUrl);
}
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,215 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
Home
</title>
<style>
/* Page tweaks */
.preview-page {
margin-top: 64px;
margin-bottom: 21px;
}
/* User-content tweaks */
.timeline-comment-wrapper > .timeline-comment:after,
.timeline-comment-wrapper > .timeline-comment:before {
content: none;
}
/* User-content overrides */
.discussion-timeline.wide {
width: 920px;
}
</style>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
<div class="preview-page" data-autorefresh-url="" id="preview-page">
<main id="js-repo-pjax-container">
<div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5">
<div class="repository-content">
<div class="clearfix">
<div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end">
<div class="Layout-main">
<div class="Box md Box--responsive" id="readme">
<div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2">
<div class="d-flex flex-items-center">
<h2 class="Box-title">
Home
</h2>
</div>
</div>
<div class="Box-body px-5 pb-5">
<article class="markdown-body entry-content container-lg" id="grip-content">
<p>
PuREST JSON is a library for connecting Puredata (Pd) to HTTP services
and encoding and decoding JSON data.
</p>
<p>
The library can issue HTTP statements, so consumation of RESTful services is possible, e.g. CouchDB.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#basic-information-for-users" id="user-content-basic-information-for-users">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Basic Information for Users
</h2>
<ul>
<li>
<a href="http://ix.residuum.org/pd/purest_json.html#download" rel="nofollow">
Binary Downloads
</a>
</li>
<li>
<a href="Basic-Usage.html">
Basic Usage
</a>
</li>
</ul>
<h2>
<a aria-hidden="true" class="anchor" href="#usage-examples" id="user-content-usage-examples">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Usage examples
</h2>
<ul>
<li>
<a href="Using-JSON-Data-as-Pitch-Generator.html">
Using JSON data as pitch generator
</a>
</li>
<li>
<a href="Using-Pd-as-Twitter-Client.html">
Using Pd as Twitter Client
</a>
</li>
<li>
<a href="https://github.com/g-roma/freesound_pd">
Previewing and downloading samples from Freesound.org
</a>
</li>
</ul>
<h2>
<a aria-hidden="true" class="anchor" href="#detailed-documentation-for-objects" id="user-content-detailed-documentation-for-objects">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Detailed Documentation for Objects
</h2>
<ul>
<li>
<a href="json-decode-And-json-encode-JSON-Data-in-Pd.html">
[json decode] and [json encode]: JSON Data in Pd
</a>
</li>
<li>
<a href="rest-And-oauth-Making-HTTP-Requests.html">
[rest] and [oauth]: Making HTTP Requests
</a>
</li>
<li>
<a href="urlparams-Creating-Query-Strings.html">
[urlparams]: Creating Query Strings
</a>
</li>
</ul>
<h2>
<a aria-hidden="true" class="anchor" href="#developers" id="user-content-developers">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Developers
</h2>
<ul>
<li>
<a href="Compilation.html">
Compilation
</a>
</li>
<li>
<a href="Contributing-and-Code-Documentation.html">
Contributing and Code Documentation
</a>
</li>
</ul>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
function showCanonicalImages() {
var images = document.getElementsByTagName('img');
if (!images) {
return;
}
for (var index = 0; index < images.length; index++) {
var image = images[index];
if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) {
image.src = image.getAttribute('data-canonical-src');
}
}
}
function scrollToHash() {
if (location.hash && !document.querySelector(':target')) {
var element = document.getElementById('user-content-' + location.hash.slice(1));
if (element) {
element.scrollIntoView();
}
}
}
function autorefreshContent(eventSourceUrl) {
var initialTitle = document.title;
var contentElement = document.getElementById('grip-content');
var source = new EventSource(eventSourceUrl);
var isRendering = false;
source.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if (msg.updating) {
isRendering = true;
document.title = '(Rendering) ' + document.title;
} else {
isRendering = false;
document.title = initialTitle;
contentElement.innerHTML = msg.content;
showCanonicalImages();
}
}
source.onerror = function(e) {
if (e.readyState === EventSource.CLOSED && isRendering) {
isRendering = false;
document.title = initialTitle;
}
}
}
window.onhashchange = function() {
scrollToHash();
}
window.onload = function() {
scrollToHash();
}
showCanonicalImages();
var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url');
if (autorefreshUrl) {
autorefreshContent(autorefreshUrl);
}
</script>
</body>
</html>

View File

@ -0,0 +1,766 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
[json decode] And [json encode]: JSON Data in Pd
</title>
<style>
/* Page tweaks */
.preview-page {
margin-top: 64px;
margin-bottom: 21px;
}
/* User-content tweaks */
.timeline-comment-wrapper > .timeline-comment:after,
.timeline-comment-wrapper > .timeline-comment:before {
content: none;
}
/* User-content overrides */
.discussion-timeline.wide {
width: 920px;
}
</style>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
<div class="preview-page" data-autorefresh-url="" id="preview-page">
<main id="js-repo-pjax-container">
<div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5">
<div class="repository-content">
<div class="clearfix">
<div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end">
<div class="Layout-main">
<div class="Box md Box--responsive" id="readme">
<div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2">
<div class="d-flex flex-items-center">
<h2 class="Box-title">
[json decode] And [json encode]: JSON Data in Pd
</h2>
</div>
</div>
<div class="Box-body px-5 pb-5">
<article class="markdown-body entry-content container-lg" id="grip-content">
<p>
Pd does not have boolean values, and no notion of a NULL object, only lists, symbols (=strings) and floats (=numbers).
</p>
<p>
To use the definitions from
<a href="http://json.org/" rel="nofollow">
json.org
</a>
this leads to the following mapping of JSON data to Pd:
</p>
<table>
<thead>
<tr>
<th>
JSON type
</th>
<th>
Pd type
</th>
<th>
JSON example
</th>
<th>
Pd example
</th>
</tr>
<tr>
</tr>
</thead>
<tbody>
<tr>
<td>
string
</td>
<td>
symbol
</td>
<td>
"my string, containing a comma"
</td>
<td>
symbol my string\, containing a comma
</td>
</tr>
<tr>
</tr>
<tr>
<td>
number
</td>
<td>
float
</td>
<td>
1.01
</td>
<td>
1.01
</td>
</tr>
<tr>
</tr>
<tr>
<td>
object
</td>
<td>
see below
</td>
<td>
{"key": "value"}
</td>
<td>
</td>
</tr>
<tr>
</tr>
<tr>
<td>
array
</td>
<td>
see below
</td>
<td>
[{"key": "value"}, {"other key": "other value"}]
</td>
<td>
</td>
</tr>
<tr>
</tr>
<tr>
<td>
boolean
</td>
<td>
float
</td>
<td>
true
</td>
<td>
1
</td>
</tr>
<tr>
</tr>
<tr>
<td>
boolean
</td>
<td>
float
</td>
<td>
false
</td>
<td>
0
</td>
</tr>
<tr>
</tr>
<tr>
<td>
null
</td>
<td>
symbol
</td>
<td>
null
</td>
<td>
symbol
</td>
</tr>
<tr>
</tr>
</tbody>
</table>
<p>
As you can infer from the table, values of
<code>
true
</code>
,
<code>
false
</code>
, or
<code>
null
</code>
cannot be constructed by
<code>
[json-encode]
</code>
, but can be read by the objects. A value of null yields a Pd value of an empty symbol.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#json-decode" id="user-content-json-decode">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
<code>
[json-decode]
</code>
</h2>
<p>
Feeding a symbol or list to
<code>
[json-decode]
</code>
will parse the values and generate an output. If you use a list, then all elements of the list will be converted to symbols and concatenated using a space as separator, so
<code>
symbol my value
</code>
will generate the same output as
<code>
list my value
</code>
.
</p>
<p>
You must feed exactly one valid JSON object or array of objects as a symbol or list message to
<code>
[json-decode]
</code>
. Any other correct JSON data cannot be interpreted by the
<code>
[json-decode]
</code>
.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#output-of-a-json-object" id="user-content-output-of-a-json-object">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Output of a JSON object
</h3>
<p>
JSON objects are interpreted by
<code>
[json-decode]
</code>
as key value stores. Each key/value pair outputs a list on the middle outlet, where the key is always converted to a symbol, while the value is converted according to the table above. Arrays and objects are converted to their string representation again and then output as a symbol.
</p>
<p>
After all key/value are sent to the middle outlet, a
<code>
bang
</code>
is emitted from the left outlet.
</p>
<p>
<strong>
Example:
</strong>
</p>
<p>
JSON string:
</p>
<pre><code>{
"id": 1,
"active": true,
"obsolete": false,
"name": "PuREST JSON",
"objects": ["json-decode", "json-encode", "urlparams", "rest", "oauth"],
"author": {"name": "me", "age": "none of your business"}
}
</code></pre>
<p>
Output:
</p>
<ol>
<li>
middle:
<code>
list id 1
</code>
</li>
<li>
middle:
<code>
list active 1
</code>
</li>
<li>
middle:
<code>
list obsolete 0
</code>
</li>
<li>
middle:
<code>
list name PuREST JSON
</code>
</li>
<li>
middle:
<code>
list objects ["json-decode"\, "json-encode"\, "urlparams"\, "rest"\, "oauth"]
</code>
</li>
<li>
middle:
<code>
list author {"name": "me"\, "age": "none of your business"}
</code>
</li>
<li>
left:
<code>
bang
</code>
</li>
</ol>
<h3>
<a aria-hidden="true" class="anchor" href="#output-of-an-array-of-json-objects" id="user-content-output-of-an-array-of-json-objects">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Output of an Array of JSON objects
</h3>
<p>
An array generates the same output as a series of JSON objects, including
<code>
bang
</code>
messages on the left outlet.
</p>
<p>
<strong>
Example:
</strong>
</p>
<p>
JSON string:
</p>
<pre><code>[
{"key": "value", "id": 1},
{"id": 2},
{"id": 3}
]
</code></pre>
<p>
Output:
</p>
<ol>
<li>
middle:
<code>
list key value
</code>
</li>
<li>
middle:
<code>
list id 1
</code>
</li>
<li>
left:
<code>
bang
</code>
</li>
<li>
middle:
<code>
list id 2
</code>
</li>
<li>
left:
<code>
bang
</code>
</li>
<li>
middle:
<code>
list id 3
</code>
</li>
<li>
left:
<code>
bang
</code>
</li>
</ol>
<h3>
<a aria-hidden="true" class="anchor" href="#error-handling" id="user-content-error-handling">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Error handling
</h3>
<p>
If the string fed into
<code>
[json-decode]
</code>
cannot be converted into a valid JSON object, then Pd will write an error to the console, and the right outlet will output a bang. Use that for error handling.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#some-hints-for-data-processing" id="user-content-some-hints-for-data-processing">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Some hints for data processing
</h3>
<ul>
<li>
Use
<code>
list trim
</code>
from list-abs for trimming the list selector off the output and then use
<code>
[route]
</code>
for the data. If you want to create new lists, feed them into
<code>
[pack]
</code>
.
</li>
<li>
If you process an array of same object types, use the approach above and store the values in a FIFO buffer, e. g.
<code>
[fifop]
</code>
from zexy or
<code>
[list-fifo]
</code>
from list-abs.
</li>
<li>
Do not expect JSON data to be ordered:
<code>
{"id": 1, "name: "my name"}
</code>
and
<code>
{"name": "my name", "id": 1}
</code>
are in fact the same object. Use an empty first inlet of
<code>
[pack]
</code>
and the
<code>
bang
</code>
from the left outlet to create your own lists.
</li>
</ul>
<h2>
<a aria-hidden="true" class="anchor" href="#json-encode" id="user-content-json-encode">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
<code>
[json-encode]
</code>
</h2>
<h3>
<a aria-hidden="true" class="anchor" href="#reading-and-writing-json-files" id="user-content-reading-and-writing-json-files">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Reading and Writing JSON files
</h3>
<p>
<code>
[json-encode]
</code>
can hold one JSON object at a time in its memory. Therefore, if you read JSON data from a file using the
<code>
[read(
</code>
message, the message needs exactly one additional parameter, the path to the file to read.
</p>
<p>
The file must contain exactly one JSON object. If you want to read an array, you must wrap the array in an object.
</p>
<p>
<strong>
Example:
</strong>
</p>
<p>
<code>
[{"key": "value"}, {"another key": "another value"}]
</code>
cannot be read, but
<code>
{"wrapping": [{"key": "value"}, {"another key": "another value"}]}
</code>
can.
</p>
<p>
To write data to a file, use the
<code>
[write(
</code>
message. This message needs exactly one additional parameter, the path to the file to write the JSON object as string. It will overwrite existing content without asking for confirmation.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#storing-data-with-add-and-array" id="user-content-storing-data-with-add-and-array">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Storing Data with
<code>
[add(
</code>
And
<code>
[array(
</code>
</h3>
<p>
There are two messages for adding values to the JSON object stored in
<code>
[json-encode]
</code>
,
<code>
[add(
</code>
and
<code>
[array(
</code>
. Both need at least two additional values. The first parameter must be a symbol and represents the key. As Pd currently has no way to escape whitespace, there is no simple way to generate keys with space in it, a workaround is possible using
<code>
[makefilename]
</code>
from
<a href="http://puredata.info/downloads/zexy" rel="nofollow">
zexy
</a>
.
</p>
<p>
If the message has exactly two additional parameters, and the second parameter is a float, then the value will be stored as a number. Otherwise all additional parameters will be concatenated with a space.
</p>
<p>
If the additional parameters can be converted to a JSON object, then the resulting string will be converted thusly, otherwise, a string is stored.
</p>
<p>
Adding a value with an already stored key will result in overwriting the existing value.
</p>
<p>
<strong>
Example:
</strong>
</p>
<ul>
<li>
<code>
[add key 1(
</code>
will store
<code>
{"key":1}
</code>
.
</li>
<li>
<code>
[add key first second third(
</code>
will store
<code>
{"key":"first second third"}
</code>
.
</li>
<li>
<code>
[add key {"first":"second third"}(
</code>
will store
<code>
{"key":{first: "second third"}}
</code>
.
</li>
</ul>
<p>
<code>
[array(
</code>
will add data to an array with the name of the key. The members of the array will be sorted in the specified order. If a value with the same key exists, but was stored with
<code>
[add(
</code>
, the value will be discarded. A new
<code>
[add(
</code>
message with the same key will discard the stored array.
</p>
<p>
<strong>
Example:
</strong>
</p>
<ol>
<li>
<code>
[add id 1(
</code>
=&gt;
<code>
{"id": 1}
</code>
.
</li>
<li>
<code>
[array id 2(
</code>
=&gt;
<code>
{"id": [2]}
</code>
.
</li>
<li>
<code>
[array id 3(
</code>
=&gt;
<code>
{"id": [2, 3]}
</code>
.
</li>
<li>
<code>
[add id 4(
</code>
=&gt;
<code>
{"id": 4}
</code>
.
</li>
</ol>
<h3>
<a aria-hidden="true" class="anchor" href="#outputting-and-clearing-data" id="user-content-outputting-and-clearing-data">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Outputting And Clearing Data
</h3>
<p>
Issuing a
<code>
[bang(
</code>
message to
<code>
[json-encode]
</code>
will output the JSON object as a string on its only outlet. If no data is stored, an empty symbol is sent.
</p>
<p>
You can clear the stored object with the
<code>
[clear(
</code>
method.
</p>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
function showCanonicalImages() {
var images = document.getElementsByTagName('img');
if (!images) {
return;
}
for (var index = 0; index < images.length; index++) {
var image = images[index];
if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) {
image.src = image.getAttribute('data-canonical-src');
}
}
}
function scrollToHash() {
if (location.hash && !document.querySelector(':target')) {
var element = document.getElementById('user-content-' + location.hash.slice(1));
if (element) {
element.scrollIntoView();
}
}
}
function autorefreshContent(eventSourceUrl) {
var initialTitle = document.title;
var contentElement = document.getElementById('grip-content');
var source = new EventSource(eventSourceUrl);
var isRendering = false;
source.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if (msg.updating) {
isRendering = true;
document.title = '(Rendering) ' + document.title;
} else {
isRendering = false;
document.title = initialTitle;
contentElement.innerHTML = msg.content;
showCanonicalImages();
}
}
source.onerror = function(e) {
if (e.readyState === EventSource.CLOSED && isRendering) {
isRendering = false;
document.title = initialTitle;
}
}
}
window.onhashchange = function() {
scrollToHash();
}
window.onload = function() {
scrollToHash();
}
showCanonicalImages();
var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url');
if (autorefreshUrl) {
autorefreshContent(autorefreshUrl);
}
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -0,0 +1,232 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
[urlparams]: Creating Query Strings
</title>
<style>
/* Page tweaks */
.preview-page {
margin-top: 64px;
margin-bottom: 21px;
}
/* User-content tweaks */
.timeline-comment-wrapper > .timeline-comment:after,
.timeline-comment-wrapper > .timeline-comment:before {
content: none;
}
/* User-content overrides */
.discussion-timeline.wide {
width: 920px;
}
</style>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
<div class="preview-page" data-autorefresh-url="" id="preview-page">
<main id="js-repo-pjax-container">
<div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5">
<div class="repository-content">
<div class="clearfix">
<div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end">
<div class="Layout-main">
<div class="Box md Box--responsive" id="readme">
<div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2">
<div class="d-flex flex-items-center">
<h2 class="Box-title">
[urlparams]: Creating Query Strings
</h2>
</div>
</div>
<div class="Box-body px-5 pb-5">
<article class="markdown-body entry-content container-lg" id="grip-content">
<p>
<code>
[urlparams]
</code>
is an object for creating query strings. It takes a series of key/value pairs at its inlet and outputs these as one symbol. Special characters in both key and value are URL encoded.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#storing-data-with-add" id="user-content-storing-data-with-add">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Storing Data with
<code>
[add(
</code>
</h2>
<p>
The
<code>
[add(
</code>
message needs at least two parameters: key and value. Any additional parameters are concatenated to the value with a space. A key/value pair is output with a
<code>
=
</code>
separator, while all key/value pairs are concatenated with a
<code>
&amp;
</code>
. Special characters will be URL encoded.
</p>
<p>
Adding a value with an already stored key will result in overwriting the existing value.
</p>
<p>
<strong>
Examples:
</strong>
</p>
<ul>
<li>
<code>
[add key 1(
</code>
will store
<code>
key=1
</code>
</li>
<li>
<code>
[add name My Name(
</code>
will store
<code>
name=My%20Name
</code>
</li>
<li>
<code>
[add key 1(
</code>
,
<code>
[add name My Name(
</code>
,
<code>
[add key 2(
</code>
will store
<code>
key=2&amp;name=My%20Name
</code>
</li>
<li>
<code>
[add key @me with #hashtag(
</code>
will store
<code>
key=%40me%20with%20%23hashtag
</code>
</li>
</ul>
<h2>
<a aria-hidden="true" class="anchor" href="#outputting-and-clearing-data" id="user-content-outputting-and-clearing-data">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Outputting And Clearing Data
</h2>
<p>
Issuing a
<code>
[bang(
</code>
message to
<code>
[urlparams]
</code>
will output the stored key/value pairs as string on its only outlet. If no data is stored, an empty symbol is sent.
</p>
<p>
You can clear the stored object with the
<code>
[clear(
</code>
method.
</p>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
function showCanonicalImages() {
var images = document.getElementsByTagName('img');
if (!images) {
return;
}
for (var index = 0; index < images.length; index++) {
var image = images[index];
if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) {
image.src = image.getAttribute('data-canonical-src');
}
}
}
function scrollToHash() {
if (location.hash && !document.querySelector(':target')) {
var element = document.getElementById('user-content-' + location.hash.slice(1));
if (element) {
element.scrollIntoView();
}
}
}
function autorefreshContent(eventSourceUrl) {
var initialTitle = document.title;
var contentElement = document.getElementById('grip-content');
var source = new EventSource(eventSourceUrl);
var isRendering = false;
source.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if (msg.updating) {
isRendering = true;
document.title = '(Rendering) ' + document.title;
} else {
isRendering = false;
document.title = initialTitle;
contentElement.innerHTML = msg.content;
showCanonicalImages();
}
}
source.onerror = function(e) {
if (e.readyState === EventSource.CLOSED && isRendering) {
isRendering = false;
document.title = initialTitle;
}
}
}
window.onhashchange = function() {
scrollToHash();
}
window.onload = function() {
scrollToHash();
}
showCanonicalImages();
var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url');
if (autorefreshUrl) {
autorefreshContent(autorefreshUrl);
}
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
purest_json/oauth.pd_linux Executable file

Binary file not shown.

398
purest_json/rest-help.pd Normal file
View File

@ -0,0 +1,398 @@
#N canvas 209 73 1011 704 10;
#X declare -path purest_json;
#X text 55 178 - object for HTTP communication with REST webservices;
#X obj 18 176 rest;
#X obj 450 468 rest;
#X text 466 107 By default \, requests do not timeout. To set a maximal time in milliseconds \, set a value with [timeout( message. To clear the value and return to the default \, use an empty [timeout( message.;
#X msg 469 166 timeout 2000;
#X msg 569 166 timeout;
#X msg 594 415 sslcheck 0;
#X msg 691 414 sslcheck 1;
#X obj 18 198 oauth;
#X text 55 197 - object for HTTP communication with OAuth webservices;
#N canvas 148 110 1044 412 oauth-specific 0;
#X obj 29 53 oauth http://example.com/ CLIENTKEY CLIENTSECRET ACCESSTOKEN ACCESSSECRET;
#X msg 31 205 method PLAINTEXT;
#X obj 31 304 oauth;
#X msg 82 234 method HMAC;
#X msg 91 262 method RSA privatekey;
#N canvas 551 129 913 749 RSA 0;
#X msg 131 448 GET /echo_api.php?method=foo&bar=baz;
#X msg 128 491 POST /echo_api.php?method=foo&bar=baz;
#X obj 92 539 oauth;
#X msg 114 83 method RSA -----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d 7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+ 3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8 AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54 Lw03eHTNQghS0A== -----END PRIVATE KEY-----;
#X text 481 33 You need to set client secret and access secret with the [init( message or as arguments for [oauth] \, but these will be ignored with the RSA key;
#X obj 92 608 print status-rsa;
#X obj 202 608 print data-rsa;
#X obj 202 581 spigot;
#X obj 235 555 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X msg 78 35 init https://example.com/oauth/example key this_is_ignored accesskey this_is_ignored;
#X connect 0 0 2 0;
#X connect 1 0 2 0;
#X connect 2 0 5 0;
#X connect 2 1 7 0;
#X connect 3 0 2 0;
#X connect 7 0 6 0;
#X connect 8 0 7 1;
#X connect 9 0 2 0;
#X restore 333 190 pd RSA;
#X text 29 135 The method message will set the OAUTH signature method. Default is HMAC (HMAC-SHA1). For RSA (RSA-SHA1) you have to submit your private key. If your version of liboauth does not support RSA-SHA1 signatures \, you will receive an error message.;
#X msg 523 55 GET /echo_api.php?method=foo&bar=baz;
#X msg 541 100 POST /echo_api.php?method=foo&bar=baz;
#X obj 489 142 oauth;
#X text 27 7 Set the base url \, consumer key and secret (client credentials) \, and optionally access token and secret (token credentials) at creation or use [init( message.;
#X obj 413 211 print status;
#X obj 502 211 print data;
#X obj 502 177 spigot;
#X obj 535 151 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X msg 489 9 init https://www.example.com/oauth/example key secret accesskey accesssecret;
#X connect 1 0 2 0;
#X connect 3 0 2 0;
#X connect 4 0 2 0;
#X connect 7 0 9 0;
#X connect 8 0 9 0;
#X connect 9 0 11 0;
#X connect 9 1 13 0;
#X connect 13 0 12 0;
#X connect 14 0 13 1;
#X connect 15 0 9 0;
#X restore 196 498 pd oauth-specific;
#X text 19 230 Most methods work the same for [rest] and [oauth] \, only some methods differ. The differences are outlined below.;
#X obj 22 429 urlparams;
#N canvas 137 61 404 367 rest-specific 0;
#N canvas 699 67 413 419 cookie-auth 0;
#X text 15 75 This will try to log you in on creation. It will call the url http://example.com/login-page and post username=myusername&password=mypass to the page.;
#X text 15 124 When this returns a cookie \, the cookie will be saved and included in every request \, as long as the base url does not change.;
#X text 15 173 Please keep in mind \, that passwords in Pd patches are stored in plain text \, especially when you use code hosting services. Better store your passwords in a seperate file or application and use [textfile] or OSC for getting the data.;
#X text 19 234 This;
#X obj 17 54 rest http://example.com/ login-page myusername mypass;
#X obj 20 253 rest http://example.com/ login-page myusername mypass;
#X obj 20 327 rest;
#X msg 20 293 init http://example.com/ login-page myusername mypass;
#X text 19 273 is the same as this after clicking the [init( message;
#X text 20 353 To clear your stored authentication cookie \, send a [init( message with no additional parameters \, or with only one parameter. The latter will send only the base url \, but will not try to log you in.;
#X text 15 6 Basic cookie authentication is possible with [rest] \, as long as the service uses some guidelines \, that are adopted from CouchDB.;
#X connect 7 0 6 0;
#X restore 8 316 pd cookie-auth;
#X text 6 296 Using cookie authentication with [rest];
#N canvas 548 57 860 439 CouchDB-basics 0;
#X text 469 71 CRUD documents:;
#X text 15 10 Basic CRUD methods for databases and individual documents are done with three HTTP methods: PUT \, GET and DELETE. PUT is used for creating and updating data \, GET is used for retrieving data \, while DELETE is used for deleting data. This is best explained with some examples:;
#X text 15 81 CRUD databases:;
#X text 15 100 PUT http://localhost:5984/pd-test;
#X text 15 119 This will create a database "pd-test" on the server localhost. If the operation is successful \, CouchDB will return a JSON object starting with a key of "ok" and a message as value for that key. If creating the database is not possible \, you will get a key "error" and the reason for the failure as its value.;
#X text 15 203 GET http://localhost:5984/pd-test;
#X text 15 222 This will get some info on the database \, including the count of stored documents as "doc_count". If getting the database is not possible you will receive a key "error" and the reason for the failure as its value.;
#X text 15 280 DELETE http://localhost:5984/pd-test;
#X text 15 299 This will delete the database if possible. BEWARE: You won't get prompted for confirmation \, CouchDB will delete the database without any warning including all stored documents. This will return "ok" or "error" as a key.;
#X text 469 122 This will create or update a document with the ID "object-name" in the database "pd-test". The database must be created first. If a document with the ID "object-name" already exists \, you must include the revision \, that you can get with the GET method (see below). On error CouchDB will return a key of "error" and the reason for the error as its value. Data for the object must be provided as JSON data in the request header.;
#X text 469 232 GET http://localhost:5984/pd-test/object-name;
#X text 469 251 This will retrieve the document "object-name" from the database "pd-test". This will return the document as a JSON object \, including the ID with the key "_id" and the revision code with the key "_rev". The latter value is needed for updating or deleting the object from the table to prevent concurrent updates.;
#X text 469 335 DELETE http://localhost:5984/pd-test/object-name;
#X text 469 354 This will delete the document if possible. You will need to provide the revision for the document. You will receive data with a key of "ok" or "error" and information as value.;
#X text 469 90 PUT http://localhost:5984/pd-test/object-name data-as-json-string;
#X text 15 357 All these request \, PUT \, GET and DELETE can be done with [rest] \, you can even issue POST requests to a CouchDB server. If you want to do complex data operations on a CouchDB \, please refer to the manual: http://guide.couchdb.org/;
#X restore 9 190 pd CouchDB-basics;
#N canvas 563 47 932 955 couchdb 0;
#X msg 170 173 bang;
#X obj 446 470 list trim;
#X msg 348 508 0;
#X obj 391 497 t b b;
#X msg 383 535 1;
#X obj 78 616 print error message;
#N canvas 574 80 450 431 create-sequencer-data 0;
#X obj 2 10 inlet;
#X obj 2 348 outlet;
#X obj 32 300 + 1;
#X obj 2 323 pack f s;
#X obj 2 244 json-encode;
#X obj 2 271 t b a;
#X obj 2 300 0;
#X msg 80 244 0;
#X obj 90 10 inlet;
#X obj 2 83 list append;
#X msg 2 60 440 2000 880 1000 440 1000 1320 500 880 2000;
#X obj 2 106 list split 2;
#X obj 90 173 spigot;
#X msg 123 145 0;
#X msg 152 149 1;
#X obj 2 37 t b b b;
#X msg 2 220 clear \, add pitch \$1 \, add duration \$2 \, bang;
#X obj 15 174 list;
#X connect 0 0 15 0;
#X connect 2 0 6 1;
#X connect 3 0 1 0;
#X connect 4 0 5 0;
#X connect 5 0 6 0;
#X connect 5 1 3 1;
#X connect 6 0 2 0;
#X connect 6 0 3 0;
#X connect 7 0 6 1;
#X connect 8 0 12 0;
#X connect 9 0 11 0;
#X connect 10 0 9 0;
#X connect 11 0 16 0;
#X connect 11 1 17 1;
#X connect 11 2 13 0;
#X connect 12 0 17 0;
#X connect 13 0 12 1;
#X connect 14 0 12 1;
#X connect 15 0 10 0;
#X connect 15 1 7 0;
#X connect 15 2 14 0;
#X connect 16 0 4 0;
#X connect 17 0 11 0;
#X restore 170 200 pd create-sequencer-data;
#X text 24 45 1 Sets the base URL.;
#X text 167 155 3 Creates some sequencer data and stores the data in pd-test. Objects contain "pitch" and "duration"., f 107;
#X text 328 189 4 Start sequencer and get first object;
#X obj 329 236 f;
#X obj 357 238 + 1;
#X obj 446 501 route pitch duration;
#X obj 418 533 pack f f f;
#X obj 338 627 unpack f f f;
#X obj 407 653 del;
#X obj 132 509 print data;
#X text 446 220 5 Get database pd-test;
#X text 446 275 6 Delete database pd-test;
#X msg 445 240 GET pdtest;
#X msg 72 134 PUT pdtest;
#X msg 170 224 PUT pdtest/\$1 \$2;
#X msg 448 293 DELETE pdtest;
#X msg 329 265 GET pdtest/\$1;
#X msg 329 208 0;
#X obj 338 570 spigot 1;
#X obj 750 503 spigot;
#X obj 783 469 tgl 15 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000 0 1;
#X obj 302 474 t b a b;
#X text 544 327 toggle only when using sequencer;
#X msg 302 506 0;
#X obj 372 673 osc~;
#X obj 433 720 *~ 0;
#X obj 433 746 dac~;
#X obj 391 436 json-decode;
#X obj 281 384 rest;
#X msg 23 65 init http://puredata:puredata@localhost:5984/;
#X text 3 14 This example uses a user named "puredata" and password "puredata" on a local instance that is able to create and delete databases., f 131;
#X text 70 100 2 Creates database pd-test on server with base URL. If you do not set the base URL \, then you can also issue this command with [PUT http://puredata:puredata@localhost:5984/pd-test/(, f 122;
#X obj 132 489 spigot;
#X obj 165 463 tgl 15 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000 0 1;
#X obj 199 249 print PUT-command;
#X connect 0 0 6 0;
#X connect 1 0 12 0;
#X connect 2 0 25 1;
#X connect 3 0 4 0;
#X connect 3 1 13 0;
#X connect 4 0 25 1;
#X connect 6 0 21 0;
#X connect 10 0 11 0;
#X connect 10 0 23 0;
#X connect 11 0 10 1;
#X connect 12 0 13 1;
#X connect 12 1 13 2;
#X connect 13 0 25 0;
#X connect 14 1 31 0;
#X connect 14 2 15 0;
#X connect 15 0 26 0;
#X connect 19 0 35 0;
#X connect 20 0 35 0;
#X connect 21 0 35 0;
#X connect 21 0 41 0;
#X connect 22 0 35 0;
#X connect 23 0 35 0;
#X connect 24 0 10 0;
#X connect 25 0 14 0;
#X connect 26 0 10 0;
#X connect 27 0 26 1;
#X connect 27 0 32 1;
#X connect 28 0 30 0;
#X connect 28 1 5 0;
#X connect 28 2 2 0;
#X connect 30 0 27 0;
#X connect 31 0 32 0;
#X connect 32 0 33 0;
#X connect 32 0 33 1;
#X connect 34 0 3 0;
#X connect 34 1 1 0;
#X connect 35 0 6 1;
#X connect 35 1 34 0;
#X connect 35 1 39 0;
#X connect 35 2 28 0;
#X connect 36 0 35 0;
#X connect 39 0 16 0;
#X connect 40 0 39 1;
#X restore 9 267 pd couchdb;
#X text 6 169 An example for a RESTful interface is CouchDB:;
#X obj 9 80 rest http://localhost:5984/;
#X text 6 114 The second outlet will output status information of the request.;
#X text 5 222 Here is a complex example for using [rest] to communicate with CouchDB. It uses GET \, POST and DELETE request methods. You will need to have a local installation of CouchDB.;
#X text 6 10 Set the base url at creation or use [init( message. An empty init message will clean a previous set base url. The number of possible parameters for [rest] and [oauth] differ. You can also use four parameters for the [init( message to use basic cookie authentication \, see below.;
#X restore 21 498 pd rest-specific;
#X text 594 369 By default correct SSL host is checked. Disable check by sending sslcheck with a value to 0 \, reenable checking by setting the value to 1;
#X msg 573 234 cancel;
#X text 628 271 Use this request to test cancelling and timeout: it will wait for 10 seconds before returning data.;
#N canvas 385 252 635 326 cancel 0;
#X obj 15 237 rest;
#X msg 115 145 cancel;
#X obj 190 106 t b b;
#X obj 190 77 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X msg 15 190 GET http://ix.residuum.org/pd/sleep_example.php;
#X obj 15 70 t b b;
#X obj 15 41 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X text 12 9 This won't always work \, as another thread will have to be signalled and must clean up.;
#X obj 97 289 print data;
#X obj 15 289 print status;
#X text 188 42 By experimentation \, I have found out that a delay of 20ms is sufficient on my system (TM).;
#X obj 187 152 del 20;
#X text 251 121 NOTE: For Windows the delay must be longer because of problems with cancelling threads from the outside \, so the object must use a different approach for cancellation.;
#X obj 97 267 spigot;
#X obj 130 241 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X connect 0 0 9 0;
#X connect 0 1 13 0;
#X connect 1 0 0 0;
#X connect 2 0 11 0;
#X connect 2 1 1 0;
#X connect 3 0 2 0;
#X connect 4 0 0 0;
#X connect 5 0 4 0;
#X connect 5 1 1 0;
#X connect 6 0 5 0;
#X connect 11 0 4 0;
#X connect 13 0 8 0;
#X connect 14 0 13 1;
#X restore 653 235 pd cancel;
#X text 628 165 You can cancel a currently executed request by issuing [cancel(. If data has been returned already \, but is not output \, or output only partially \, outputting the data will still be completed. Note \, that cancelling the call may take some time \, so do not try to issue a new request immediately. See;
#X text 19 259 [rest] is an object for communication with REST services. Request methods GET \, POST \, PUT \, DELETE \, HEAD \, OPTIONS \, PATCH and TRACE are available.;
#X text 19 455 HTTP requests are asynchronous. Do not expect a request to return data immediately. While one request is processed \, the object is blocked.;
#N canvas 358 174 423 340 download-to-file 0;
#X obj 17 237 rest;
#X text 14 10 Set the location \, where the file should be saved;
#X text 57 76 Downloaded data will write it to the file;
#X text 110 162 Clear the location;
#X msg 17 28 file /tmp/test.json;
#X msg 112 182 file;
#X obj 17 287 print done;
#X obj 101 287 print data;
#X msg 59 96 GET https://jsonplaceholder.typicode.com/posts;
#X obj 101 265 spigot;
#X obj 134 241 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X connect 0 0 6 0;
#X connect 0 1 9 0;
#X connect 4 0 0 0;
#X connect 5 0 0 0;
#X connect 8 0 0 0;
#X connect 9 0 7 0;
#X connect 10 0 9 1;
#X restore 21 578 pd download-to-file;
#X text 20 535 More functions:;
#N canvas 170 140 678 510 streaming-and-blocking 0;
#X obj 17 353 rest;
#X msg 17 142 mode stream;
#X msg 70 203 mode block;
#X text 72 182 This will reset the object to the default mode;
#X text 14 124 Setting the mode to streaming;
#X text 12 8 By default \, [rest] and [oauth] both output data only when the request has finished. Some services decide to keep an HTTP connection open and flush data to clients (streaming).;
#X text 12 59 To output that data when it is done \, use the [mode( message and set the mode to stream. The default mode is blocking mode. You can set the mode even during running requests.;
#X text 195 223 Example for a streaming webservice;
#X obj 17 433 print done;
#X obj 102 433 print data;
#X msg 197 245 GET https://ix.residuum.org/pd/stream_example.php;
#X msg 222 285 cancel;
#X obj 102 407 spigot;
#X obj 135 381 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X connect 0 0 8 0;
#X connect 0 1 12 0;
#X connect 1 0 0 0;
#X connect 2 0 0 0;
#X connect 10 0 0 0;
#X connect 11 0 0 0;
#X connect 12 0 9 0;
#X connect 13 0 12 1;
#X restore 21 600 pd streaming-and-blocking;
#N canvas 114 149 628 451 setting-headers 0;
#X obj 76 327 rest;
#X msg 191 226 GET https://api.github.com/repos/residuum/PuRestJson/contents/Makefile;
#X msg 74 62 header Accept: application/json;
#X msg 126 110 header User-Agent: My User Agent;
#X text 71 0 You can set arbitrary HTTP headers with the [header( message.;
#X text 180 155 To clear HTTP headers \, issue [header_clear(;
#X msg 182 172 header_clear;
#X text 71 32 Some webservices return different data types for different values of Accept: headers;
#X obj 158 389 print data;
#X obj 76 389 print done;
#X obj 238 389 print error;
#X text 125 90 Github requires User-Agent: header;
#X obj 158 367 spigot;
#X obj 191 341 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X connect 0 0 9 0;
#X connect 0 1 12 0;
#X connect 0 2 10 0;
#X connect 1 0 0 0;
#X connect 2 0 0 0;
#X connect 3 0 0 0;
#X connect 6 0 0 0;
#X connect 12 0 8 0;
#X connect 13 0 12 1;
#X restore 21 556 pd setting-headers;
#N canvas 696 177 899 593 proxy 0;
#X obj 291 442 rest;
#X msg 433 380 proxy;
#X text 460 46 This request returns the IP address of the connected computer;
#X text 433 219 You must always specify protocol \, server and port number.;
#X text 433 239 If your proxy needs a username and password \, add those delimited by spaces \, like;
#X msg 436 276 proxy protocol://server:port username password;
#X text 431 342 To clear proxy settings \, send a proxy message without any parameter to the object.;
#X msg 460 78 GET https://ix.residuum.org/pd/proxy_example.php;
#X msg 328 206 cancel;
#X obj 301 486 spigot;
#X obj 334 460 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X obj 301 509 print;
#X msg 58 188 proxy socks5://192.252.208.67:14287;
#X msg 37 248 proxy socks4://161.97.169.216:1080;
#X msg 125 142 proxy https://135.181.103.249:8888;
#X text 34 49 WARNING: all those proxies are from some dubious lists on the internet \, use at your own risk. These may not be up during the test.;
#X msg 62 114 proxy http://47.89.185.178:8888;
#X obj 455 486 print error;
#X text 34 356 Running TOR locally in standard configuration, f 23;
#X msg 35 388 proxy socks5://127.0.0.1:9050;
#X connect 0 1 9 0;
#X connect 0 2 17 0;
#X connect 1 0 0 0;
#X connect 7 0 0 0;
#X connect 8 0 0 0;
#X connect 9 0 11 0;
#X connect 10 0 9 1;
#X connect 12 0 0 0;
#X connect 13 0 0 0;
#X connect 14 0 0 0;
#X connect 16 0 0 0;
#X connect 19 0 0 0;
#X restore 21 622 pd proxy;
#X obj 623 576 print error;
#X obj 450 576 print done;
#X obj 529 577 print data;
#X msg 628 304 GET https://ix.residuum.org/pd/sleep_example.php;
#X msg 451 32 GET https://jsonplaceholder.typicode.com/posts;
#X text 19 349 All requests are issued with [REQUEST_METHOD URL DATA( where REQUEST_METHOD is the uppercase verb of the method \, URL is the request URL \, or the relative server path \, if [url( or initialization is used \, and DATA is the upload data for PUT or post data for POST. For creating url encoded lists of parameters see;
#X text 19 302 [oauth] is an object for communication with OAUTH enabled webservices. Request methods GET \, POST \, PUT \, DELETE \, HEAD \, OPTIONS and TRACE are available.;
#X obj 21 668 declare -path purest_json;
#X text 18 90 To mitigate that \, set the [spigot]s only to 1 \, if running Pd with the command line switch -stderr \, that will redirect the output to the command line instead of the Pd console.;
#X obj 529 555 spigot;
#X obj 562 531 tgl 18 0 empty empty empty 0 -9 0 10 #fcfcfc #000000 #000000 0 1;
#X text 18 132 Another strategy can be to use [text] for storing data for inspection.;
#X text 18 9 WARNING: [print]ing downloaded data to console may lead to undesired behaviour \, because it usually contains special characters such as curly braces \, backslashes \, or quotation marks that may be interpreted as tcl commands and therefore break the console or even crash Pd. Data from arbitrary URLs can also contain malicious data.;
#X obj 409 671 text define \$0-example;
#X obj 519 619 text insert \$0-example;
#X connect 2 0 27 0;
#X connect 2 1 35 0;
#X connect 2 1 40 0;
#X connect 2 2 26 0;
#X connect 4 0 2 0;
#X connect 5 0 2 0;
#X connect 6 0 2 0;
#X connect 7 0 2 0;
#X connect 15 0 2 0;
#X connect 29 0 2 0;
#X connect 30 0 2 0;
#X connect 35 0 28 0;
#X connect 36 0 35 1;

BIN
purest_json/rest.pd_linux Executable file

Binary file not shown.

1
purest_json/test.json Normal file
View File

@ -0,0 +1 @@
{ "firstName": "John", "lastName": "Smith", "age": 25, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": 10021 }, "phoneNumber": [ { "type": "home", "number": "212 555-1234" }, { "type": "fax", "number": "646 555-4567" } ] }

View File

@ -0,0 +1,28 @@
#N canvas 44 51 687 503 10;
#X declare -path purest_json;
#X msg 211 140 add id 1;
#X text 208 107 Will add key id and value of 1 to object;
#X msg 253 170 add name Residuum;
#X msg 299 266 add year 2011;
#X msg 316 320 add id 2;
#X msg 23 360 clear;
#X text 22 335 This will clear the object;
#X text 359 346 output the value;
#X msg 360 365 bang;
#X obj 47 16 urlparams;
#X obj 229 404 urlparams;
#X text 43 44 [urlparams] has three methods: add \, clear and bang. add adds a new key/value pair to the internally stored object. clear clears the internally stored object. bang outputs the stored object as urlencoded parameter string., f 78;
#X text 279 196 This will add a string with url encoded spaces and special characters;
#X obj 229 439 print;
#X msg 279 224 add anothername who will tweet to @residuummuc with hashtag #Pd?;
#X text 109 15 - create a list of URL encoded parameters for request parameters., f 67;
#X text 314 285 adding a different value will overwrite the previously stored one;
#X obj 14 478 declare -path purest_json;
#X connect 0 0 10 0;
#X connect 2 0 10 0;
#X connect 3 0 10 0;
#X connect 4 0 10 0;
#X connect 5 0 10 0;
#X connect 8 0 10 0;
#X connect 10 0 13 0;
#X connect 14 0 10 0;

BIN
purest_json/urlparams.pd_linux Executable file

Binary file not shown.