Hi!
Does anyone know of a simple way to receive the information printed on the console window?
I am using ann_mlp for a small neural network project, and I need to know when it is done training, which can take a very variable amount of time depending on the file I give it, and the complexity of the NN. My problem is that this object only displays this information on the console, it doesn't bang any outlet.
I have tried a few methods like [r pd], but I only got some pings and keypressed information...
Thank you!
-
Receive Pd Console data
-
@wqt I gave up a while ago trying to sniff the messages posted to the terminal. They are sent in the tcl/tk by the command type.......... ::pdwindow::post "hello "
Pd and wish communicate over tcp. It might be possible to sniff the port, filter the data, and get it back into a patch.......?
The messages go to stderr as well I think, or certainly can do if you start Pd with the startup flag -stderr.
That might be easier to get at through a re-direct? Again, how to get it back into the patch once you have captured it. Maybe send it to a port and bring it back in through [netreceive]?So like this (nearly)...... http://stackoverflow.com/questions/21430245/python-redirect-stdout-to-a-socket
@alexandros might chip in with a solution for you....
David. -
Thank you!
I will try to find the right port, I will let you know if I can find something. -
@wqt Good luck! I think it's port 54000.... but if you close Pd and open it again it will be 54001 (and etc.), as sys-wait will not open the same port again.
I managed to read the terminal output into a text file fairly easily. Unfortunately "print" messages are not sent until an error is printed (they are printed before, but not sent to stderr). It would be fairly trivial to print a stream of errors...... metro>float>symbol-inlet for example..... but that doesn't work. The error "unable to create" works though. Painful.
I am having trouble with piping the stderr onward to a socket at the moment (from the windows command line).
It needs to be a udp socket, as the batch file that receives stderr needs to open Pd....... and only then can Pd open [netreceive]..... hmm unsure, might be possible with tcp....?
David. -
Well, if it were me, I'd make a gui plugin. The proc that underlies everything that gets posted to the pdwindow is
pdwindow::logpost
So use introspection to overwrite it.set lp_args [info args pdwindow::logpost] set lp_body [info body pdwindow::logpost] #this is the part where you send a tcl message to pd append lp_body { pdsend "receive_name $message" } #then actually overwrite it. proc pdwindow::logpost $lp_args $lp_body
So replace receive_name with whatever name you'd like to use. Hopefully this will work with externals, i tried it with print. You'll have to route out other messages posted to the window.
If you have to use a unique identifier ($0) in the receive name, then.. I'll have to think about that..
-
@Monetus You should start a "plug-in on request" factory!
It works well in "extended" older tcl too.
It would be helpful if this plugin created a patch window containing an [r receive_name] object at load, which would avoid the error loop when it does not already exist.......... or maybe better........ as any errors in the handling of the received "logpost" within a patch also cause a message loop maybe error messages could be filtered in the plugin instead?
Simple testing patch......receive_pdwindow.pd
David.
-
@whale-av you're right. That is dangerous. Hmm.. I tried catching it, but pdsend probably already catches the error so, you could add a break statement to filter out that particular error message maybe...
Well, instead of creating a canvas dedicated to a receive, I figure that it would be best to make some 'functions' you could send to the pdwindow through print or something.
hmm.
variable pdwindow::receive_name {} set lp_args [info args pdwindow::logpost] set lp_body [info body pdwindow::logpost] append lp_body { # find 'function' names if {[lindex $message 1] eq "set_receive"} { set pdwindow::receive_name [lindex $message 2] return } if {$pdwindow::receive_name ne ""} { #this is the part where you send a tcl message to pd pdsend "$pdwindow::receive_name $message" } }
So maybe this will work. It doesn't explicitly check to see if the object exists, which could be dangerous if you deleted the object. It does allow you to set the receive name though. Just send a [set_receive receive_name( message to print.
-
No luck with the last post so far......
For anyone watching the first post by @monetus works very well if Pd is started from this patch receive_pdwindow.pd while his plugin...... send_back-plugin.tcl is somewhere to be found in the Pd paths.
If the plugin is active (found by Pd) and another patch starts Pd then Pd will effectively crash and need to be killed.
Pd will need to be started by a patch that contains a [receive receive_name] object...
David -
@whale-av Maybe it was because I didn't add the whole code..
Well, when I printed the message arg from logpost into the console (not the pdwindow) I found that it doesn't print the entirety of the message in one function call.
So you can't rely on any index of the message arg past 1 being what you expect...variable pdwindow::receive_name {} set lp_args [info args pdwindow::logpost] set lp_body [info body pdwindow::logpost] append lp_body { # find 'function' names puts msg:\ [llength $message]\n$message\n if {[lindex $message 0] eq "set_receive:"} { set pdwindow::receive_name [lindex $message 1] return } if {$pdwindow::receive_name ne ""} { #this is the part where you send a tcl message to pd pdsend "$pdwindow::receive_name $message" } } proc pdwindow::logpost $lp_args $lp_body
This works for me, and it doesn't produce an infinite loop if pdsend posts an error. Try it out.
EDIT:: remember to get rid of that puts statement. I forgot to.
-
@monetus the last GUI works when I start Pd normally (I get one error and then it works), but not when I start it from receive_pdwindow.pd (I get a few errors and then it doesn't respond).
-
@monetus Oh I guess I should copy your patch instead?
-
@wqt you have to be careful overwriting this proc we are playing with, because if anything goes wrong in the beginning, pd's gui doesn't get connected to pd's internal process.
The second plugin was an attempt to expose tcl procs to the print object. This is potentially really nifty, thanks for having this problem. Anyways, the way the second plugin works is that you have to send a name to a print object named set_receive. From then on, any print message will be sent to that receive. Print after having deleted that object and you could start an infinite loop.
The if statement
if {$pdwindow::receive_name ne ""}
should keep an infinite loop from happening while the receive exists, or before it has been initialized, So I'm not sure whats happening. Need more info.. hmm. -
@wqt I had spotted and added in the missing line, but not understood the code.....
The patch was required!...... receive_pdwindow_new.pd......... and......... new_monetus-plugin.tcl
Thank you for the lessons @monetus! It works very well. My only coding was Fortran in the 1970's, which helps a little, but my understanding is progressing very slo__wl_y.Here as an abstraction and accessories for demo purposes........print_window.zip
Do not delete the [r_print] abstraction and do not close the container patch and then open another....... always close Pd before you continue working.
David.