cd-da-reader 1.0.0

CD-DA (audio CD) reading library
Documentation
#include "shim_common.h"

static bool copy_bsd_name(io_service_t media, char *outName, size_t outNameLen) {
    if (!outName || outNameLen == 0) {
        return false;
    }

    CFTypeRef bsd = IORegistryEntryCreateCFProperty(
        media,
        CFSTR(kIOBSDNameKey),
        kCFAllocatorDefault,
        0
    );
    if (!bsd) {
        return false;
    }

    bool ok = false;
    if (CFGetTypeID(bsd) == CFStringGetTypeID()) {
        ok = CFStringGetCString((CFStringRef)bsd, outName, outNameLen, kCFStringEncodingUTF8);
    }

    CFRelease(bsd);
    return ok;
}

bool list_cd_drives(CdDriveInfo **outDrives, uint32_t *outCount) {
    if (!outDrives || !outCount) {
        return false;
    }

    *outDrives = NULL;
    *outCount = 0;

    CFMutableDictionaryRef match = IOServiceMatching(kIOCDMediaClass);
    if (!match) {
        return false;
    }

    io_iterator_t it = IO_OBJECT_NULL;
    kern_return_t kr = IOServiceGetMatchingServices(kIOMainPortDefault, match, &it);
    if (kr != KERN_SUCCESS) {
        return false;
    }

    CdDriveInfo *drives = NULL;
    uint32_t count = 0;
    io_service_t media;

    while ((media = IOIteratorNext(it))) {
        CdDriveInfo info;
        memset(&info, 0, sizeof(info));

        if (copy_bsd_name(media, info.bsd_name, sizeof(info.bsd_name))) {
            CdDriveInfo *next = realloc(drives, (count + 1) * sizeof(CdDriveInfo));
            if (!next) {
                IOObjectRelease(media);
                free(drives);
                IOObjectRelease(it);
                return false;
            }

            drives = next;
            drives[count] = info;
            count++;
        }

        IOObjectRelease(media);
    }

    IOObjectRelease(it);

    *outDrives = drives;
    *outCount = count;
    return true;
}