Update of /cvsroot/alsa/alsa-utils/iecset
In directory sc8-pr-cvs1:/tmp/cvs-serv32536/iecset

Added Files:
        .cvsignore Makefile.am iecbits.c iecset.1 iecset.c 
Log Message:
- moved iecset from alsa-lib/test.
- added man page.


--- NEW FILE: .cvsignore ---
.deps
iecset
Makefile
Makefile.in

--- NEW FILE: Makefile.am ---
INCLUDES = -I$(top_srcdir)/include
LDADD = -lm
# LDFLAGS = -static
# CFLAGS += -g -Wall

bin_PROGRAMS = iecset
amixer_SOURCES = iecset.c iecbits.c
man_MANS = iecset.1
EXTRA_DIST = iecset.1

--- NEW FILE: iecbits.c ---
/*
   iecdump - dump IEC958 status bits on ALSA
   Copyright (C) 2003 by Takashi Iwai <[EMAIL PROTECTED]>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <stdio.h>
#include <alsa/asoundlib.h>

struct category_str {
        int val;
        const char *name;
};

static struct category_str con_category[] = {
        { IEC958_AES1_CON_DAT, "DAT" },
        { IEC958_AES1_CON_VCR, "VCR" },
        { IEC958_AES1_CON_MICROPHONE, "microphone" },
        { IEC958_AES1_CON_SYNTHESIZER, "synthesizer" },
        { IEC958_AES1_CON_RATE_CONVERTER, "rate converter" },
        { IEC958_AES1_CON_MIXER, "mixer" },
        { IEC958_AES1_CON_SAMPLER, "sampler" },
        { IEC958_AES1_CON_PCM_CODER, "PCM coder" },
        { IEC958_AES1_CON_IEC908_CD, "CD" },
        { IEC958_AES1_CON_NON_IEC908_CD, "non-IEC908 CD" },
        { IEC958_AES1_CON_GENERAL, "general" },
};


#define ARRAY_SIZE(x) (int)(sizeof(x)/sizeof(x[0]))

void dump_iec958(snd_aes_iec958_t *iec)
{
        int i;

        if (! (iec->status[0] & IEC958_AES0_PROFESSIONAL)) {
                /* consumer */
                printf("Mode: consumer\n");
                printf("Data: ");
                if (!(iec->status[0] & IEC958_AES0_NONAUDIO)) {
                        printf("audio\n");
                } else {
                        printf("non-audio\n");
                }
                printf("Rate: ");
                switch (iec->status[3] & IEC958_AES3_CON_FS) {
                case IEC958_AES3_CON_FS_44100:
                        printf("44100 Hz\n");
                        break;
                case IEC958_AES3_CON_FS_48000:
                        printf("48000 Hz\n");
                        break;
                case IEC958_AES3_CON_FS_32000:
                        printf("32000 Hz\n");
                        break;
                default:
                        printf("unknown\n");
                        break;
                }
                printf("Copyright: ");
                if (iec->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT) {
                        printf("permitted\n");
                } else {
                        printf("protected\n");
                }
                printf("Emphasis: ");
                if ((iec->status[0] & IEC958_AES0_CON_EMPHASIS) != 
IEC958_AES0_CON_EMPHASIS_5015) {
                        printf("none\n");
                } else {
                        printf("50/15us\n");
                }
                printf("Category: ");
                for (i = 0; i < ARRAY_SIZE(con_category); i++) {
                        if ((iec->status[1] & IEC958_AES1_CON_CATEGORY) == 
con_category[i].val) {
                                printf("%s\n", con_category[i].name);
                                break;
                        }
                }
                if (i >= ARRAY_SIZE(con_category)) {
                        printf("unknown 0x%x\n", iec->status[1] & 
IEC958_AES1_CON_CATEGORY);
                }
                printf("Original: ");
                if (iec->status[1] & IEC958_AES1_CON_ORIGINAL) {
                        printf("original\n");
                } else {
                        printf("1st generation\n");
                }
                printf("Clock: ");
                switch (iec->status[3] & IEC958_AES3_CON_CLOCK) {
                case IEC958_AES3_CON_CLOCK_1000PPM:
                        printf("1000 ppm\n");
                        break;
                case IEC958_AES3_CON_CLOCK_50PPM:
                        printf("50 ppm\n");
                        break;
                case IEC958_AES3_CON_CLOCK_VARIABLE:
                        printf("variable pitch\n");
                        break;
                default:
                        printf("unknown\n");
                        break;
                }
        } else {
                printf("Mode: professional\n");
                printf("Data: ");
                if (!(iec->status[0] & IEC958_AES0_NONAUDIO)) {
                        printf("audio\n");
                } else {
                        printf("non-audio\n");
                }
                printf("Rate: ");
                switch (iec->status[0] & IEC958_AES0_PRO_FS) {
                case IEC958_AES0_PRO_FS_44100:
                        printf("44100 Hz\n");
                        break;
                case IEC958_AES0_PRO_FS_48000:
                        printf("48000 Hz\n");
                        break;
                case IEC958_AES0_PRO_FS_32000:
                        printf("32000 Hz\n");
                        break;
                default:
                        printf("unknown\n");
                        break;
                }
                printf("Rate Locked: ");
                if (iec->status[0] & IEC958_AES0_PRO_FREQ_UNLOCKED)
                        printf("no\n");
                else
                        printf("yes\n");
                printf("Emphasis: ");
                switch (iec->status[0] & IEC958_AES0_PRO_EMPHASIS) {
                case IEC958_AES0_PRO_EMPHASIS_CCITT:
                        printf("CCITT J.17\n");
                        break;
                case IEC958_AES0_PRO_EMPHASIS_NONE:
                        printf("none\n");
                        break;
                case IEC958_AES0_PRO_EMPHASIS_5015:
                        printf("50/15us\n");
                        break;
                case IEC958_AES0_PRO_EMPHASIS_NOTID:
                default:
                        printf("unknown\n");
                        break;
                }
                printf("Stereophonic: ");
                if ((iec->status[1] & IEC958_AES1_PRO_MODE) == 
IEC958_AES1_PRO_MODE_STEREOPHONIC) {
                        printf("stereo\n");
                } else {
                        printf("not indicated\n");
                }
                printf("Userbits: ");
                switch (iec->status[1] & IEC958_AES1_PRO_USERBITS) {
                case IEC958_AES1_PRO_USERBITS_192:
                        printf("192bit\n");
                        break;
                case IEC958_AES1_PRO_USERBITS_UDEF:
                        printf("user-defined\n");
                        break;
                default:
                        printf("unkown\n");
                        break;
                }
                printf("Sample Bits: ");
                switch (iec->status[2] & IEC958_AES2_PRO_SBITS) {
                case IEC958_AES2_PRO_SBITS_20:
                        printf("20 bit\n");
                        break;
                case IEC958_AES2_PRO_SBITS_24:
                        printf("24 bit\n");
                        break;
                case IEC958_AES2_PRO_SBITS_UDEF:
                        printf("user defined\n");
                        break;
                default:
                        printf("unknown\n");
                        break;
                }
                printf("Word Length: ");
                switch (iec->status[2] & IEC958_AES2_PRO_WORDLEN) {
                case IEC958_AES2_PRO_WORDLEN_22_18:
                        printf("22 bit or 18 bit\n");
                        break;
                case IEC958_AES2_PRO_WORDLEN_23_19:
                        printf("23 bit or 19 bit\n");
                        break;
                case IEC958_AES2_PRO_WORDLEN_24_20:
                        printf("24 bit or 20 bit\n");
                        break;
                case IEC958_AES2_PRO_WORDLEN_20_16:
                        printf("20 bit or 16 bit\n");
                        break;
                default:
                        printf("unknown\n");
                        break;
                }
        }
}


