Cabbage Logo
Back to Cabbage Site

Exposing csoundGetChannelIist... for presets?

Hi @giovannibedetti. I wonder if you have time might you look at adding an interface to:
https://csound.com/docs/api/group___c_o_n_t_r_o_l_e_v_e_n_t_s.html#ga5fa6839d0f6bae9a3c5a0e82e4d83a5f
If we had that we could very easily write methods to save all the current channel data. Something like this (in psedudo code):

string channels[] = csoundUnity.getAllChannels();
for ( int i = 0 ; i < channels.size() ; i++)
{
   float current value = csoundUnity.getChannel(channels[i]);
   writeToPresetFIle(file, channel[i], currentValue);
}

Similar methods could be used to read the data and update all channels accordingly? It would preset a very simple and robust way of saving presets?

1 Like

Yes it seems great!
I started a new branch where I listed all the API methods (also the ones that are not implemented yet), to be aligned with Csound 6.11. I’ll push the CsoundUnityBridge to the develop branch and add those!

I am in the middle of a big rewrite, I was just messing with channels :sweat_smile: and how the editor manages them (maybe to get saved).
I’ll write a new thread where I talk about the status of the new package development.

We definitely don’t need to implement all the API methods. Many of them are pretty useless to us!

Yes of course, but it was just to be visibly aligned with Csound 6.11. I’ll push an update of CsoundCsharp in a minute, take a look! (I also added regions to be more clear)

Btw, we’re currently on Csound 6.14 :laughing:

:sweat_smile:
Too fast!!
I took everything from here, https://csound.com/docs/api/modules.html

Slow down!!

But I didn’t implement everything. Most of the methods are commented just for reference!
So It’s easier to follow the Csound API docs!

All joking aside, this is a good idea. At least others can see what has, and what has not been implemented.

1 Like

Ok I got this, but for the test synth we were talking about the native call returns 0 channels!
Then I have a crash. I’ll push it now in the dev, can you test this?
(as always I grabbed code totally from Richard Henninger’s csound6Net)

You can test this like this:

if (Input.GetMouseButtonDown(0)) {
    var list = csound.GetChannelList();
    Debug.Log("list: "+list);
    foreach (var chan in list) {
       Debug.Log(chan.Key+": "+chan.Value.Name+" "+chan.Value.Type+" dir: "+chan.Value.Direction+" "+chan.Value.Hints);
    }
}

I just tried on Windows and I get a crash as soon as I try calling GetChannelList()?

Yes I think it’s something that gets wrong after the native call. it returns 0 channels:

Hold on, I think I know what’s going on. I think we have to declare our channels first. Yes, that’s right, I think we have to use:

https://csound.com/docs/manual/chn.html

This isn’t so useful for us… we don’t want to have to declare all channels in advance of using them…

Btw now I didn’t get the crash without changing anything. :hushed:
I think the way to go is through serializedProperties in editor, it’s a bit difficult to get a custom class from the property, but I’ll find a way:

Regardless of this, I don’t think you can actually retrieve the channels unless they have been declared with the chn opcodes. Which makes this much less usable I think…

Ok fine!
But that method could be useful in the future :wink:

TBH, it needs further investigation. It might still be possible. I guess if we can get it working with chn declared channels then at least we know it works. After that we can check for channels that Csound creates on the fly…

Unfortunately this still crashes as of CsoundUnity version 3.0.1.
Watch out!
The channels can be retrieved with CsoundUnity.channels, but it could be handy to have this method working.
Any expert with native methods?

This is the current definition of the function:

    /// <summary>
    /// Provides a dictionary of all currently defined channels resulting from compilation of an orchestra
    /// containing channel definitions.
    /// Entries, keyed by name, are polymorphically assigned to their correct data type: control, audio, string, pvc.
    /// Used by the Csound6SoftwareBus class to initialize its contents.
    /// </summary>
    /// <returns>a dictionary of all currently defined channels keyed by their name to its ChannelInfo</returns>
    public IDictionary<string, ChannelInfo> GetChannelList()
    {
        IDictionary<string, ChannelInfo> channels = new SortedDictionary<string, ChannelInfo>();
        IntPtr ppChannels = IntPtr.Zero;
        int size = Csound6.NativeMethods.csoundListChannels(csound, out ppChannels);
        if ((size > 0) && (ppChannels != IntPtr.Zero))
        {
            int proxySize = Marshal.SizeOf(typeof(ChannelInfoProxy));
            for (int i = 0; i < size; i++)
            {
                var proxy = Marshal.PtrToStructure(ppChannels + (i * proxySize), typeof(ChannelInfoProxy)) as ChannelInfoProxy;
                string chanName = Marshal.PtrToStringAnsi(proxy.name);
                ChannelInfo info = new ChannelInfo(chanName, (ChannelType)(proxy.type & 15), (ChannelDirection)(proxy.type >> 4));
                var hintProxy = proxy.hints;
                var hints = new ChannelHints((ChannelBehavior)hintProxy.behav, hintProxy.dflt, hintProxy.min, hintProxy.max)
                {
                    x = hintProxy.x,
                    y = hintProxy.y,
                    height = hintProxy.height,
                    width = hintProxy.width,
                    attributes = (hintProxy.attributes != IntPtr.Zero) ? Marshal.PtrToStringAnsi(hintProxy.attributes) : null
                };
                info.Hints = hints;
                channels.Add(chanName, info);
            }
            Csound6.NativeMethods.csoundDeleteChannelList(csound, ppChannels);
        }

        return channels;
    }

Edit: after some more investigation, the call that makes this crash is:

string chanName = Marshal.PtrToStringAnsi(proxy.name);

Proxy is defined as:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private class ChannelInfoProxy
    {
        public IntPtr name;
        public int type;
        [MarshalAs(UnmanagedType.Struct)]
        public ChannelHintsProxy hints;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    private struct ChannelHintsProxy
    {
        public ChannelHintsProxy(ChannelHints hints)
        {
            behav = (int)hints.behav;
            dflt = hints.dflt; min = hints.min; max = hints.max;
            x = hints.x; y = hints.y; height = hints.height; width = hints.width;
            attributes = IntPtr.Zero;
        }

        public int behav;
        public double dflt;
        public double min;
        public double max;
        public int x;
        public int y;
        public int width;
        public int height;
        public IntPtr attributes;
    }