Param device questions

Hi there,

2 Questions:

  1. When is 2.3 out, and where is its PDK? I noticed somebody mentioned it in a recent forum post.

2)I’m trying to write a plugin that will output parameters (like a seed value) from a separate application into World Machine. To do this, I’m actually planning on the device dynamically growing as each output port is connected, and sending back the names of the ports I’m connecting to from my device to this separate application. However, I’m noticing that NotifyPortConnected only seems to notify on input ports. In order to know when an output port is being connected to, which I couldn’t find in the API of the 2.2 PDK, I’m planning on creating a MyDeviceOutputPort type that derives from OutputPort, and whenever I add a port, I’ll replace the OutputPort the PDK creates in the background with my MyDeviceOutputPort. From there, I’ll override make/break link so I know when these are connected and disconnected. Does this sound ok? Any other suggestions? Am I missing something in the API?

Scratch that, outputs doesn’t seem to contain what I think it would - the vector is inaccessible at any rate. So I’ll rephrase: how can I detect when my device’s output is connected to the parameter input of another device?

Hi there,

2.3 is in public beta right now and will be available as a final release candidate, well, actually, later today, along with the PDK for it. It should be up within the next 4-6 hours! Head to http://www.world-machine.com/beta/ for the latest.

As to your specific question:

The good news is that interestingly, in 2.3 it is quite possible to implement your first idea of subclassing the output ports. I don’t think this has changed so it should actually be possible in 2.2 as well. This is something I never considered even allowing however! Thus is slightly risky ground… but as long as your input ports are derived from at least Port and your output ports derived from at least OutputPort, it should work. There are a number of gotchas though, so be sure to:

*Whenever you assign your new ports to the port vector, make sure you call MyPort->SetOwner(this).
*Do not manipulate the vector size manually, use the ChangeLinks() function then replace afterwards if you need to vary your number of ports
*You must implement the doClone(other) function to properly copy your device with its non-standard ports.
*If you have dynamically created ports you must also re-setup your ports in your Load() function after your parent has finished loading.

I just verified that a simple proof of concept implementation that overrides the OutputPort::MakeLink() and adds parameters shows no obvious issues and can be implemented in 2.3 from the public PDK.

Back to the notifyPortConnected, you are right that it currently only sends to inputs; it would indeed be useful to notify outputs too, so I will add that behavior for the final… thus you should be able to achieve your goal through either route in 2.3.

Cheers!

Thanks for the quick response. Awesome that you were able to test it out - so is that pdk with notify port connected available today?

Trying to do this myself, I was trying to access the outputs array of the device - however accessing this array crashes, and when I look in the debugger, ((outputs)._Myfirst) is 0xbaadf00d = MS’ code for uninitialized heap memory. This is the case both in the constructor of my device (after I have SetLinks(0, 1, WMP_scalar)), and in the activate function. In your proof of concept, were you instead using the OutputPort *out function of the device? Or were you using the outputs array?

Update: Updating to the 2.3 beta and re-creating my project in 2010 (I was using 2008 before with 2.2 and it seemed to be working, even though you recommend 2005), I now see that the outputs vector gets set as I expect. Any idea what might have been going on in 2.2?

Hi there,

Yes, the 2005 / 2008 conflict before is almost certainly why it didn’t work – Microsoft changed their STL code between those editions so it was extremely dicy relying on vectors, etc having the same layout across compilers.

Essentially plugins must be created with the same compiled that WM is compiled against, which is 2010 for 2.3.

Cheers

Alright. I’d hoped that wasn’t the case, as installing 2005 may screw up my other VS installations. Hopefully I can get us moved over to 2.3. Final question for you - I’m creating my new output port (for now, just testing replacing the first output port after a SetLinks(0, 1)) as such
OutputPort* out = outputs.back();
MyOutputPort * newPort = new MyOutputPort(*out);
outputs[0] = newPort;

and
MyOutputPort::MyOutputPort(OutputPort& other)
{
strncpy(name, other.GetName(), PORT_NAME_LEN);
data_type = other.GetType();
target = other.Target();
owner = other.Owner();
flag = other.GetFlag();
}

How do I release the old output port safely? Can I simply delete it, or will something go amiss at that point?

Yep, that looks fine, you can go ahead and just delete the old port – In this case you should encounter no issues as the ports allocated are from your local DLL’s heap.

Ok, sounds good. I lied, of course I still have another question: I’m doing some communication with another program over a named pipe, so I’m looking to have a separate thread doing this communication. Any special requirements, or can I just create one with CreateThread? It seems right now I’m getting a hang on startup when I do that (I’m terminating it in the node’s destructor), but I may find a solution yet.

