[PD] pd -> php
Max Neupert
abonnements at revolwear.com
Sat Oct 7 14:19:04 CEST 2006
merci patco,
i have a hard time to spot your modifications in the semi-human-
readable php code without line breaks. could you paste it formatted
or just the changes?
thank you.
Am 07.10.2006 um 03:27 schrieb Patco:
> Patco a écrit :
>> Max Neupert a écrit :
>>> hi list,
>>>
>>> i am trying to send a value from pd to a php page.
>>> i am using an udp connection vie netsend to fsockopen().
>> Hello, there is a php class for that:
>> http://www.a2hd.com/software/OSC.phps
>> The end of the file have to be modified, I've tested it once it's
>> more stable than netsend.
> attached is the modified php file
> Patco.
> * Copyright 2003 * * Version 0.1 * * Requirements: PHP 4.1.0 or
> later. * For information about Open Sound Control, * see http://
> cnmat.berkeley.edu/OSC * * This is free software. * It may contain
> bugs, design flaws or other unforseeable problems. * Please feel
> free to report problems (or success stories) to the author. * *
> License: LGPL version 2.1 or later. * * This library is free
> software; you can redistribute it and/or * modify it under the
> terms of the GNU Lesser General Public * License as published by
> the Free Software Foundation; either * version 2.1 of the License,
> or (at your option) any later version. * * This library is
> distributed in the hope that it will be useful, * but WITHOUT ANY
> WARRANTY; without even the implied warranty of * MERCHANTABILITY or
> FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General
> Public License for more details. * * You should have received a
> copy of the GNU Lesser General Public * License along with this
> library; if not, write to the Free Software * Foundation, Inc., 59
> Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For
> questions regarding this library contact * Andy W. Schmeder */ //
> Test if this machine is a little endian architecture function
> test_little_endian() { $cpu_int = pack("L", 1); // Machine
> dependent $be_int = pack("N", 1); // Machine independent if($cpu_int
> [0] == $be_int[0]) { return FALSE; } else { return TRUE; } } //
> Test if this machine uses twos complement representation function
> test_twos_complement() { $cpu_int = pack("i", -1); // Machine
> dependent if(ord($cpu_int[0]) == 255) { return TRUE; } else
> { return FALSE; } } // Take note of the configuration for this
> machine. $_arch_little_endian = test_little_endian();
> $_arch_twos_complement = test_twos_complement(); if(!
> $_arch_twos_complement) { trigger_error("WARNING: This machine does
> not use twos-complement integers. " . "Negative numbers may not be
> represented correctly.", E_USER_NOTICE); } /** This is a utility
> function to convert from CPU byte order to network order (big
> endian). * * It is necessary to use this function because PHP's pack
> () function does not support * big endian encoding for most data
> types. (It only does big endian for unsigned ints). */ function
> host_to_network_order($str) { global $_arch_little_endian; if
> ($_arch_little_endian) { $swstr = ""; for($i = 0; $i < strlen
> ($str); $i++) { $swstr .= $str[(strlen($str)-1)-$i]; } return
> $swstr; } else { // No conversion necessary for big-endian arch
> return $str; } } /** OSCDatagram is a virtual base class for
> OSCMessage and OSCBundle. */ class OSCDatagram { // Virtual private
> data var $bin = NULL; var $data = NULL; // Virtual functions
> function get_binary() {} function clear() {} // Shared functions /
> ** Returns a semi-human readable representation of the binary data.
> * Printable bytes will appear as "_C" where C is the printable
> character. * Non-printable bytes will appear in hex, e.g. '20' for
> a space (\s) character * Bytes are clustered in groups of 4 to show
> the alignment. */ function get_human_readable() { $bin = $this-
> >get_binary(); $hex = ""; for($i = 0; $i < strlen($bin); $i++) { if
> (ord($bin[$i]) >= 33 && ord($bin[$i]) <= 126) { // Printable
> characters $hex .= "_" . chr(ord($bin[$i])); } else { $hex .=
> sprintf("%02x", ord($bin[$i])); } if($i != 0 && $i < strlen($bin)
> && ($i+1) % 4 == 0) { $hex .= " "; } } return $hex . "\n"; } /**
> Pack data into $this->bin as 4-byte aligned, network-byte order. */
> function pack_data($data, $type_hint) { $bin = ""; switch
> ($type_hint) { case "T": case "F": case "N": case "I": return; //
> These types have no allocated space case "A": foreach($data as
> $arg) { $this->pack_data($arg[0], $arg[1]); } break; case "s":
> $data .= "\0"; // The builtin \0 terminator is ignored... we must
> explicitly request one. $bin = pack("a*" . $this->get_strpad
> ($data), $data); break; case "b": $this->pack_data(strlen($data-
> >bin), "i"); $bin = pack("a*" . $this->get_strpad($data->bin),
> $data->bin); break; case "i": $bin = host_to_network_order(pack
> ("i", $data)); // Machine-independent size (4-bytes) break; case
> "f": $bin = host_to_network_order(pack("f", $data)); // Machine-
> dependent size if(strlen($bin) != 4) { $this->error("Sorry, your
> machine uses an unsupported single-precision floating point
> size."); } break; case "d": $bin = host_to_network_order(pack("d",
> $data)); // Machine-dependent size if(strlen($bin) != 8) { $this-
> >error("Sorry, your machine uses an unsupported double-precision
> floating point size."); } break; case "t": if(is_null($data))
> { $data = array(0, 1); } $bin = host_to_network_order(pack("L",
> $data->sec)) . host_to_network_order(pack("L", $data->frac_sec));
> break; } if(strlen($bin) % 4 != 0) { $this->error("$data failed to
> align properly, size is " . strlen($bin) . " bytes."); } $this-
> >bin .= $bin; } /** Utility to generate padding for strings */
> function get_strpad($str) { $x = (strlen($str)) % 4; if($x == 0)
> { return ''; } else { $x = 4 - $x; } switch($x) { case 1: return
> 'x'; case 2: return 'xx'; case 3: return 'xxx'; default: $this-
> >error("Pad calculation is screwy, x = $x"); } } /** Report an
> error */ function error($message) { trigger_error("OSCDatagram
> Error: $message", E_USER_ERROR); } } /** OSCMessage type */ class
> OSCMessage extends OSCDatagram { var $address = "/"; var
> $typetags = ","; var $data = array(); /** Make a new message -
> Optionally specify address and arguements. * * e.g. $a = new
> OSCMessage("/foo", array(1, 2.94, "bar")) * It is not possible to
> provide type-hinting using this initialization method. */ function
> OSCMessage($address = NULL, $args = NULL) { if(! is_null($address))
> { $this->address = $address; } if(is_array($args)) { foreach($args
> as $arg) { $this->add_arg($arg); } } } /** Reset internal data
> structures */ function clear() { $this->address = "/"; $this-
> >typetags = ","; $this->data = array(); $this->bin = NULL; } /**
> Set packet address * e.g. "/test". * See OSC spec for details on
> allowed characters in an OSC address. */ function set_address
> ($addr) { $this->bin = NULL; $this->address = $addr; } /** Add an
> arg to the OSC message. * $data can be an integer, float, string,
> boolean, NULL, or an array of those types. * $type-hint is
> optional. */ function add_arg($data, $type_hint = NULL) { $this-
> >bin = NULL; if($type_hint == NULL) { $type_hint = $this->get_type
> ($data); } $data = $this->set_type($data, $type_hint); array_push
> ($this->data, array($data, $type_hint)); } /** Try to guess the
> type of data. * If this does not work for you, try using a type-
> hint. */ function get_type($data) { switch(gettype($data)) { case
> "integer": return "i"; case "double": case "float": return "f";
> case "string": return "s"; case "boolean": if($data) { return
> "T"; } else { return "F"; } case "array": // Array type will be
> handled later... 'A' is not actually an OSC type. return "A"; case
> "object": switch(strtolower(get_class($data))) { case "infinitum":
> return "I"; case "timetag": return "t"; case "blob": return "b";
> default: $this->error("Unknown or unsupported object type."); }
> case "NULL": return "N"; default: $this->error("Unknown or
> unsupported data type."); } } /** Cast data to type, and add type
> info to typetags. */ function set_type($data, $type_tag) { switch
> ($type_tag) { case "i": $this->typetags .= "i"; return (int)$data;
> case "f"; $this->typetags .= "f"; return (double)$data; case "d";
> $this->typetags .= "d"; return (double)$data; case "s": case "c":
> $this->typetags .= "s"; return (string)$data; case "T": $this-
> >typetags .= "T"; return TRUE; case "F": $this->typetags .= "F";
> return FALSE; case "N": $this->typetags .= "N"; return NULL; case
> "I": $this->typetags .= "I"; return $data; case "t": $this-
> >typetags .= "t"; return $data; case "b": $this->typetags .= "b";
> return $data; case "A": // Array is now expanded... $this-
> >typetags .= "["; $data = (array)$data; for($i = 0; $i < count
> ($data); $i++) { $type_tag = $this->get_type($data[$i]); $data[$i]
> = array($this->set_type($data[$i], $type_tag), $type_tag); } $this-
> >typetags .= "]"; return $data; default: trigger_error
> ("Unrecognized type tag, '$type_tag'", E_USER_ERROR); } } function
> get_binary() { // Check for cached binary representation and reuse
> if found. if(! is_null($this->bin)) { return $this->bin; } // Pack
> address... $this->pack_data($this->address, "s"); // Pack
> typetags... $this->pack_data($this->typetags, "s"); // Pack args...
> foreach($this->data as $arg) { $this->pack_data($arg[0], $arg
> [1]); } return $this->bin; } } /** OSCBundle datagram type * This
> object can contain any number of other OSCDatagram objects. */
> class OSCBundle extends OSCDatagram { var $data = array(); var
> $timetag = NULL; /** Create a new OSCBundle datagram * * $init may
> be an array of OSCDatagram objects, * e.g. $b = new OSCBundle(new
> OSCMessage(...), new OSCBundle(...)) * * Otherwise, add messages at
> runtime using OSCBundle::add_datagram. */ function OSCBundle($init
> = NULL) { if(is_array($init)) { foreach($init as $d) { $this-
> >add_datagram($d); } } } /** Set time tag as whole seconds since
> July 1, 1970, and fraction of a second. * This feature is not
> tested, but it should work if you need it. * * If timetag is not
> set, it will default to "Immediate". */ function set_timetag
> ($timetag_obj) { $this->timetag = $timetag_obj; } /** Add an
> OSCDatagram object to a bundle. * This can be either an OSCMessage
> or an OSCBundle. * However, you cannot reasonably add a bundle to
> itself. */ function add_datagram($osc_datagram) { $this->bin =
> NULL; array_push($this->data, $osc_datagram); } function clear()
> { $this->bin = NULL; $this->data = NULL; } function get_binary()
> { if($this->bin != NULL) { return $this->bin; } $this->bin = "";
> $this->pack_data("#bundle", "s"); $this->pack_data(NULL, "t");
> foreach($this->data as $datagram) { $bin = $datagram->get_binary();
> $this->pack_data((int)strlen($bin), "i"); $this->bin .= $bin; }
> return $this->bin; } } /** OSCClient uses a connectionless UDP
> socket to transmit binary to its destination. * * Example of use: *
> * $c = new OSCClient(); * $c->set_destination("192.168.1.5", 3890);
> * $c->send(new OSCMessage("/foo", array(1,2,3))); * ... etc. * *
> Since it is connectionless, you can change the destination address/
> port at any time. * If you are having problems establishing
> communication, it may be due to a bad address, * improper setup of
> the IP routing table, or a problem on the other end. When in doubt,
> * use tcpdump or ethereal to check that packets are indeed being
> transmitted. */ class OSCClient { var $sock = NULL; var $address
> = NULL; var $port = NULL; function OSCClient($address = NULL, $port
> = NULL) { $this->address = $address; $this->port = $port; if(($this-
> >sock = socket_create(AF_INET, SOCK_DGRAM, 0)) < 0) { $this->error
> ("Could not create datagram socket."); } } /** Destructor function,
> usually not needed, provided in case you want to free the socket.
> */ function destroy() { socket_close($this->sock); } /* // You can
> enable this part if you have PHP 4.3.0 or later... function
> enable_broadcast() { if(($ret = socket_set_option($this->sock,
> SOL_SOCKET, SO_BROADCAST, 1)) < 0) { $this->error
> ("Failed to enable broadcast option."); } } function
> disable_broadcast() { if(($ret = socket_set_option($this->sock,
> SOL_SOCKET, SO_BROADCAST, 0)) < 0) { $this->error("Failed to
> disable broadcast option."); } } */ /** Address is an IP address,
> given as a string. * To convert a hostname to IP, use gethostbyname
> ('www.example.com') * You must also specify a port as an integer,
> typically $port is larger than 1024. */ function set_destination
> ($address, $port) { $this->address = $address; $this->port =
> $port; } /** send() accepts either an OSCDatagram object or a
> binary string */ function send($message) { if(is_null($this-
> >address) || is_null($this->port)) { $this->error("Destination is
> not well-defined. Please use OSCClient::set_destination()."); } if
> (is_object($message)) { $message = $message->get_binary(); } if
> (($ret = socket_sendto($this->sock, $message, strlen($message), 0,
> $this->address, $this->port)) < 0) { $this->error("Transmission
> failure."); } if($ret != strlen($message)) { $mlen = strlen
> ($message); $this->error("Could not send the entire message, only
> $ret bytes were sent, of $mlen total"); } return $ret; } /** Report
> a fatal error. */ function error($message) { trigger_error
> ("OSCClient Error: $message", E_USER_ERROR); } } /** Object to
> represent the OSC Infinitum type ("I") */ class Infinitum { } /**
> 64-bit OSC timetag type, Refer to NTP format for details. */ /
> **class Timetag { function Timetag($sec = 0, $frac_sec = 1) { $this-
> >sec = $sec; $this->frac_sec = $frac_sec; } }*/ /** Binary Blob
> datatype * Blob is basically a non-null-terminated string prefixed
> by a size indicator. */ class Blob { function Blob($bin) { $this-
> >bin = $bin; } } /** Run some tests to make sure the library
> behaves in a sane way. the modifications begins here replace
> localhost with server's adress and put the correct port */ function
> test_osc_lib() { $c = new OSCClient(); $c->set_destination
> ("localhost", 3333); /** $m1 = new OSCMessage("/test", array(new
> Timetag(3294967295, 5), new Infinitum(), new Blob("aoeuaoeu!")));
> $m1->add_arg(28658.93, "d"); */ $m2 = new OSCMessage("/bar", array
> (test, one, two)); $b = new OSCBundle(); $b->add_datagram($m1); $b-
> >add_datagram($m2); $b2 = new OSCBundle(array($m1, $b)); //echo $b2-
> >get_human_readable(); //echo $m1->get_human_readable(); $c-
> >send($m2); } // Uncomment to run the test test_osc_lib(); ?>
More information about the Pd-list
mailing list