--- NEW FILE: iecset.1 ---
.TH iecset 1 "23 Oct 2003"
.SH NAME
iecset \- Set or dump IEC958 status bits

.SH SYNOPSIS
\fBiecset\fP [\fIoptions\fP] [\fIcmd\fP \fIarg\fP...]

.SH DESCRIPTION
\fBiecset\fP is a small utility to set or dump the IEC958 (or so-called
"S/PDIF") status bits of the specified sound card via ALSA control API.

When \fBiecset\fP is started without arguments except for options,
it will show the current IEC958 status in a human-readable form.
When the commands are given in the arguments, they are parsed
and the IEC958 status bits are updated.  The resultant status is
shown as well.

The commands consist of the command directive and the argument.
As the boolean argument, \fIyes\fP, \fIno\fP, \fItrue\fP, \fIfalse\fI,
or a digit number is allowed.

.SH EXAMPLES
.TP
.BI iecset\ \-Dhw:1
Displays the current IEC958 status bits on the second card.
This is equivalent with \fI-c 1\fP.
.TP
.BI iecset\ \-x
Displays the current IEC958 status bits in a style of the arguments
for the PCM stream.  The output string can be passed to the \fIiec958\fP
(or \fIspdif\fP) PCM type as the optional argument.
.TP
.BI iecset\ pro\ off\ audio\ off
Sets the current status to the consumer-mode and turns on the
non-audio bit.  The modified status will be shown, too.

