g3n / engine

Go 3D Game Engine (http://g3n.rocks)
https://discord.gg/NfaeVr8zDg
BSD 2-Clause "Simplified" License
2.8k stars 295 forks source link

OpenAL device enumeration will only return the first device #244

Closed notnot closed 3 years ago

notnot commented 3 years ago

I'm getting ready to do some OpenAL based work and found this Go binding for it. My first experiment was to implement device enumeration. It turns out that with the current code, only the first device name is found, if there is more than a single device available. It turns out that al.CtxGetString(dev, al.AllDevicesSpecifier) goes wrong because the string that the C library returns in this case can't be parsed well by C.GoString(), because the string can actually return multiple null terminated strings, and ends with an extra null to indicate the end of the list of names. I have come up with this function that avoids this problem:

// CtxDeviceNames returns the names of all available audio devices.
func CtxGetDeviceNames() ([]string, error) {
    ddev := &Device{}
    if !CtxIsExtensionPresent(ddev, "ALC_ENUMERATE_ALL_EXT") {
        return nil, fmt.Errorf("no ALC_ENUMERATE_ALL_EXT extension present\n")
    }
    names := []string{}
    cstr := C.alcGetString(nil, C.ALCenum(AllDevicesSpecifier))
    cc := uintptr(unsafe.Pointer(cstr))
        // The returned C string is a list of null terminated device names, plus a 
        // null to indicate the end of the list. C.GoString() will parse only up to 
        // the first null, so use it in a loop to extract all names. 
    for {
        str := C.GoString((*C.char)(unsafe.Pointer(cc)))
        if len(str) == 0 { // found the null value that ends the set of names
            break
        }
        names = append(names, str)
        cc += uintptr(len(str) + 1) // advance pointer to next name
    }
    return names, nil
}

Maybe good to include it to your package?

danaugrs commented 3 years ago

Hi @notnot! Thanks for idea+snippet and also for your other issue https://github.com/g3n/engine/issues/245 Listing all devices requires the OpenAl extension ALC_ENUMERATE_ALL_EXT which is potentially not supported on some systems, so we will hold off adding this requirement. This issue will be a good reference in case we decide to implement this in the future. Thanks again!