Hello,
Is there a way to make an abstraction that has one inlet that takes both signal and control messages (like osc~, e.g., or fiddle~ which gets audio and setting info, etc.)? It's part of the API for objects; it seems to me there ought to be a way to do this with abstractions as well. I'm envisioning an inlet object that splits signal and control into two outlets which can be parsed from there. Something that uses the signal and control values to do the same thing (as in osc~) might be difficult to implement in an abstraction, but having signal and optional settings messages go to the same inlet would add to the abstraction-as-object nature of PD... does it exist?
Thanks,
Matt
No... I hope to figure out a good way to permit that. Meanwhile, there's also a bug in that inlet~ doesn't take numbers "correctly" (doesn't promote them to signals)
cheers Miller
On Tue, May 06, 2008 at 10:07:04AM -0400, Matt Barber wrote:
Hello,
Is there a way to make an abstraction that has one inlet that takes both signal and control messages (like osc~, e.g., or fiddle~ which gets audio and setting info, etc.)? It's part of the API for objects; it seems to me there ought to be a way to do this with abstractions as well. I'm envisioning an inlet object that splits signal and control into two outlets which can be parsed from there. Something that uses the signal and control values to do the same thing (as in osc~) might be difficult to implement in an abstraction, but having signal and optional settings messages go to the same inlet would add to the abstraction-as-object nature of PD... does it exist?
Thanks,
Matt
PD-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
It piqued my curiousity this morning...
whether you could use $1 arguments in the name of an object. So, I made a abstraction this morning called inle.pd and it works.
You can instatiate the abstraction as [inle t] or [inle t~]
I don't think this approach is at all useful, though.
Chuck
On Tue, May 6, 2008 at 9:09 AM, Miller Puckette mpuckett@imusic1.ucsd.edu wrote:
No... I hope to figure out a good way to permit that. Meanwhile, there's also a bug in that inlet~ doesn't take numbers "correctly" (doesn't promote them to signals)
cheers Miller
On Tue, May 06, 2008 at 10:07:04AM -0400, Matt Barber wrote:
Hello,
Is there a way to make an abstraction that has one inlet that takes both signal and control messages (like osc~, e.g., or fiddle~ which gets audio and setting info, etc.)? It's part of the API for objects; it seems to me there ought to be a way to do this with abstractions as well. I'm envisioning an inlet object that splits signal and control into two outlets which can be parsed from there. Something that uses the signal and control values to do the same thing (as in osc~) might be difficult to implement in an abstraction, but having signal and optional settings messages go to the same inlet would add to the abstraction-as-object nature of PD... does it exist?
Thanks,
Matt
PD-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
PD-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
On Tue, 6 May 2008, Matt Barber wrote:
Is there a way to make an abstraction that has one inlet that takes both signal and control messages (like osc~, e.g., or fiddle~ which gets audio and setting info, etc.)?
My solution has been to make an external that contains no objectclass and load it using -lib. It contains this code:
#define ALIAS(y,x)
class_addcreator((t_newmethod)getfn(m,gensym(x)),gensym(y),A_GIMME,0);
t_pd *m = &pd_objectmaker;
ALIAS( "inlet.f","inlet" );
ALIAS( "inlet.~","inlet~" );
So after that, Pd 0.40 can instantiate it as [inlet.$1]
If you are stuck with Pd 0.39 you will need to swap it around because [inlet.$1] won't work but [$1.inlet] will.
But this is just an alternative to what Charles Henry said. I prefer mine because the syntax looks better. Then I pass either "f" or "~" as argument to an abstraction. I would later add more single-character suffixes such as "s" and such perhaps, but only to the extent that polymorphism makes sense - first, an analogy has to be made between two types such that one behaviour one one type can be likened to one behaviour on the other. From that point, the two behaviours can be unified, partially or totally, and then [inlet.$1] (or equivalent) becomes useful.
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard - tél:+1.514.383.3801, Montréal, Québec
Hello,
Thanks for your reply!
I think my wording of the original problem was wrong -- your solution would work well, but my point is there should be an object (or maybe this should just be the default behavior of [inlet~]) which looks like the following (hopefully the ascii art doesn't get munged on the way out):
[inlet~]
|
|
signal
control data
This way you could pass audio signals and control messages into the one inlet, like you can with something like [snapshot~], say:
[osc~] | | [bang( | / | / |/ [abstraction~ arg1 arg2 etc]
Inside the abstraction the signal would come out of [inlet~]'s left outlet, and the bang would be sent to its right outlet and would be passed to the rest of the abstraction appropriately and at the correct time. This would help complete the abstraction-as-object API and could be a separate object if such a thing would use more overhead than normal [inlet~]...
If I'm not mistaken your solution would allow you to decide whether an inlet is a control or a signal object as it's instantiated in an abstraction at creation time (which I think is what my original wording might have implied) -- I think I'm after something a little different than polymorphism (which is quite an interesting problem on its own). For numbers, [inlet~] already does a good job turning floats into signals.
One other, possibly more extravagant feature that would go even further:
An object like [osc~] seems to "know" when a signal is attached to its inlet or not -- if it's given a creation argument, it will snap back to that, or the last float value it received when the audio signal is disconnected. I'm not sure how to simulate this behavior in an abstraction; I think [inlet~] itself will snap to the last float it received when an audio signal is disconnected, but if you want your abstraction to move back to using the value of its creation argument, there's a problem, since presumably the inlet~ knows nothing about that. One solution I've found is to poll the inlet with an [env~ 2] to look for nonzero values and to switch between using the output of the [inlet~] and a [sig $1] depending on the [env~]'s output, but this assumes that zero is a "non-setting" (as it would snap to the $1 as soon as it received a zero-valued float or [sig~]. The feature I propose would be to allow a float argument to [inlet~] as the default signal to be passed and which is remembered as signals are connected and disconnected to the abstraction from the parent, only until the value stored is changed by a float message. Of course I'm interested in other currently implementable solutions...
Thanks,
Matt
On Wed, Jun 11, 2008 at 8:24 AM, Mathieu Bouchard matju@artengine.ca wrote:
On Tue, 6 May 2008, Matt Barber wrote:
Is there a way to make an abstraction that has one inlet that takes both signal and control messages (like osc~, e.g., or fiddle~ which gets audio and setting info, etc.)?
My solution has been to make an external that contains no objectclass and load it using -lib. It contains this code:
#define ALIAS(y,x) \
class_addcreator((t_newmethod)getfn(m,gensym(x)),gensym(y),A_GIMME,0); t_pd *m = &pd_objectmaker; ALIAS( "inlet.f","inlet" ); ALIAS( "inlet.~","inlet~" );
So after that, Pd 0.40 can instantiate it as [inlet.$1]
If you are stuck with Pd 0.39 you will need to swap it around because [inlet.$1] won't work but [$1.inlet] will.
But this is just an alternative to what Charles Henry said. I prefer mine because the syntax looks better. Then I pass either "f" or "~" as argument to an abstraction. I would later add more single-character suffixes such as "s" and such perhaps, but only to the extent that polymorphism makes sense - first, an analogy has to be made between two types such that one behaviour one one type can be likened to one behaviour on the other. From that point, the two behaviours can be unified, partially or totally, and then [inlet.$1] (or equivalent) becomes useful.
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard - tél:+1.514.383.3801, Montréal, Québec
Matt Barber wrote:
Hello,
soon as it received a zero-valued float or [sig~]. The feature I propose would be to allow a float argument to [inlet~] as the default signal to be passed and which is remembered as signals are connected and disconnected to the abstraction from the parent, only until the value stored is changed by a float message. Of course I'm interested in other currently implementable solutions...
you seem to not be aware that [inlet~] already takes arguments, which makes your proposal a bit more awkward to implement. (nonetheless i like the basic idea; as you are already adding outlets to [inlet~] once could imagine a third inlet that would tell you the connection state...)
mfg.asdr IOhannes
Right, I had thought about a third outlet which sends a 1 or a 0 depending on connection state -- somehow the float argument seems better integrated with the default behavior of other objects, and much simpler to use. I think the reason is that floats coming in are already promoted to signals; in the "split signal and control" model for [inlet~], if floats were passed as control data rather than promoted then the third outlet for connection state would make more sense.
In fact, now that I think about it this may be a very different problem from the splitting signal and control problem because it might not just affect [inlet~] -- a similar feature could be made for [outlet~] since it can also take float messages and promote them to signals (this functionality is much less needed for [outlet~] than for [inlet~] however, since float messages can be passed directly to the [outlet~] from inside the patch, but it could be useful especially for an abstraction whose internal connections change dynamically).
I only know two arguments for [inlet~] and [outlet~] -- "hold" and "lin" -- but they don't take floats for anything, do they? (actually, they currently take "0", I guess with the default "interleave zeroes" meaning?) I suppose I need to go through the code more thoroughly, but I could imagine that since they already know what to do with one nonzero float argument (the object is not created), they could possibly use that float instead as a default output value. The problem is what to do when you want both sample-and-hold when upsampling (say) and a default output value:
[inlet~ hold 0.5]
would not break current patches, as it keeps the currently available arguments first. The other problem is that other objects define arguments by order rather than by type, and I doubt anybody would want to require an argument for the default "intervleaving" that an [inlet~] or [outlet~] already does for upsampling just to maintain proper order:
[outlet~ inter 0.7]
seems kind of silly since the argument would not make explicit sense in non-upsampled subpatches/abstractions.
Of course this is all moot if [inlet~] and [outlet~] already take float arguments for something after all. One other option which I think is way too extravagant for something this low-level would be to provide flagged arguments a la [sigmund~]... it would be too error-prone and would break tons of patches.
At any rate, I appreciate your help and others' on the list greatly!
Thanks,
Matt
On Thu, Jun 12, 2008 at 3:41 AM, IOhannes m zmoelnig zmoelnig@iem.at wrote:
Matt Barber wrote:
Hello,
soon as it received a zero-valued float or [sig~]. The feature I propose would be to allow a float argument to [inlet~] as the default signal to be passed and which is remembered as signals are connected and disconnected to the abstraction from the parent, only until the value stored is changed by a float message. Of course I'm interested in other currently implementable solutions...
you seem to not be aware that [inlet~] already takes arguments, which makes your proposal a bit more awkward to implement. (nonetheless i like the basic idea; as you are already adding outlets to [inlet~] once could imagine a third inlet that would tell you the connection state...)
mfg.asdr IOhannes
Someone could just write new objectclasses that handle both signal
and message, maybe something like:
message_inlet~ message_outlet~
.hc
On Jun 12, 2008, at 4:09 PM, Matt Barber wrote:
Right, I had thought about a third outlet which sends a 1 or a 0 depending on connection state -- somehow the float argument seems better integrated with the default behavior of other objects, and much simpler to use. I think the reason is that floats coming in are already promoted to signals; in the "split signal and control" model for [inlet~], if floats were passed as control data rather than promoted then the third outlet for connection state would make more sense.
In fact, now that I think about it this may be a very different problem from the splitting signal and control problem because it might not just affect [inlet~] -- a similar feature could be made for [outlet~] since it can also take float messages and promote them to signals (this functionality is much less needed for [outlet~] than for [inlet~] however, since float messages can be passed directly to the [outlet~] from inside the patch, but it could be useful especially for an abstraction whose internal connections change dynamically).
I only know two arguments for [inlet~] and [outlet~] -- "hold" and "lin" -- but they don't take floats for anything, do they? (actually, they currently take "0", I guess with the default "interleave zeroes" meaning?) I suppose I need to go through the code more thoroughly, but I could imagine that since they already know what to do with one nonzero float argument (the object is not created), they could possibly use that float instead as a default output value. The problem is what to do when you want both sample-and-hold when upsampling (say) and a default output value:
[inlet~ hold 0.5]
would not break current patches, as it keeps the currently available arguments first. The other problem is that other objects define arguments by order rather than by type, and I doubt anybody would want to require an argument for the default "intervleaving" that an [inlet~] or [outlet~] already does for upsampling just to maintain proper order:
[outlet~ inter 0.7]
seems kind of silly since the argument would not make explicit sense in non-upsampled subpatches/abstractions.
Of course this is all moot if [inlet~] and [outlet~] already take float arguments for something after all. One other option which I think is way too extravagant for something this low-level would be to provide flagged arguments a la [sigmund~]... it would be too error-prone and would break tons of patches.
At any rate, I appreciate your help and others' on the list greatly!
Thanks,
Matt
On Thu, Jun 12, 2008 at 3:41 AM, IOhannes m zmoelnig
zmoelnig@iem.at wrote:Matt Barber wrote:
Hello,
soon as it received a zero-valued float or [sig~]. The feature I propose would be to allow a float argument to [inlet~] as the
default signal to be passed and which is remembered as signals are connected and disconnected to the abstraction from the parent, only until the value stored is changed by a float message. Of course I'm
interested in other currently implementable solutions...you seem to not be aware that [inlet~] already takes arguments,
which makes your proposal a bit more awkward to implement. (nonetheless i like the basic idea; as you are already adding
outlets to [inlet~] once could imagine a third inlet that would tell you the
connection state...)mfg.asdr IOhannes
Pd-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/ listinfo/pd-list
If nature has made any one thing less susceptible than all others of
exclusive property, it is the action of the thinking power called an
idea, which an individual may exclusively possess as long as he keeps
it to himself; but the moment it is divulged, it forces itself into
the possession of everyone, and the receiver cannot dispossess
himself of it. - Thomas Jefferson
Hans-Christoph Steiner wrote:
Someone could just write new objectclasses that handle both signal
iirc, it's not that simple. iolets need deep access to pd-internals.
this is one of the reasons why i have implemented the signal up/downsampling in iolet~s within Pd rather than as externals. (the other reason was the need to modify [block~] to accept the resampling factor...)
and message, maybe something like:
message_inlet~
what does that mean?
and how about [message~] or [ (~ ?
fmasdr IOhannes
I've been going through the code for this the last couple of days. I'm new to the code, so this might be for my own understanding than as any kind of explanation:
There seem to be two main problems -- one is that [inlet] and [inlet~] are the same class with different creators (and which therefore utilize different functions) -- it might be that it would break things to create new classes outright (i.e. there's a reason they're currently members of the same class), and it would be hard/undesirable(/impossible?) to add a creator to a class's setup function externally.
A more serious problem is that the vinlet objects are instantiated as CLASS_NOINLET which means they have no "main" inlet (the c_firstin member of the class is switched off), and canvas_addinlet() uses inlet_new() to forward the subpatch/abstraction inlet to the outlet of the inlet(~) object -- but since it's no longer a "main" inlet, CLASS_MAINSIGNALIN() won't work, and any inlet made with inlet_new() has to decide whether it takes messages or signals/floats - it can't do both.
The ability of a first inlet to do both seems not to be written into the the inlet class functions (here I'm talking about the code for any generic inlet, not [inlet] in particular...), but into object class functions and the ugen functions: particularly, an object class's c_firstinlet and c_floatsignalin members seem to be pretty deeply ingrained into the design of the functions which determine whether the first inlet is a signal inlet and should therefore be included in the ugen graph, and this seems different than any inlets which were added to the class later (e.g. the code for finding the float value to convert to a signal in obj_findsignalscalar() is split into code for the first inlet, which points to a member in the object class's type, and code for other inlets which points to a float value in a union which is a member of the inlet struct, not the object class itself).
In other words, at the moment it seems to be just as hard to add the extra functionality to [inlet~] as it would be to make any ordinary objectclass whose right inlet could take a signal and a bang message.
I could be very wrong, but I think the external solution would involve changing some code in unwarranted places, even if new creators, destructors, and functions could be made for the vinlet class.
BTW, to complicate things, if one wanted abstractions to REALLY work like objects, then if the abstraction's leftmost inlet were an [inlet~], it would automatically sprout the right outlet for passing messages (and this only if it were an abstraction -- you probably wouldn't want this for subpatches)...
Sorry for the long posts of late.
Thanks,
Matt
On Tue, Jun 17, 2008 at 6:05 AM, IOhannes m zmoelnig zmoelnig@iem.at wrote:
Hans-Christoph Steiner wrote:
Someone could just write new objectclasses that handle both signal
iirc, it's not that simple. iolets need deep access to pd-internals.
this is one of the reasons why i have implemented the signal up/downsampling in iolet~s within Pd rather than as externals. (the other reason was the need to modify [block~] to accept the resampling factor...)
and message, maybe something like:
message_inlet~
what does that mean?
and how about [message~] or [ (~ ?
fmasdr IOhannes
Matt Barber wrote:
In other words, at the moment it seems to be just as hard to add the extra functionality to [inlet~] as it would be to make any ordinary objectclass whose right inlet could take a signal and a bang message.
actually it is rather trivial, see attached diff. this however is a quick hack and i don't think it should really be used.
probably a better approach would be to accept any messages in [inlet~] and just pass them on to the objects connected. then you could have another object that separates signals and messages. i would call the latter [route~]ld be made for the vinlet class.
BTW, to complicate things, if one wanted abstractions to REALLY work like objects, then if the abstraction's leftmost inlet were an [inlet~], it would automatically sprout the right outlet for passing messages (and this only if it were an abstraction -- you probably wouldn't want this for subpatches)...
i don't fully understand what you mean here. however, it seems to me that you are trying to mimick flaws in the external-API in the abstraction-API. it would probably be better to fix the flaws than to mimick them. (and one could hack together an external that takes messages+signals on any inlet; and signals only on a right-hand inlet,...)
fmgasd IOhannes
--- g_io.c (Revision 9980) +++ g_io.c (Arbeitskopie) @@ -36,8 +36,9 @@ /* if not reblocking, the next slot communicates the parent's inlet signal from the prolog to the DSP routine: */ t_signal *x_directsignal;
} t_vinlet;
static void *vinlet_new(t_symbol *s) @@ -47,43 +48,46 @@ x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, 0); x->x_bufsize = 0; x->x_buf = 0;
}
static void vinlet_bang(t_vinlet *x) {
}
static void vinlet_pointer(t_vinlet *x, t_gpointer *gp) {
}
static void vinlet_float(t_vinlet *x, t_float f) {
}
static void vinlet_symbol(t_vinlet *x, t_symbol *s) {
}
static void vinlet_list(t_vinlet *x, t_symbol *s, int argc, t_atom *argv) {
}
static void vinlet_anything(t_vinlet *x, t_symbol *s, int argc, t_atom *argv) {
}
static void vinlet_free(t_vinlet *x) { canvas_rminlet(x->x_canvas, x->x_inlet);
}
@@ -247,17 +251,24 @@
static void *vinlet_newsig(t_symbol *s) {
x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, &s_signal);
x->x_msgoutlet=0;
x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, 0);
x->x_msgoutlet=outlet_new(&x->x_obj, 0);