/usr/lib/puredata/tcl/pd_connect.tcl is in puredata-gui 0.46.7-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | package provide pd_connect 0.1
namespace eval ::pd_connect:: {
variable pd_socket
variable cmds_from_pd ""
variable plugin_dispatch_receivers
namespace export to_pd
namespace export create_socket
namespace export pdsend
namespace export register_plugin_dispatch_receiver
}
# TODO figure out how to escape { } properly
proc ::pd_connect::configure_socket {sock} {
fconfigure $sock -blocking 0 -buffering none -encoding utf-8;
fileevent $sock readable {::pd_connect::pd_readsocket}
}
# if pd opens first, it starts pd-gui, then pd-gui connects to the port pd sent
proc ::pd_connect::to_pd {port {host localhost}} {
variable pd_socket
::pdwindow::debug "'pd-gui' connecting to 'pd' on localhost $port ...\n"
if {[catch {set pd_socket [socket $host $port]}]} {
puts stderr "WARNING: connect to pd failed, retrying port $host:$port."
after 1000 ::pd_connect::to_pd $port $host
return
}
::pd_connect::configure_socket $pd_socket
}
# if pd-gui opens first, it creates socket and requests a port. The function
# then returns the portnumber it receives. pd then connects to that port.
proc ::pd_connect::create_socket {} {
if {[catch {set sock [socket -server ::pd_connect::from_pd -myaddr localhost 0]}]} {
puts stderr "ERROR: failed to allocate port, exiting!"
exit 3
}
return [lindex [fconfigure $sock -sockname] 2]
}
proc ::pd_connect::from_pd {channel clientaddr clientport} {
variable pd_socket $channel
::pdwindow::debug "Connection from 'pd' to 'pd-gui' on $clientaddr:$clientport\n"
::pd_connect::configure_socket $pd_socket
}
# send a pd/FUDI message from Tcl to Pd. This function aims to behave like a
# [; message( in Pd or pdsend on the command line. Basically, whatever is in
# quotes after the proc name will be sent as if it was sent from a message box
# with a leading semi-colon.
proc ::pd_connect::pdsend {message} {
variable pd_socket
append message \;
if {[catch {puts $pd_socket $message} errorname]} {
puts stderr "pdsend errorname: >>$errorname<<"
error "Not connected to 'pd' process"
}
}
# register a plugin to receive messages from running Pd patches
proc ::pd_connect::register_plugin_dispatch_receiver { nameatom callback } {
variable plugin_dispatch_receivers
lappend plugin_dispatch_receivers($nameatom) $callback
}
proc ::pd_connect::pd_readsocket {} {
variable pd_socket
variable cmds_from_pd
if {[eof $pd_socket]} {
# if we lose the socket connection, that means pd quit, so we quit
close $pd_socket
exit
}
append cmds_from_pd [read $pd_socket]
if {[string index $cmds_from_pd end] ne "\n" || \
![info complete $cmds_from_pd]} {
# the block is incomplete, wait for the next block of data
return
} else {
set docmds $cmds_from_pd
set cmds_from_pd ""
if {![catch {uplevel #0 $docmds} errorname]} {
# we ran the command block without error, reset the buffer
} else {
# oops, error, alert the user:
global errorInfo
switch -regexp -- $errorname {
"missing close-brace" {
::pdwindow::fatal \
[concat [_ "(Tcl) MISSING CLOSE-BRACE '\}': "] $errorInfo "\n"]
} "^invalid command name" {
::pdwindow::fatal \
[concat [_ "(Tcl) INVALID COMMAND NAME: "] $errorInfo "\n"]
} default {
::pdwindow::fatal \
[concat [_ "(Tcl) UNHANDLED ERROR: "] $errorInfo "\n"]
}
}
}
}
}
|