.SH OPTIONS
.TP
\fI-D\fP device
Specifies the device name of the control to open
.TP
\fI-c\fP card
Specifies the card index to open.  Equivalent with \fI-Dhw:x\fP.
.TP
\fI-x\fP
Dumps the status in the form of AESx bytes.
.TP
\fI-i\fP
Reads the command sequences from stdin.
Each line has single command.

.SH COMMANDS
.TP
\fIprofessional\fP <bool>
The professional mode (true) or consumer mode (false).

.TP
\fIaudio\fP <bool>
The audio mode (true) or non-audio mode (false).

.TP
\fIrate\fP <int>
The sample rate in Hz.

.TP
\fIemphasis\fP <int>
The emphasis: 0 = none, 1 = 50/15us, 2 = CCITT.

.TP
\fIlock\fP <bool>
Rate lock: locked (true), unlocked (false).
This command is for the professional mode only.

.TP
\fIsbits\fP <int>
Sample bits:  2 = 20bit, 4 = 24bit, 6 = undefined.
This command is for the professional mode only.

.TP
\fIwordlength\fP <int>
Wordlength: 0 = No, 2 = 22-18 bit, 4 = 23-19 bit, 5 = 24-20 bit, 6 = 20-16 bit.
This command is for the professional mode only.

.TP
\fIcategory\fP <int>
Category: the value is from 0 to 0x7f.
This command is for the consumer mode only.

.TP
\fIcopyright\fP <bool>
Copyright: copyrighted (true), non-copyrighted (false).
This command is for the consumer mode only.

.TP
\fIoriginal\fP <boo>
Original flag: original (true), 1st generation (false).
This command is for the consumer mode only.

.SH AUTHOR
Takashi Iwai <[EMAIL PROTECTED]>

