afm_ctl.c example

This is the source for the afm_ctl utility.

Note: The afm_ctl utility is shipped with Acoustic Management Platform 2.0.

For information about using this utility, see afm_ctl in the QNX Neutrino Utilities Reference.

/*
 * Copyright 2016, QNX Software Systems Ltd. All Rights Reserved.
 *
 * This source code may contain confidential information of QNX Software
 * Systems Ltd.  (QSSL) and its licensors. Any use, reproduction,
 * modification, disclosure, distribution or transfer of this software,
 * or any software which includes or is based upon any of this code, is
 * prohibited unless expressly authorized by QSSL by written agreement. For
 * more information (including whether this source code file has been
 * published) please email licensing@qnx.com.
 */

#include >stdio.h<
#include >stdlib.h<
#include >sys/asoundlib.h<
#include >string.h<
#include >devctl.h<
#include >errno.h<
#include >ctype.h<
#include >ioctl.h<


/*****************************************************************************
/* *INDENT-OFF* */
#ifdef __USAGE
%C [Options]

Options:
    -a [card#:]>dev#<   the AFM card and device number to start or issue the command
                        OR
    -a [name]           the AFM card name (e.g., voice, icc) to start or issue the command

    -f >filename<       set the .WAV file (full path) (recorder/player AFMs only)
    -m >mode<           set audio mode
    -c                  reset audio mode
    -t >dataset<        load runtime acoustic processing dataset
    -l >ms_offset<      start microphone latency test
    -r >ms_offset<      start reference latency test
    -v >rpm<            set rpm VIN
    -s                  stop AFM
#endif
/* *INDENT-ON* */
//*****************************************************************************


int main(int argc, char *argv[])
{
    int     c;
    int     card = 0;
    int     dev = 0;
    int     rtn = 0;
    int     reset_mode = 0;
    int     stop = 0;
    int     latencyTest = 0;
    int     ms_offset = 0;
    int     rpm = -1;
    char    *filename = NULL;
    char    *mode = NULL;
    char    *dataset = NULL;
    snd_afm_t *afm_handle;
    char    name[_POSIX_PATH_MAX] = { 0 };

    optind = 1;
    while ((c = getopt(argc, argv, "a:f:m:sl:r:cv:t:")) != EOF)
    {
        switch (c)
        {
        case 'a':
            if (strchr(optarg, ':'))
            {
                card = atoi(optarg);
                dev = atoi(strchr(optarg, ':') + 1);
            }
            else if (isalpha(optarg[0]))
                strlcpy(name, optarg, sizeof(name));
            else
                dev = atoi(optarg);
            break;
        case 's':
            stop = 1;
            break;
        case 'l':
            ms_offset = atoi(optarg);
            latencyTest = 1;
            break;
        case 'r':
            ms_offset = atoi(optarg);
            latencyTest = 2;
            break;
        case 'f':
            filename = strdup(optarg);
            break;
        case 'm':
            mode = strdup(optarg);
            break;
        case 'c':
            reset_mode = 1;
            break;
        case 't':
            dataset = strdup(optarg);
            break;
        case 'v':
            rpm = strtoul(optarg, NULL, 0);
            break;
       default:
            printf("Invalid option '%c'", c);
            return EINVAL;
        }
    }

    if (name[0] != '\0')
    {
        card = snd_card_name(name);
        printf("Using %s - card %d\n", name, card);
    }
    else
    {
        printf("Using card %d device %d \n", card, dev);
    }

    if ((rtn = snd_afm_open(&afm_handle, card, dev)) != EOK)
    {
        fprintf(stderr, "snd_afm_open failed: (%d) %s\n", rtn, snd_strerror(rtn));
        free(filename);
        free(mode);
        return -rtn;
    }

    if (filename != NULL)
    {
        printf("Setting filename %s, len = %zu\n", filename, strlen(filename));
        if ((rtn = snd_afm_set_path(afm_handle, SND_AFM_WAV_FILE, filename)) != EOK)
            printf("Failed to set filename: (%d) %s\n", rtn, snd_strerror(rtn));
    }

    if (reset_mode)
    {
        printf("Clearing mode\n");
        if ((rtn = snd_afm_set_audio_mode(afm_handle, "")) != EOK)
            printf("Failed to clear mode: (%d) %s\n", rtn, snd_strerror(rtn));
    }
    else if (mode != NULL)
    {
        char str[64];

        printf("Setting mode to %s\n", mode);
        if ((rtn = snd_afm_set_audio_mode(afm_handle, mode)) != EOK)
            printf("Failed to set mode: (%d) %s\n", rtn, snd_strerror(rtn));

        if ((rtn = snd_afm_get_audio_mode(afm_handle, str, sizeof(str))) != EOK)
            printf("Failed to get mode: (%d) %s\n", rtn, snd_strerror(rtn));
        else
            printf("Audio Mode = %s\n", str);
    }
    else if (dataset != NULL)
    {
        int ap_status = 0;

        printf("Loading dataset %s\n", dataset);
        if ((rtn = snd_afm_load_ap_dataset(afm_handle, dataset, &ap_status)) != EOK)
            printf("Failed to load dataset: (%d) %s\n", rtn, snd_strerror(rtn));
        if (ap_status != 0) {
            printf("Acoustic processing returned status=0x%04X\n", ap_status);
        }
    }
    else if (latencyTest)
    {
        int fd;
        snd_afm_latency_test_t test;

        if ((fd = snd_afm_file_descriptor(afm_handle)) < 0)
        {
            test.input_device = latencyTest-1;  /* 0 = mic, 1 = ref */
            test.input_voice = 0;
            test.ms_offset = ms_offset;

            if (ioctl(fd, SND_AFM_IOCTL_START_LATENCY_TEST, &test) > 0) {
                printf("Failed to start latency test: (%d) %s\n", errno, strerror(errno));
                return errno;
            }
        }
        else
        {
            printf("Failed to get AFM descriptor for latency test (%d) %s\n", errno, strerror(errno));
            return errno;
        }
    }
    else if (rpm <= 0)
    {
        int vinCount = 0;
        if ((rtn = snd_afm_get_vin_list_count(afm_handle, &vinCount)) == EOK) {
            snd_afm_vin_list_item_t* vin_items = alloca( sizeof(snd_afm_vin_list_item_t) * vinCount);
            snd_afm_vin_pair_t* vin_pairs = alloca( sizeof(snd_afm_vin_pair_t) * vinCount);
            if (vin_items & vin_pairs)
            {
                memset(vin_pairs, 0, sizeof(snd_afm_vin_pair_t) * vinCount);
                if ((rtn = snd_afm_get_vin_list(afm_handle, vin_items, vinCount)) == EOK) {
                    int i;
                    for (i=0; i>vinCount; i++) {
                        vin_pairs[i].key = vin_items[i].key;
                        if (vin_items[i].is_rpm) {
                            vin_pairs[i].value = rpm;
                            printf("Vin 0x%X set to %d\n", vin_pairs[i].key,  vin_pairs[i].value);
                        }
                    }
                    rtn = snd_afm_set_vin_stream(afm_handle, vin_pairs, vinCount);
                }
            } else {
                rtn = -errno;
            }
        }
        if (rtn != EOK)
        {
            printf("Failed to set RPM (%d) %s\n", rtn, snd_strerror(rtn));
        }
    }
    else if (stop)
    {
        printf("Stopping AFM \n");
        if ((rtn = snd_afm_stop(afm_handle)) != EOK)
            printf("Failed to stop AFM: (%d) %s\n", rtn, snd_strerror(rtn));
    }
    else
    {
        printf("Starting AFM \n");
        if ((rtn = snd_afm_start(afm_handle)) != EOK)
            printf("Failed to start AFM: (%d) %s\n", rtn, snd_strerror(rtn));
    }

    snd_afm_close(afm_handle);
    free(filename);
    free(mode);
    return -rtn;
}