There shouldn’t be any special worries in doing so; the only thing I can think of is that during the process of loading all plugins WM will instantiate a copy of your device temporarily; if your create/cleanup code is stuck in a wait that could explain the hang on startup.

So I’ve written an output port that will actually call notifyPortConnected on make/break of a link. However, I’m trying to get the slot index of the port, but calling GetLinkedPort on the owner always returns 0. Is there a function I can call on the device with a Port * to get the slot #? Is there a bug in GetLinkedPort right now?

[EDIT]: I found FindPort, and it works fine. What is GetLinkedPort supposed to return?

Good questions. I will clarify the port function documentation (or rename the methods) for the final as many serve different purposes but sound similar.

If you have this arrangement:

Device A:
Output 0 : port x

Device B:
Input 0 : port y

FindPort should be what you want.

for example, calling A->FindPort(x) will set output params slot = 0, io = DEV_OUTPUT;

GetLinkedPort reaches through the wiring and compares to the ports on the other side of the a device’s links – basically “If I am connected to port target on a different device, what part of me is connected to it?”.

As I’ve discussed previously, I’m doing some communication with an external application. From this application, I’m going to be setting a value within this node, that its outputting on an output node. I’m going to have a manager doing the communication with my external app, keeping a list of the devices it’s tracking. It will have a separate thread reading set value messages from the external app. From there, I can set the value on the node fine, but I don’t know how to let the world machine graph know a value has updated. How do I get WorldMachine to trigger a node’s Activate function from a thread I’ve created?

So… you can trigger a graph rebuild by calling Falsify() on a device, which will flag that device and all its successors for rebuilding.

However, there is still a problem, because this is not an asynchronous interface; if your communication thread called Falsify() whenever the external data changed, for example, it could easily do so at completely inappropriate times (during a build is bad but not catastrophic; but during serialization or right in the middle of a port connection could be very bad). In short the Falsify() or Preview() calls are not thread safe, and so should never be called from a secondary thread.

Off the top of my head, the best solution I can think of is to have a threadsafe collection in your manager that keeps track of all updates that have come in since the last synchronization.

Then override RunUI() in your device and before you call the default implementation, retrieve the set of changed devices and call Falsify() and/or Preview() on them appropriately. This call will be done on the main program thread and so is a safe operation. … so your changes won’t sync till you open your user interface, but within that limitation it should work nicely. Alternatively, you could add an auxillary UI action by overriding the set of:

virtual int  getAuxActionSize() { return 1; };
virtual bool RunAuxAction(int index) { domySynchAndPreview() };
virtual char *getAuxActionName(int index); { return "Synchronize"; };

This would give you an explicit Synchronize action on the device that can be selected by right-clicking and then choosing Synch.

How do your worker threads update their progress then? Is there any way to get a threadsafe falsify in a later PDK? Or perhaps add an update pass to the devices? If I had some way to get control of the main thread at a certain point I’d also be able to solve my problem.

Does it some news on MSVC 2010 support? I’m trying to build the inverted example but the upgrading process of the Visual Studio Solution fails. I would to develop some little plugins . It’s better to wait or shall i install a previous VS version?
Thanks

Walter

You need to grab the latest pdk from the beta site kalwalt. I’ve had no problems using it with visual studio 2010. beta site is at world-machine.com/beta. However, your post is completely off-topic - if you’re still having problems, do you mind starting another thread? Thanks.

Really sorry for the off topic.! i forgot of the beta version… i will download it. If i have other problem i will open another topic. Thanks for the info, @skylerd.

p.s. also was noted by Remnant that new PDK is on beta site… i read very quicly , sorry again …

Generally speaking, threading in WM is done at both a coarser and finer level than this – devices do data-parallelism on their workload, and the WM core schedules task parallelism by having different devices work on different threads, but unfortunately this case falls right down the middle – the device-class interface is single threaded. The main program thread “owns” the world, even if it does lend out a single device at a time to different threads for processing.

But I agree, it would be useful to have an asynchronous message queue exposed to devices so that they can affect the world. This is quite possible for post 2.3 release.

As an alternative to a full scale asynchronous reworking of the device class (for now, until you have time), would it be fairly easy to add to your message pump handler a special user message that will do a callback to a void SomeFunc(void* param) function? That would also solve my problem.

P.S. In case I’m not being clear, I’m very very thankful for all your help here, and none of the above is a demand - just a suggestion for something quick & dirty if you wish to implement it.