--- NEW FILE: iecset.c ---
/*
   iecset - change IEC958 status bits on ALSA
   Copyright (C) 2003 by Takashi Iwai <[EMAIL PROTECTED]>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <stdio.h>
#include <ctype.h>
#include <alsa/asoundlib.h>

#include "iecbits.c"

static int get_bool(const char *str)
{
        if (strncmp(str, "yes", 3) == 0 ||
            strncmp(str, "YES", 3) == 0 ||
            strncmp(str, "on", 2) == 0 ||
            strncmp(str, "ON", 2) == 0 ||
            strncmp(str, "true", 4) == 0 ||
            strncmp(str, "TRUE", 4) == 0 ||
            *str == '1')
                return 1;
        return 0;
}

enum {
        CMD_BOOL, CMD_BOOL_INV, CMD_INT
};

enum {
        IDX_PRO, IDX_NOAUDIO, IDX_RATE, IDX_UNLOCK, IDX_SBITS, IDX_WORD, IDX_EMP, 
IDX_CAT, IDX_NOCOPY, IDX_ORIG,
        IDX_LAST
};

struct cmdtbl {
        const char *name;
        int idx;
        int type;
        const char *desc;
};

static struct cmdtbl cmds[] = {
        { "pro", IDX_PRO, CMD_BOOL,
          "professional (common)\n\toff = consumer mode, on = professional mode" },
        { "aud", IDX_NOAUDIO, CMD_BOOL_INV,
          "audio (common)\n\toff = audio mode, on = non-audio mode" },
        { "rat", IDX_RATE, CMD_INT,
          "sample rate (common)\n\tsample rate in Hz" },
        { "emp", IDX_EMP, CMD_INT,
          "emphasis (common)\n\t0 = none, 1 = 50/15us, 2 = CCITT" },
        { "loc", IDX_UNLOCK, CMD_BOOL_INV,
          "lock (prof.)\n\toff = rate unlocked, on = rate locked" },
        { "sbi", IDX_SBITS, CMD_INT,
          "sbits (prof.)\n\tsample bits 2 = 20bit, 4 = 24bit, 6 = undef" },
        { "wor", IDX_WORD, CMD_INT,
          "wordlength (prof.)\n\t0=no, 2=22-18bit, 4=23-19bit, 5=24-20bit, 6=20-16bit" 
},
        { "cat", IDX_CAT, CMD_INT,
          "category (consumer)\n\t0-0x7f" },
        { "cop", IDX_NOCOPY, CMD_BOOL_INV,
          "copyright (consumer)\n\toff = non-copyright, on = copyright" },
        { "ori", IDX_ORIG, CMD_BOOL,
          "original (consumer)\n\toff = 1st-gen, on = original" },
};


static void usage(void)
{
        int i;

        printf("Usage: iecset [options] [cmd arg...]\n");
        printf("Options:\n");
        printf("    -D device   specifies the control device to use\n");
        printf("    -c card     specifies the card number to use (equiv. with 
-Dhw:#)\n");
        printf("    -x          dump the dump the AESx hex code for IEC958 PCM 
parameters\n");
        printf("    -i          read commands from stdin\n");
        printf("Commands:\n");
        for (i = 0; i < (int)(sizeof(cmds)/sizeof(cmds[0])); i++) {
                printf("    %s\n", cmds[i].desc);
        }
}


/*
 * parse iecset commands
 */
static void parse_command(int *parms, const char *c, const char *arg)
{
        int i;

        for (i = 0; i < (int)(sizeof(cmds)/sizeof(cmds[0])); i++) {
                if (strncmp(c, cmds[i].name, strlen(cmds[i].name)) == 0) {
                        int val;
                        switch (cmds[i].type) {
                        case CMD_BOOL:
                                val = get_bool(arg);
                                break;
                        case CMD_BOOL_INV:
                                val = !get_bool(arg);
                                break;
                        case CMD_INT:
                        default:
                                val = (int)strtol(arg, NULL, 0);
                                break;
                        }
                        parms[cmds[i].idx] = val;
                        return;
                }
        }
}

static char *skipspace(char *line)
{
        char *p;
        for (p = line; *p && isspace(*p); p++)
                ;
        return p;
}

/*
 * parse iecset commands from the file
 */
static void parse_file(int *parms, FILE *fp)
{
        char line[1024], *cmd, *arg;
        while (fgets(line, sizeof(line), fp) != NULL) {
                cmd = skipspace(line);
                if (*cmd == '#' || ! *cmd)
                        continue;
                for (arg = cmd; *arg && !isspace(*arg); arg++)
                        ;
                if (! *arg)
                        continue;
                *arg++ = 0;
                arg = skipspace(arg);
                if (! *arg)
                        continue;
                parse_command(parms, cmd, arg);
        }
}

/* update iec958 status values
 * return non-zero if the values are modified
 */
