[struct] / [pointer] object limitation?
I'm also curious about what triggers the Stack Overflow.
A safety mechanism that puts an upper limit on how deep an immediate "chain reaction" can be in response to an event like a mouse click, key press, netreceive, or clock callback (.e.,g. a bang coming from [delay 1000]
). When I say "chain reaction", I mean an initial message to an object triggers an outgoing message to another object, and so on until there are no more outgoing messages to process. When I say "immediate", I mean the messages get sent without any logical time in between.
Here's an example:
[bng]
|
[bng]
|
[bng]
If you clicked the object chain above, you get an immediate chain reaction 3 objects deep.
Now, if you extended that chain so that there were 1001 [bng] objects-- each with a single connection to the next-- you'd get a stack overflow error because it exceeds the limit Pd puts on how deeply a single message is allowed to flow in an immediate chain reaction.
The way Pd is coded, these simple examples actually end up using recursive function calls in C. Using recursion with too many levels can end up overflowing the stack and cause a crash, which is why you get that particular error message. (1000 may be too small a number nowadays, but recursion is complex and I'm not sure how one would come up with a better number.)
When you use recursion explicitly in a Pd diagram-- that is, hooking an object's outlet to an inlet that is back up the chain-- you make it way more likely to hit this particular error. You can imagine that your recursive diagram ends up "unrolling". That is, if you have a chain of 4 objects where the bottom one connects back into the top one and recursing 251 times, you're going to hit a stack limit and get the error.
The [until]
object solves this "explicit" recursion problem-- it sends a bang to its outlet, and when the resulting immediate chain reaction has finished it sends another until the specified limit is reached.
So if you have this:
[10000(
|
[until]
|
[bng]
|
[bng]
|
[bng]
You go two objects deep for the bang coming out of [until]
, then three more for the first time through the chain of [bng]
objects. So now we're 5 deep. But once the first iteration of the [bng]
objects are done they unroll, so we're back to being just 2 levels deep. Then the [until]
object starts its next iteration, which goes 3 more deep, then unrolls. It can do this indefinitely, which is why [until]
is preferred over using recursive object chains in Pd.
Max style messages (set via right inlet)
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.
Max style messages (set via right inlet)
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.
Pure Data noob
Ok...... So I have been meaning to do this for a very long time......
I don't think it is the perfect "show_me_dollars" and so I will change it from time to time.
3rd attempt.........
show_me_dollars.zip
Here is a really terrifying screenshot, but I have also tried to explain it in words.
In many ways I think words ( below the screenshot) are easier to understand.
David.
Dollar $ variables in Pure Data patches.
A dollar variable is a thing that can be given a new value.
The new value can be a float or a symbol.
- If the Dollar variable is in an [object] box
A Pd patch can be saved and used inside another patch. We then call it an abstraction.... and it is just like a programming sub-routine.
If you want to use it many times then you have a problem, that they are all the same, so if you put an object [receive woof] they will all receive any message that you send with [send woof].
That might well be what you want to do.
But what if you want to send the message to only one of them?
You can give it an [inlet], but your patch will get messy, and what if your patch needs to make its own mind up about which abstraction it wants to send the message to, maybe depending on which midi note it received?
The solution is to give the abstraction arguments... some parameters that define it and make it different to the other copies.
For example [my_abstraction]
Let’s give it some arguments [my_abstraction 5 9 woof]
Inside the abstraction, as it is created (you open its parent patch) the dollar variables will be replaced. Wherever you see $1 written IN AN OBJECT it has been replaced by the number 5.
Number 5 because 5 is the first argument and has actually replaced the $1. You still see $1, but if you bang a [$1] object it will output 5.
[f $2] will output 9
[symbol $3] will output woof
So if you have an object [receive $1-$3] then it has now become [receive 5-woof]
And if you want to send it a message from outside, from another patch or abstraction, you will need to use [send 5-woof]
Every Pd patch, which remember includes your abstractions, also has a secret number. The number is unique and greater than 1000. As Pd opens each patch it gives it the number, increased by one from the last number it gave.
That number will replace $0 as the patch is created. You can find out what the number is by banging a [$0] object and connecting its output to a number box, or [print] object.
$0 can be used in any object as part of the name or the address, which means that a message cannot escape from the abstraction. A sub-patch like [pd my-subpatch] will be given the same number.
But from outside your abstraction you don’t know what it will be when the patch is created, so it is not useful. (A lie, you can find out, but as it can change every time you open your patch it is not worth the bother).
Use it to send messages within your patch [send $0-reset] to [receive $0-reset] for example, because the message is absolutely unique to its window, so you know it cannot interfere with other abstractions.
Use it also for objects like [delwrite~ $0-buffer 100] or for an array name [array $0-array] so that in each abstraction they have a different name and you will not have problems with their being "multiply defined"...... as each name can only exist once in your patch.
- If the Dollar $ variable is in a [message( box
Dollar $ variables are also replaced, but not as the patch is created (drawn by Pd as you open it).
Dollar zero $0 has no meaning in a message box. It will produce a zero if the message is banged, but that is it.
It is a mistake, a patching error, to put a $0 in a message box.
$1 $2 $3 $4 etc. in a message box are replaced by incoming atoms (individual floats or symbols or whatever) when they arrive. $1 will be replaced by the first atom in the list, $2 the second etc.
So if you have a message box [$1 $2 $3( ..... and you send into it a list [3 48 lala( .....then it will output 3 48 lala
That is not really very useful.
But it is actually very powerful.
Make a list in a message box........ [33 12 wav(
And bang it into a message box [open my-track$2-$1.$3( and you will get the output.........
open my-track12-33.wav
Which could be just the message that you want to send to [soundfiler]
P.S. If the first item in the incoming list is a symbol then it will be dropped causing errors.
You can fix that by making the message a list by passing it through the object [list].
Unfortunately only messages starting with a float are automatically recognised as lists.
C74 and my definitive Return2Pd
Again C74 shits on your users, as he makes enough with Pluggo.
Arbitrary changes and are not consulted frequently, but a change of license which means C74 owns everything that is created in Gen development tool, it really is a gesture of usury only expect from a corporation like Microsoft.
Many users have been developing in Gen since leaving, and read attentively the license before investing money, time and other resources to learn and develop.
/****************************************
Copyright (c) 2012 Cycling ’74
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.
*****************************************************/
/**********************************
Cycling ’74 License for Max-Generated Code for Export
Copyright (c) 2016 Cycling ’74
The code that Max generates automatically and that end users are capable of exporting and using, and any
associated documentation files (the "Software") is a work of authorship for which Cycling ’74 is the author
and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a
copy of the Software ("Licensee") to use, copy, modify, merge, publish, and distribute copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the
Software must contact the copyright owner to determine if a license for commercial use is available, and the
terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries
to licensing (at) cycling74.com. The determination of whether a use is commercial use or non-commercial use is based
upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or
other business whether for-profit or non-profit so long as the use itself is not a commercialization of the
materials or a use that generates or is intended to generate income, revenue, sales or profit.
The above copyright notice and this license 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 NON-INFRINGEMENT. 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.
*****************************************************/
Anyway
My return to Pd...
Pd Internal Messages "remove object"
There are 3 options that I am aware of:
-
Easiest but not Vanilla: [iemguts/canvasdelete]. Once this object is loaded, you can send a delete message to the canvas, ie. "delete 2" will delete the 2nd object on the canvas (0 being the first). Note that you send this message to the canvas itself, not the [canvasdelete] object. The object just needs to be there in the patch, even if nothing is connected to it.
-
A "clear" message will delete everything in a patch window. This is usually no good, but depending on your needs you might be able to make a small sub-patch with one object plus a send and receive. The send and receive will be deleted as well, so you'll need to recreate and reconnect these if you want to re-make the object (inlets and outlets should be avoided for the same reason). But this can still work.
-
The other is a horrible hack involving simulated mouse messages. Basically you send all the messages that the mouse would have sent to delete the object (go to this coordinate, select the object, press delete, etc). This is documented (badly) in manuals-->pd-msg-->1... --> 3.2 cut_paste.
1 is definitely the easiest, if you can afford to use externals.
Loading a folder of audio files
@RonHerrema Hello again Ron......
Are you planning to have a main folder, with sub-folders all containing tracks, or are you expecting to just pick folders at random from anywhere on your computer.
If you want to pick from absolutely anywhere then you have three problems....
Most folders will have no wav files.........
Some folders will have wav files at the wrong sample rate....
Most folders containing wav files will contain other files as well... album art, etc.
Anyway..... in "cart" the playlist window is cleared and re-populated as each folder is opened.
If you want to bang a message box you need to give each one a [receive] object and then build a patch to send bangs to those objects. That patch is easy using [random]. The track name will always display in "cart" already. The number of tracks can be known (already the tracklist populator stops when it has created the messages in tracklist).
So you need to add (using the populator) a receive object for each message, place it into "tracklist" and attach (connect) each one to its message.
Either you should do this.........
The populator creates the message, connects it to the [s trackplay] object, creates the [receive 1] object and connects it to the message........ and moves on.
Or this....... the populator runs as in cart, but you add a counter, and when it has finished (how do you know, do you just put a delay and hope) it builds the [receive objects and connects them.
I reckon the first is easier. [s trackplay is object 0 on the page and each message is 1-n for the connect message. You need to change the numbers for the connect messages.......
the populator will build..
[s trackplay] (this is object 0)
[message 1] (this is object 1)
connect object 1 to object 0
[receive 1] (this is object 2)
connect object 2 to object 1
[message 2] (this is object 3....... in "cart" it was object 2 but [receive 1 has been created first)
connect object 3 to object 0
[receive 2] (this is object 4)
connect object 4 to object 3
etc. and it will stop when no more names arrive.
You will need a counter though (don't forget to reset it when the next folder is loaded) so that random can have the right argument. [random x].
You can use the right outlet of [readsf~] to bang out the next number from [random] and start the next track..............another counter and a calculation (when tracks played == track count +1) load the next folder.......... etc.......
Have Fun!
David.
use of threads for i²c I/O external : looking for a good strategy
Hi there,
I'm developing an audio device based on a cubieboard2(armf). I use potentiometers read by an adc that communicates through i²c protocol with my cubie. An i²c lcd display shows the desired parameters values.
I wrote externals in order to get data from the potentiometers (and other switches, and a rotary encoder), or send data to the display. Everything was working, but the i²c I/O functions calls were leading to clicks 'n pops in the audio, which was unacceptable. I use a rt patched debian with selected rt priorities for irqs and audio as I always did with success, and I am looking for a smart way to make my pd patches communicate with my physical interface, in a transparent way at audio level.
Then a opened this topic : http://forum.pdpatchrepo.info/topic/9489/external-i2c-data-reader-leads-to-clicks-standalone-version-works-better , and @Eeight proposed to implement threads, kindly giving a template in order to show me the way.
And now I'd need some advice. I'm not a real C programmer, just learning the empirical way, and I'm reaching my limits... I made a threaded version of the external that reads the potentiometers every x milliseconds, and it works perfectly, no audio pollution anymore. But when I made a threaded version of the external that handles the i²c display (thus receiving incoming messages such as "position x y", or "write message"), it lead to timing problems.
Some of the messages get uninterpreted because my writing function is threaded, and takes the form of an infinite while(1) loop containing a "usleep(10000)" instruction at the end of it in order to limit cpu load. The problem is that this leads to the "loss" of most of the incoming messages...
When reading potentiometers values, it's ok to get them merely one every 10ms, but when you have to send messages that can be interpreted merely one every 1oms, you have to send them to the external with delays, which works (That's my present situation), but is tiedious and inelegant.
Would someone have an idea of how this problem could be addressed in a more elegant manner ?
Here is how I implemented it :
- I create a thread for an infinite while (1) loop containing a call to a writing function whenever a flag equals 1, followed by a usleep(10000) instruction.
This "thread" is running from the beginning and awaits for a nonzero value of the flag to enter in action. It reads the string to be displayed from the object's data structure, but only when the "clocking" allows it together with the flag - a "write" method can receive a t_symbol : the string to display. When a "write blahblah" message is received by the object, the string "blahblah" is stored in the object's data structure, as the flag which is set to 1.
- Then the next time the threaded loop evaluates the flag, it displays "blahblah", resets the flag to 0 and sleeps for 10ms.
But when you use incoming messages using 10 lines messages (allowing for cursor positioning and writing orders), they of course flow through the code in far less than 10ms, hence my problems... In other words the string to be displayed can be changed several times in the object's data structure without being actually displayed because of the relatively slow "clocking".
Please forget the incredible length of this message, together to the fact that I don't post the source yet because of a basic shame of my inelegant coding style. Maybe will I finally clean it and post it later.
Thank you,
Nau
How to install externals, libraries, gui plug-ins, etc.
Edit: This post was originally written with Pd-extended 0.43 in mind. These days there is a nice little plugin called Deken that you can use to easily download and install most of the popular libraries in Pd. It comes bundled with recent versions of Pd-vanilla. You can still use namespaces to load up the objects for most libraries, but for some libraries like zexy that have all the objects bundled into a single file, you will still need to use [declare] to load it up.
Installing libraries and plug-ins isn't so obvious. This guide will hopefully clear up the process, and may even explain more than you need to know.
Recent changes
This first section is mainly for those upgrading to Pd-0.43 from previous versions. If you're new to Pd and are starting on 0.43, you can just skip this section and get on with loading libraries.
It use to be that installing a library was done by putting it wherever you wanted on your system and adding its path to the preferences. While this wasn't particularly difficult, it did have some problems. Recent efforts have been made to standardize this a bit so those problems can be avoided.
In Pd-extended 0.43, you can't add paths from within Pd any more like you used to. You can open the preferences and add a path, but it won't save it. This means that non-default libraries won't load on start-up any more; you have to load them from within the patch. While this sounds like a hassle, it does have the advantage that patches are much easier to share. You don't have to worry about others having different start-up settings than you. It also forces the patch to document what libraries are being used, so if an object isn't loading, you don't have to go on some crazy hunt to find out where it came from or what it's supposed to do.
Putting them in the right folder
To make sure Pd can easily find the library, you need to put them in the right folder. This is OS dependent. The following folders are your options (taken from here). I personally recommend putting them in the user-specific folders since they are likely easier to migrate when updating your OS.
Linux:
User-specific:
~/pd-externals
Global:
/usr/local/lib/pd-externals
Mac OSX
User-specific:
~/Library/Pd
Global:
/Library/Pd
Windows
User-specific:
%AppData%/Pd
Global:
%CommonProgramFiles%/Pd
Linux and OSX are pretty straight-forward. "~" means your home folder.
Windows is a bit trickier. %AppData% and %CommonProgramFiles% are environment variables that contain specific directories. What the exact directory is depends on which version of Windows you are on. You can find out what it is by opening up the command line and typing this:
echo %AppData%
You might end up with something like C:\Users\username\AppData\Roaming or C:\Documentes and Settings\username\Application Data. Also, to see it in the file browser, you might need to show hidden files. At any rate, once you find the directory, create a Pd folder if there isn't one, and put your library, objects, or plug-ins there.
Loading whole libraries
To load a library you have a few options. The one that works on both vanilla and extended is to use [declare -stdpath libraryname]. The libraryname is the name of the folder that all the objects/abstractions are in.
[declare] doesn't always work as expected in abstractions, though. In Pd-extended, you can also use [import], which works well in abstractions. I have found that sometimes it doesn't work with libraries of abstractions that don't have a meta file, though. But that can be fixed by just making one. Simply create an empty Pd patch and save it as libraryname-meta.pd in the library's folder. That's all the meta patch is.
A third option (also Pd-extended only) is to use [path]. This is new to Pd-extended 0.43 and works similarly to [declare]. I haven't needed it, yet. But it's there.
Once the library is loaded, you should be able to load an object or abstraction just by creating it by name.
Loading objects or abstractions using namespaces
While this method means a little more typing, it is also the safest, and it makes it easier to find out what objects are from which library. The way you do it is add the library name (i.e. the namespace) to the beginning of the object when you call it, like this:
[zexy/multiplex~] <-- load the [multiplex~] object from zexy
[cyclone/comb~] <-- load [comb~] from cyclone
You don't have to load the library with [import] or [declare] for this to work. You just call the object that way.
Why is this safest? Because it's possible for different libraries to have objects with the same name. For example, both cyclone and zexy have an object called [mean]. But they don't work exactly the same. zexy's takes a list, while cyclone's takes in a continuous stream. If you have both libraries loaded (and in Pd-extended, these two libraries happen to be loaded by default), you can't be sure which one you're getting if you just type [mean]. However, if you type [cyclone/mean], you know exactly which one you are getting.
Conditional gate
@mod said:
But time and time again we see the same sort of posts. People who just want to turn an audio signal on and off use something like [spigot~], people use [counter] instead of basic pd objects. They post these patches and run into trouble that could easily be avoided by only using vanilla objects unless necessary.
What's wrong with [counter]? Objects like those remedy the trouble of trying to figure out how to make one using only vanilla objects. Not that it's particularly difficult to do, but it may just be more intuitive or time saving to someone to use [counter].
Of course most people are using extended, but it's such a vast ocean that no-one knows how EVERY object in extended works. The object in question here, [gate], i can only hazard a guess, but i'm thinking that a maximum of 50% of users know the cyclone library and in particular the [gate] object well enough to debug a patch.
Well, that's where the basic advice that you and others have posted comes in: Right click -> Help.
Besides, I don't really think that because less people know or use an object should deter one from trying it. It may just make more sense or fit with their particular programming preferences. I know I like to build from low-level objects and work up, but not everyone is so interested. For example, I've built my own compressor abstraction. But plenty of other people would rather just load a compressor object and be done with it. Nothing wrong with either approach.
Also, I've been using Pd long enough that I feel comfortable saying I'm in "expert" territory. I don't know what every extended object does, but I don't know what EVERY vanilla object does, either.
(I'm speaking from my own bad experiences here too, because my old patches had some extended objects in them, and i answered countless emails from people having trouble with those externals not loading. I could have saved myself a lot of time by just using the correct vanilla constructs in the first place)
Now, this is a different issue, and I'm more inclined to agree here. You can definitely ensure higher compatibility by sticking to vanilla objects, as some externals don't work correctly on all OS's and vanilla users may not have some of the more popular libraries installed, but it does come with the potential costs of flexibility or computational load. And, this is only an issue if you want to share your patches or use them on other OS's.
When I'm writing a patch that's for personal use only, and I don't expect to be sharing it, I tend to use whatever I want. But if I'm making an abstraction I might share, I usually follow an order of precedence:
1. Use vanilla objects where possible/practical for best compatibility.
2. Use extended objects if needed, since it's used widely and newbie-friendly.
3. If absolutely necessary, use a popular lib not included in Pd-extended, like GridFlow or RjLib (I've never had to do this, yet).
But that's entirely for compatibility reasons only.
@Shakasin said:
But is there something in vanilla that could replace my [gate] just curious ?
. [== 1] [== 2] [== 3]
| | |
[spigot] [spigot] [spigot] etc....
Connect the gate number to the left inlet of the [== ] objects, and the value you want to pass to the left inlet of the [spigot]s.