Cabbage Logo
Back to Cabbage Site

CsoundUnity Package (UPM) development

Packages\CsoundUnityPackage\Runtime\CsoundUnityBridge.cs(164,17): error CS0051: Inconsistent accessibility: parameter type 'Csound6.NativeMethods.YieldCallback' is less accessible than method 'CsoundUnityBridge.SetYieldCallback(Csound6.NativeMethods.YieldCallback)'
ackages\CsoundUnityPackage\Runtime\CsoundUnity.cs(835,17): error CS0051: Inconsistent accessibility: parameter type 'Csound6.NativeMethods.YieldCallback' is less accessible than method 'CsoundUnity.SetYieldCallback(Csound6.NativeMethods.YieldCallback)'

These were the same errors I was getting :laughing:

Yes sorry I wrote some garbage code, maybe itā€™s better now! Just pushed!

call it like this:

void Start()
{
    csound = GetComponent<CsoundUnity>();
    csound.SetYieldCallback(() => {
        Debug.Log("call me please");
    });
}

or could be a method:

csound.SetYieldCallback(MethodToCall);

private void MethodToCall() {
    Debug.Log("call the method please");
}

I just noticed that we can only set one callback at a time, or we have Null Refs all around, I am trying to fix this

Iā€™ll take a look in the morning. Seems like youā€™re getting close!

No more null refs but only the last method set is called.
Iā€™ll take a look at it tomorrow too!

Hmm. I better double check we can register more than one. I had always assumed so, but I may be wrong. It wouldnā€™t be the first time :hear_no_evil:

So it looks like only one callback function can be registered. Sorry about that. This makes things trickier, but there is nothing stopping our yield callback from calling other functions. Iā€™ll have a look at it and see what I can work out. We may need to keep a list of node objects within our CsoundUnity class :thinking:

Hmm, another issue I see now is that the yield callback function is staticā€¦

Ok so itā€™s one call for sure!
Then letā€™s go with the list of node objects!

I had a look at the API, there are lots of methods that can help us passing things around, for example:

csoundRegisterSenseEventCallback()

Register a function to be called once in every control period by sensevents(). Any number of functions may be registered, and will be called in the order of registration. The callback function takes two arguments: the Csound instance pointer, and the userData pointer as passed to this function. This facility can be used to ensure a function is called synchronously before every csound control buffer processing. It is important to make sure no blocking operations are performed in the callback. The callbacks are cleared on csoundCleanup(). Returns zero on success.

csoundSetRtplayCallback()

Sets a function to be called by Csound for performing real-time audio playback.

But Iā€™m sure you know what to do better than me! :pray:

Ok, csoundRegisterSenseEventCallback() looks like it might be a better option. I wasnā€™t aware of this one. The fact that it lets us pass a pointer to our object means that we can then access member data in the callback function. Let me just look through the C source code firstā€¦

And itā€™s already implemented in Csound6Net! :partying_face:

Yeah, it looks good. Youā€™re getting quick at adding these methods now! I just pushed to the dev2 branch. I just added:

/// <summary>
/// Gets a Csound Audio channel. Used in connection with a chnset opcode in your Csound instrument.
/// </summary>
/// <param name="channel"></param>
/// <returns></returns>
public MYFLT[] GetAudioChannel(string channel)
{
    return csound.GetAudioChannel(channel);
}

We need to send a box of cigars to Richard when this is all done!!

1 Like

I think we can remove the coundSetYieldCallback stuff if this works. I think it might just end up confusing end usersā€¦

Yes 90% of the code comes from there! And its style is very clear, all is commented, well organized, great work!!
Thinking about that, maybe we could achieve a better organization of the CsoundUnityBridge and CsoundUnity classes, adding regions and ordering methods like listed in the api (like what I did in CsoundCsharp.cs)

Yes I agree, but maybe it could be useful if you want that only the last method you add executes?
I canā€™t think of an application right now, but it could come in handy.

And of course some work must be done to give a proper documentation. As an end user I would like to know which methods to use and how, instead of reading an infinite list of methods with their summary.

I agree with all of this. I think this is the last big issue. Once it is done we can concentrate on creating useful examples, templates, documentation and all of that end-user stuff.

Let me know when you push. I will try this out straight away :wink:

1 Like

Sorry I had an interview in the meantimeā€¦
Give me some time :sweat_smile:
btw itā€™s not easy to pass the struct, never done this!
Should we define some sort of interface? Do we have any requirements?

You mean the pointer to our host data? Iā€™ve no idea how that will work either. Does Richard have an example of that I wonder :thinking:

I hope the interview went well!

He just uses the pointer!
Iā€™ll look into it more deeper, until now I was distracted by too many things
I will use a generic type, of which I have to get the pointer somehow, and pass it to the native method.

Not much help to you but in C++ I would just do this:

MyClass* userData = (MyClass*)_userData;