static int update_iec958_status(snd_aes_iec958_t *iec958, int *parms)
{
        int changed = 0;
        if (parms[IDX_PRO] >= 0) {
                if (parms[IDX_PRO])
                        iec958->status[0] |= IEC958_AES0_PROFESSIONAL;
                else
                        iec958->status[0] &= ~IEC958_AES0_PROFESSIONAL;
                changed = 1;
        }
        if (parms[IDX_NOAUDIO] >= 0) {
                if (parms[IDX_NOAUDIO])
                        iec958->status[0] |= IEC958_AES0_NONAUDIO;
                else
                        iec958->status[0] &= ~IEC958_AES0_NONAUDIO;
                changed = 1;
        }
        if (parms[IDX_RATE] >= 0) {
                if (iec958->status[0] & IEC958_AES0_PROFESSIONAL) {
                        iec958->status[0] &= ~IEC958_AES0_PRO_FS;
                        switch (parms[IDX_RATE]) {
                        case 44100:
                                iec958->status[0] |= IEC958_AES0_PRO_FS_44100;
                                break;
                        case 48000:
                                iec958->status[0] |= IEC958_AES0_PRO_FS_48000;
                                break;
                        case 3200:
                                iec958->status[0] |= IEC958_AES0_PRO_FS_32000;
                                break;
                        }
                } else {
                        iec958->status[3] &= ~IEC958_AES3_CON_FS;
                        switch (parms[IDX_RATE]) {
                        case 44100:
                                iec958->status[3] |= IEC958_AES3_CON_FS_44100;
                                break;
                        case 48000:
                                iec958->status[3] |= IEC958_AES3_CON_FS_48000;
                                break;
                        case 3200:
                                iec958->status[3] |= IEC958_AES3_CON_FS_32000;
                                break;
                        }
                }
                changed = 1;
        }
        if (parms[IDX_NOCOPY] >= 0) {
                if (! (iec958->status[0] & IEC958_AES0_PROFESSIONAL)) {
                        if (parms[IDX_NOCOPY])
                                iec958->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT;
                        else
                                iec958->status[0] &= ~IEC958_AES0_CON_NOT_COPYRIGHT;
                }
                changed = 1;
        }
        if (parms[IDX_ORIG] >= 0) {
                if (! (iec958->status[0] & IEC958_AES0_PROFESSIONAL)) {
                        if (parms[IDX_ORIG])
                                iec958->status[1] |= IEC958_AES1_CON_ORIGINAL;
                        else
                                iec958->status[1] &= ~IEC958_AES1_CON_ORIGINAL;
                }
                changed = 1;
        }
        if (parms[IDX_EMP] >= 0) {
                if (iec958->status[0] & IEC958_AES0_PROFESSIONAL) {
                        iec958->status[0] &= ~IEC958_AES0_PRO_EMPHASIS;
                        switch (parms[IDX_EMP]) {
                        case 0:
                                iec958->status[0] |= IEC958_AES0_PRO_EMPHASIS_NONE;
                                break;
                        case 1:
                                iec958->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015;
                                break;
                        case 2:
                                iec958->status[0] |= IEC958_AES0_PRO_EMPHASIS_CCITT;
                                break;
                        }
                } else {
                        if (parms[IDX_EMP])
                                iec958->status[0] |= IEC958_AES0_CON_EMPHASIS_5015;
                        else
                                iec958->status[0] &= ~IEC958_AES0_CON_EMPHASIS_5015;
                }
                changed = 1;
        }
        if (parms[IDX_UNLOCK] >= 0) {
                if (iec958->status[0] & IEC958_AES0_PROFESSIONAL) {
                        if (parms[IDX_UNLOCK])
                                iec958->status[0] |= IEC958_AES0_PRO_FREQ_UNLOCKED;
                        else
                                iec958->status[0] &= ~IEC958_AES0_PRO_FREQ_UNLOCKED;
                }
                changed = 1;
        }
        if (parms[IDX_SBITS] >= 0) {
                if (iec958->status[0] & IEC958_AES0_PROFESSIONAL) {
                        iec958->status[2] &= ~IEC958_AES2_PRO_SBITS;
                        iec958->status[2] |= parms[IDX_SBITS] & 7;
                }
                changed = 1;
        }
        if (parms[IDX_WORD] >= 0) {
                if (iec958->status[0] & IEC958_AES0_PROFESSIONAL) {
                        iec958->status[2] &= ~IEC958_AES2_PRO_WORDLEN;
                        iec958->status[2] |= (parms[IDX_WORD] & 7) << 3;
                }
                changed = 1;
        }
        if (parms[IDX_CAT] >= 0) {
                if (! (iec958->status[0] & IEC958_AES0_PROFESSIONAL)) {
                        iec958->status[1] &= ~IEC958_AES1_CON_CATEGORY;
                        iec958->status[1] |= parms[IDX_CAT] & 0x7f;
                }
                changed = 1;
        }

        return changed;
}
                

