-
Monetus
Hmm.. @whale-av. You could route out all the other selectors you have. Or play around with some form of type checking..
-
Monetus
Also, in regards to editing pd's messages. I'm pretty sure that is entirely in c, so you would have to fork pd and recompile it with your changes.
Since messages are one of the original things in pd, I bet its tangled up in a lot of other code... but it might not be hard. If it were me though, I'd just try get used to the [list prepend ] -- [list trim ] combo, as you can have mutating messages with just a list object.
Really the only things I use messages for anymore are loadbanging things before audio starts, and string manipulation. With strings, I use it rarely too; I tend to just use [list fromsymbol ] --- logic --- [list tosymbol ].
It looks like more clutter, and it can be weird when you have an object that needs a selector or doesn't, but its faster than plain messages. You can store big messages too, like [list prepend set $0-sine ] -- [list trim ] will set a tabread object.
edit:: you can do anything the zl objects can do with the list objects and some logic. Try making something recursive. Careful not to crash pd though. The list-abs library has some premade patches, some are bulkier than I would use, so you can trim them down to your liking.
-
Monetus
Well, pd's messages are weird. I haven't looked, but I kinda assume the code is inefficient as using a single message is slower than using a [list prepend ] -- [list trim ] combo.
This bears repeating because it is the opposite of what you would probably intuit.
Messages are slower than the list objects.
This might change, as the list objects are new compared to messages, but the code for messages probably has to sanitize a lot more inputs than the list objects...
Also fyi, the prepend and append objects are part of the cyclone library and are not part of vanilla.The reason why you would use the list objects rather than messages really just comes down to pd's semi-explicit typing. Some objects need to know what kind of input is coming so they need a selector like list, symbol, float, set, etc. Other objects just interpret whats coming at them so they don't need a selector.
-
Monetus
I never had to install anything on mac to get vanilla to work. I may have installed xquartz when I installed mac's devtools, but I'm pretty sure I already had pd downloaded at that point. The only thing about mac that sucks is that tcl/tk (the stuff used to make pd's interface) is usually version 8.4.
That should make zero difference to the sound though.
[loadbang ] -- [; pd dsp 1 (
^ If you want to make it a no brainer for him.
edit: since I mentioned tk, might as well point out that you can download a version of pd with tk 8.6 built into it. Having trouble finding the link atm, but its on the forum here somewhere. Danomatika's distributing it.
-
Monetus
Here is a control rate lfo I had in one of my patches.
I just used my oscillators' waveforms.
If you aren't actually storing some waveforms, then using a [sin] object would be the way to go. ...Basically just a choice between ram and cpu.
If you are switching the tabread between multiple arrays, then you need to control where the start and end points of the read will be.
In the pic above, the tabread goes from -1 to 1 and back by skipping the first and last quarter of the sine wave's cycle. Use two [sel ] and [f ] objects if you need to change those indices.
-
Monetus
@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. -
Monetus
@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
@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.
-
Monetus
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
I used an array of symbols in a struct with a drawnumber object to make a symbol slider. If you wanted to avoid the structs, you could indeed use a vslider underneath a canvas to feed indices into a [text get] object.
To make the menu actually popup, you'd have to create an object with a tcl/tk plugin, or make an external.
I played with the idea of making a popup menu in the tcl/tk objects, but I was making an autocomplete plugin, and settled on just drawing into the canvas itself. Lots of cool things you can do with plugins or structs.
-
-
Monetus
Sorry its taken me so long, I've been without internet.
I went ahead and created a plugin for you. It has a bunch of comments and guides through the code. Please post if you don't understand anything, its not as direct as your code.
I'm going to make a gui to edit ALL hotkeys and add new ones, but I hadn't worked every part out yet.
I'll post when I do.
-
Monetus
so, the way you have used the bind command is perfectly fine, I was only suggesting a proc if you wanted to be able to toggle the hotkeys back and forth while pd is running.
And yes, you can use tcl to send pd messages and create objects. For the gui objects, the menu_send and menu_send_float commands are all you need to make sure bind is triggering. If you wanted to make specific objects or abstractions be bound to a hotkey, you need to create the obj then trick pd into thinking you typed something in. You do this with the pdsend command.
pdsend "$mytoplevel key 1 $keynum 0"
look at my github, the rename_obj proc. also look at the embedded button bar plugin buried in the pdsite.
-
Monetus
There are a million ways to learn programming, and I have yet to be convinced there is a best way. Libpd currently has an API for C, Java, Objective-C, C++, Python, and C#. Definitely read the wiki on libpd's github.
Since you mentioned making plugins, I'd look into which languages the particular development kits use. Then I'd go over to r/learnprogramming on reddit to read some of their resources and ask around. Download some ebooks about the language you want to learn too. O'reilly media usually has a bunch for free.
There is a difference between knowing the syntax/paradigms of a language and actually knowing how to use it, so definitely try to do things as you learn.
I'd suggest C++, but thats just me.
-
Monetus
Sorry, didn't mean to discourage you, its completely doable and within the BSD license. Its actually one of the points of the BSD license imo. It is, as you say, a language. I was just trying to emphasize that there are ways to do it nicely, or ways to do it that will infuriate everyone.
For example, I've seen where people are mad at enzein audio for even making their proprietary compiler. They offer it for free non commercially, but just having all that valuable code locked away irks some people. I think though, if you make money off of pd, you're likely to spend time making it better. Just find ways to help the community and you'll be fine.
I would use libpd. You don't have to rewrite your program in C, as libpd lets you just load the patch and run it. You have to make your own GUI to control it however. Go into the issues on libpd however; right now it doesn't support multiple instances because there are global variables, which is bad for AU/VSTs. You'd have to clean that up for plugins, but not for a standalone.
-
Monetus
Note that making money off of open source software and not contributing back to the code or community is highly frowned upon.
There is a saas that offers their proprietary compiler. You'd have to purchase licensing from them though if you wanted to use it commercially: enzien audio's Heavy.
You can embed libpd, which is pd without the GUI, inside your software.
You could implement some sort of copyright protection on a custom version of pd that only loads your patch. This would piss people off. Don't do that.
-
Monetus
If you have the time to process the sample, you could just count all the zero crossings, set the loop points you'd like to be perfectly zero instead of the +/- 1-6e they usually are, and record those indices in another array. You'd have to be sure that the four point interpolation in tabread4 doesn't mess you up though. Hadn't played with that math before.
-
Monetus
Well, the first 4 couplets are octaves apart and the last two are unisons. You could pitch shift the e,a,d,g strings up an octave. You'd probably want to make sure the phases are just slightly apart too. The particulars of implementing that though could be varied.