int main(int argc, char **argv)
{
        const char *dev = "default";
        const char *spdif_str = "IEC958 Playback Default";
        snd_ctl_t *ctl;
        snd_ctl_elem_value_t *cval;
        snd_aes_iec958_t iec958;
        int from_stdin = 0;
        int dumphex = 0;
        int i, c;
        char tmpname[32];
        int parms[IDX_LAST];

        for (i = 0; i < IDX_LAST; i++)
                parms[i] = -1; /* not set */

        while ((c = getopt(argc, argv, "D:c:xhi")) != -1) {
                switch (c) {
                case 'D':
                        dev = optarg;
                        break;
                case 'c':
                        i = atoi(optarg);
                        if (i < 0 || i >= 7) {
                                fprintf(stderr, "invalid card index %d\n", i);
                                return 1;
                        }
                        sprintf(tmpname, "hw:%d", i);
                        dev = tmpname;
                        break;
                case 'x':
                        dumphex = 1;
                        break;
                case 'i':
                        from_stdin = 1;
                        break;
                default:
                        usage();
                        return 1;
                }
        }

        if (snd_ctl_open(&ctl, dev, 0) < 0) {
                perror("snd_ctl_open");
                return 1;
        }

        snd_ctl_elem_value_alloca(&cval);
        snd_ctl_elem_value_set_interface(cval, SND_CTL_ELEM_IFACE_MIXER);
        snd_ctl_elem_value_set_name(cval, spdif_str);
        if (snd_ctl_elem_read(ctl, cval) < 0) {
                snd_ctl_elem_value_set_interface(cval, SND_CTL_ELEM_IFACE_PCM);
                if (snd_ctl_elem_read(ctl, cval) < 0) {
                        perror("snd_ctl_elem_read");
                        return 1;
                }
        }

        snd_ctl_elem_value_get_iec958(cval, &iec958);

        /* parse from stdin */
        if (from_stdin)
                parse_file(parms, stdin);

        /* parse commands */
        for (c = optind; c < argc - 1; c += 2)
                parse_command(parms, argv[c], argv[c + 1]);

        if (update_iec958_status(&iec958, parms)) {
                /* store the values */
                snd_ctl_elem_value_set_iec958(cval, &iec958);
                if (snd_ctl_elem_write(ctl, cval) < 0) {
                        perror("snd_ctl_elem_write");
                        return 1;
                }
                if (snd_ctl_elem_read(ctl, cval) < 0) {
                        perror("snd_ctl_elem_write");
                        return 1;
                }
                snd_ctl_elem_value_get_iec958(cval, &iec958);
        }

        if (dumphex)
                printf("AES0=0x%02x,AES1=0x%02x,AES2=0x%02x,AES3=0x%02x\n",
                       iec958.status[0], iec958.status[1], iec958.status[2], 
iec958.status[3]);
        else
                dump_iec958(&iec958);

        snd_ctl_close(ctl);
        return 0;
}



-------------------------------------------------------
This SF.net email is sponsored by: The SF.net Donation Program.
Do you like what SourceForge.net is doing for the Open
Source Community?  Make a contribution, and help us add new
features and functionality. Click here: http://sourceforge.net/donate/
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to