Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Aug 2001 17:15:19 -0400
From:      The Anarcat <anarcat@anarcat.dyndns.org>
To:        Cameron Grant <gandalf@vilnya.demon.co.uk>
Cc:        freebsd-multimedia@freebsd.org
Subject:   Test record program triggers pcm problems on -stable (was: Re: kern/21438: Sox recording in 16 bits creates a panic: no feed)
Message-ID:  <20010815171514.B471@shall.anarcat.dyndns.org>
In-Reply-To: <007301c0c6af$4d399650$0504020a@haveblue>
References:  <3ADB420A.B1B696A4@lmc.ericsson.se> <005901c0c6aa$4ec49560$0504020a@haveblue> <3ADB4835.E34532A5@lmc.ericsson.se> <007301c0c6af$4d399650$0504020a@haveblue>

next in thread | previous in thread | raw e-mail | index | archive | help

--ZJcv+A0YCCLh2VIg
Content-Type: multipart/mixed; boundary="5G06lTa6Jq83wMTw"
Content-Disposition: inline


--5G06lTa6Jq83wMTw
Content-Type: text/plain; charset=us-ascii
Content-Description: Mail text
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi Cameron.

I hope you won't mind I CC: this to -multimedia for a wider audience. :)

I fleshed out my "rec" program. I wrote this thing about a year ago and
now it seems to be in order. I mainly use it as a replacement for sox,
since sox seems unsuitable to make hifi recordings. I think rec is great,
and I intend to make a port out of it (or put it in the base system?) ;)
Also, I would like to request your comments on the program itself.

Note that the program records hifi by default (44100 Hz, 16 bits, 2
channels).

Now I have a few problems with it:

1- pcm0: record overrun, dumping 178180 bytes

Good old error message, do I like this one. :) I only have this problem
when recording without time limit (-t 0/-f 0 or no -t/-f switch).
Recording small samples (using -t 10) works fine. Strange.

How can I debug this?

2- raw data filled

As you described to me in another mail, in some circumstances where the
hw support is not enough, the data stream is filled to pad bytes. Is
this the case here:

00000000: 04fe 50fe 08fe 54fe 09fe 51fe 05fe 52fe  ..P...T...Q...R.
00000010: 0efe 59fe 05fe 4dfe 07fe 4ffe 0afe 50fe  ..Y...M...O...P.
00000020: 07fe 4ffe 04fe 58fe 0dfe 52fe fffd 55fe  ..O...X...R...U.
00000030: 0afe 4dfe fefd 52fe 0bfe 5afe 02fe 4cfe  ..M...R...Z...L.

Sure does look like it. What do you think?

3- ioctls does not seem to work properly.

At some point in the code, I call the ioctls:

  if (ioctl(fd, SOUND_PCM_READ_CHANNELS, &params->r_channels))
    err(1, "ioctl for read channels failed");
  if (ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &params->w_channels))
    err(1, "ioctl for write channels failed");

(for example). Now the value of params->*_channels is 2 in both cases.
The output of the program, however, is:

             read       write      units
DSP device : /dev/dspW  /dev/dspW=20
Rate       : 8000       44100      Hz
Channels   : 1          2        =20
Size       : 16         16         bits

ie, params->r_channels is *changed* from 2 to 1. Same goes for r_rate. I
do not understand that behavior.=20

I know the test program is a bit crappy, especially in time
calculations, but it does the job, and I understand it well. :)

Please review the program, and tell me what is wrong here! I really need
a hifi recording program for FreeBSD. The next step a multi-track mixing
program, and I think I'm doing a good job at porting "mixmagic", a gnome
mixing program.

Anyways, the program is attached, only 2 are necessary to compile it,
(rec.c, convert.h) but as the code tells, it also has primary support to
record aiff sound files. For that it needs 4 more files (aiff.[ch],
ieee_ext.[ch]).

I include here only rec.c and convert.h.

Read on...

On Mon, 16 Apr 2001, Cameron Grant wrote:

> > Uh-uh.. Ok. This is what I understood. This is very good. Does that mean
> > I can do multiple open of /dev/dsp? I can't wait to try that out. :)
>=20
> no, but multiple dsp devices are created.  the device nodes are not creat=
ed
> by MAKEDEV under -stable, but if you read sys/dev/sound/pcm/sound.c and
> create the appropriate nodes yourself multiple opens will work.  this is
> obviously not supported usage yet, however.

Is this still applicable? I took a peak at sound.c and didn't really
figure it out.

> > OK. That is very good. And this was my concern in the first place. The
> > problem (panic) is fixed under -stable  but I'm not sure wether
> > recording still works 100% correctly. There was still this overflow
> > problem that was crippling recording. I think it is also fixed, but
> > cannot confirm. I will check all this tonight, on my AWE32 and my SBC16
> > Vibra cards. :)
>=20
> it did work when i tested it.
>=20
> the overflow problem occurs when a recording application reads too slowly.
> sox appears to read 4 bytes at a time, so the syscall overhead is extreme.
> i don't understand how it is supposed to work as at 44khz 16bit stereo th=
is
> results in >44000 syscalls per second which requires a very fast machine.
> other apps which use a larger buffer do work properly.  this does not seem
> to be related to newpcm.

I tried various buffer sizes. The default is 1092 (BUFSIZ) and I tried
up to 8192, without noticeable effect.

I think the problem might be in the rec.c code itself, especially in the
recording loop where time is (so badly) displayed and computed, but I am
not sure.

A.

--5G06lTa6Jq83wMTw
Content-Type: text/plain; charset=us-ascii
Content-Description: Conversion routines
Content-Disposition: attachment; filename="convert.h"

/****************************-*-C-*-***********************************
 * $Id: convert.h,v 1.5 2001/08/15 18:37:18 anarcat Exp $
 **********************************************************************
 * Conversion routines for sound parameters
 **********************************************************************
 *   Copyright (C) 2001 The Anarcat
 *
 * 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
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  See also http://www.fsf.org
 *********************************************************************/

#ifndef CONVERT_H
#define CONVERT_H

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef USE_AIFF
/* Compute the "very large number" so that a maximum number of samples
 * can be transmitted through a pipe without the risk of causing
 * overflow when calculating the number of bytes.  At 48 kHz, 16 bits
 * stereo, this gives ~3 hours of music.  Sorry, the AIFF format does
 * not provide for an "infinite" number of samples. */
#define MAX_BYTES 0x7f000000L
#endif

#define MAX_FRAMES(size, channels) (MAX_BYTES / ((size)/8) * (channels))
#define MAX_TIME(size, channels, frames) \
(MAX_FRAMES(size, channels) / (frames))

#define BYTES_FROM_FRAMES(frames, size, channels) \
                         ((frames) * (channels) * ((size)/8))

#define SAMPLES_FROM_BYTES(bytes, size) \
                         ((bytes) / ((size) / 8))

#define FRAMES_FROM_BYTES(bytes, size, channels) \
                         (SAMPLES_FROM_BYTES(bytes, size) / (channels))

#define TIME_FROM_BYTES(bytes, size, channels, rate) \
                       (FRAMES_FROM_BYTES(bytes, size, channels) / (rate))

#define FRAMES_FROM_TIME(time, rate) \
                         ((time) * (rate))

#define SAMPLES_FROM_TIME(time, rate, channels) \
                         (FRAMES_FROM_TIME(time, rate) * (channels))

#define BYTES_FROM_TIME(time, rate, channels, size) \
                       (SAMPLES_FROM_TIME(time, rate, channels) * ((size)/8))

#endif

--5G06lTa6Jq83wMTw
Content-Type: text/plain; charset=us-ascii
Content-Description: Record program
Content-Disposition: attachment; filename="rec.c"
Content-Transfer-Encoding: quoted-printable

/****************************-*-C-*-***********************************
 * $Id: rec.c,v 0.23 2001/08/15 21:09:43 anarcat Exp $
 **********************************************************************
 * DSP recording utility for FreeBSD
 **********************************************************************
 *   Copyright (C) 2000 The Anarcat <anarcat@tao.ca>
 *
 * 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
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  See also http://www.fsf.org
 *********************************************************************/

/*
 * This program can be used to record RAW (PCM) audio from the DSP device
 *
 * See the help (./rec -h) for more info
 *
 * Note that the resulting file can be easily converted to WAVE using sox:
 *
 * $ sox -c 2 -r 44100 -w -s file.raw file.wav
 */

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <machine/soundcard.h>
#include <err.h>
#include <signal.h>
#ifndef NDEBUG
#include <assert.h>
#include <sys/time.h>
#endif

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "convert.h"
#ifdef USE_AIFF
#include "ieee_ext.h"
#include "aiff.h"
#endif

#define DFL_DEV "/dev/dspW"
#define DFL_SIZE 16
#define DFL_CHAN 2
#define DFL_RATE 44100

int snddev;                     /* sound device to read from */
#ifdef USE_AIFF
AIFFSound aiffSnd;              /* sound to write */
#endif
int sndFile;                    /* file to write it to */

#ifndef NDEBUG
struct timeval start;           /* start of recording */
struct timeval end;             /* end of recording */
#endif

typedef struct _dsp_parameters {

  char* device;                 /* device name */
  unsigned int r_rate;          /* read sample rate */
  unsigned int w_rate;          /* write sample rate */
  unsigned int r_channels;      /* channels to use (1: mono, 2: stereo) */
  unsigned int w_channels;      /* write channels */
  unsigned int r_size;          /* read sample size (8 bits or 16 bits) */
  unsigned int w_size;          /* write sample size */
 =20
} dsp_parameters;

/* handles an interrupt in raw readings */
void quit(int signum) {

#ifndef NDEBUG
  long int secs, msecs;
#endif
  fprintf(stderr, "\n");

#ifndef NDEBUG
  assert(!gettimeofday(&end, NULL));
 =20
  secs =3D end.tv_sec - start.tv_sec;
  msecs =3D end.tv_usec - start.tv_usec;
  if (msecs < 0) {              /* keep ms > 0 */
    secs--;
    msecs +=3D 1000000;
  }
  assert (msecs >=3D 0);

  fprintf(stderr, "recording duration: %li.%6.6li secs\n",=20
          secs,msecs);
#endif

  close(snddev);
  close(sndFile);
  if (signum > 0) {
    fprintf(stderr, "Finished recording with signal %d\n", signum);
    exit(0);
  } else {
    fprintf(stderr, "Finished recording\n");
    exit(0);
  }
 =20
}

#ifdef USE_AIFF
/* handles interrupts from aiff routines */
void stopRec(int signum) {

  stopRecording(sndFile, &aiffSnd);
 =20
  fprintf(stderr, "\nWrote %d frames with %d bytes of raw sound data\n",
          aiffSnd.comm.numSampleFrames,
          aiffSnd.ssnd.ckDataSize);

  writeAIFFSound(sndFile, &aiffSnd);
  quit(signum);
 =20
}
#endif

/**
 * Initialises the DSP device
 *=20
 * Returns the fd of the open call
 **/
int initDSP(dsp_parameters *params ) {

  int fd =3D open(params->device, O_RDONLY);
   =20
  if (fd < 0) err(1,"can't open DSP device %s", params->device);
 =20
  if (ioctl(fd, SOUND_PCM_READ_BITS, &params->r_size))
    err(1, "ioctl for read sample size failed");
  if (ioctl(fd, SOUND_PCM_WRITE_BITS, &params->w_size))
    err(1, "ioctl for write sample size failed");
  if (ioctl(fd, SOUND_PCM_READ_CHANNELS, &params->r_channels))
    err(1, "ioctl for read channels failed");
  if (ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &params->w_channels))
    err(1, "ioctl for write channels failed");
  if (ioctl(fd, SOUND_PCM_READ_RATE, &params->r_rate))
    err(1, "ioctl for read sample rate failed");
  if (ioctl(fd, SOUND_PCM_WRITE_RATE, &params->w_rate))
    err(1, "ioctl for write sample rate failed");

  return fd;

} /* end initDSP() */

/* a basic usage */
void usage(char* argvo) {
  fprintf(stderr,
          "\
usage: %s [-r rate] [-c channels] [-s size | -b | -w]
       [-h] [-d dev] [-t time | -f frames] file.[raw|aiff]\n", argvo);
} /* end usage() */

/* more elaborate help */
void help(char* argvo) {
  usage(argvo);
  fprintf(stderr, "
where: (defaults)
-g size: buffer size to use (%d bytes)
-d device: DSP device to use (%s)
-r rate: sets sample rate to rate (%d Hz)
-c channels: number of channels to use (%d)
-s size: sample size in bits (%d bits)
-f samples: number of samples to record (0, \"unlimited\")
-t time: maximum recording time (0, \"unlimited\")
-b: use 8 bits samples, same as '-s 8'
-w: use 16 bits samples, same as '-s 16'\n"
#ifdef USE_AIFF
          "-a: force AIFF output
-p: force RAW PCM output"
#endif
          "-h: gives this help

Records a sound file"
#ifdef USE_AIFF
          " in the AIFF format if the filename ends with .aiff
or .aif or if the flag -i is specified, or "
#endif
          "in a RAW PCM format (signed "
#ifdef USE_AIFF
"\n"
#endif
"linear 2's complement, "
#ifndef USE_AIFF
"\n"
#endif
"little endian)"
#ifdef USE_AIFF
          " otherwise"
#endif
          ".

If time or a number of samples is specified, the recording will not be
longer than that (in seconds or frames), if not, rec will stop only for
a write failure or interruption (SIGINT/SIGHUP).

When conflicting flags (b, w, s, and f, time) are specified, the latter
overrides the former.\n\n",=20
          BUFSIZ, DFL_DEV, DFL_RATE, DFL_CHAN, DFL_SIZE);
} /* end help */

/* main */
int main(int argc, char *argv[]) {

  int toread =3D -1;              /* what's left to read */
#ifdef USE_AIFF
  short aiffFormat =3D -1;        /* boolean */
#endif
  int bufsize =3D BUFSIZ;
 =20
  dsp_parameters params;        /* how to write it */
=20
  int tmp;
 =20
  /* setting defaults */
  params.device =3D DFL_DEV;
  params.r_rate =3D DFL_RATE;
  params.w_rate =3D DFL_RATE;
  params.r_channels =3D DFL_CHAN;
  params.w_channels =3D DFL_CHAN;
  params.r_size =3D DFL_SIZE;
  params.w_size =3D DFL_SIZE;

  /*********************************************************************
   * Command line parsing
   ********************************************************************/
  {                             /* parsing of the options */
    char ch;                    /* used by getopt */
    char *endptr =3D 0;
   =20
    while ((ch =3D getopt(argc, argv, "t:f:d:r:c:s:g:bw"
#ifdef USE_AIFF
                        "ap"
#endif
                        "h?")) !=3D -1) {
      switch (ch) {
      case 'g':                 /* buffer size */
        tmp =3D strtol(optarg, &endptr, 0);
        if (*endptr) {          /* oups, did not stop at the end */
          fprintf (stderr, "invalid bufsize spec: %s\n", optarg);
          exit(1);
        } else if (!*optarg) {
          fprintf (stderr, "empty bufsize spec\n");
          exit(1);
        }
       =20
        if (tmp >=3D 0)=20
          bufsize =3D tmp;
        else {
          fprintf (stderr,=20
                   "negative sample count specification: %d\n",=20
                   tmp);
          exit(1);
        }

        break;
      case 'd':                 /* sound device */
        params.device =3D optarg;
        break;
      case 'r':                 /* sample rate */
        tmp =3D atoi(optarg);
        if (tmp > 0) params.r_rate =3D tmp;
        else fprintf(stderr,
                     "invalid sample rate spec: %s\n", optarg);
        break;
      case 'c':                 /* channel count */
        tmp =3D atoi(optarg);
        if (tmp > 0) params.r_channels =3D tmp;
        else fprintf(stderr,
                     "invalid channel count spec: %s\n", optarg);
        break;
      case 's':                 /* sample size (8 or 16) */
        tmp =3D atoi(optarg);
        if (tmp > 0) {
          if (tmp !=3D 8 && tmp !=3D 16)
            errx(1, "unsupported sampling size: %d, should be 8 or 16", tmp=
);
          params.r_size =3D tmp;
        } else fprintf(stderr,
                       "invalid sample size spec: %s\n", optarg);
        break;
      case 'f':                 /* frame count */
        tmp =3D strtol(optarg, &endptr, 0);
        if (*endptr) {          /* oups, did not stop at the end */
          fprintf (stderr, "invalid frame spec: %s\n", optarg);
          exit(1);
        } else if (!*optarg) {
          fprintf (stderr, "empty frame spec\n");
          exit(1);
        }
       =20
        if (tmp >=3D 0)=20
          toread =3D BYTES_FROM_FRAMES
            (tmp, params.r_size, params.r_channels);
        else {
          fprintf (stderr,=20
                   "negative sample count specification: %d\n",=20
                   tmp);
          exit(1);
        }
        assert (toread >=3D 0);
        break;
      case 't':                 /* time count */
        toread =3D strtol(optarg, &endptr, 0);
        if (*endptr) {          /* oups, did not stop at the end */
          fprintf (stderr, "invalid time spec: %s\n", optarg);
          exit(1);
        } else if (!*optarg) {
          fprintf (stderr, "empty time spec\n");
          exit(1);
        }
        if (toread >=3D 0)
          toread =3D BYTES_FROM_TIME(toread, params.r_rate,=20
                                   params.r_channels, params.r_size);
        else {
          fprintf(stderr, "negative time specification: %d\n", toread);
          exit(1);
        }
        assert (toread >=3D 0);
        break;
#ifdef USE_AIFF
      case 'a':                 /* force aiff output */
        aiffFormat =3D 1;
        break;
      case 'p':                 /* force pcm raw output */
        aiffFormat =3D 0;
        break;
#endif
      case 'b':                 /* byte samples (8 bits) */
        params.r_size =3D 8;
        break;
      case 'w':                 /* long samples (16 bits) */
        params.r_size =3D 16;
        break;
      case 'h':                 /* long help */
        help(argv[0]);
        exit(1);
        break;
      case '?':                 /* usage */
      default:                  /* error */
        usage(argv[0]);
        exit(1);
        break;
      }
    }
  } /* end arg parsing */

 =20
  argc -=3D optind;
  argv +=3D optind;

  if (argc < 1)                 /* examine filename */
    errx(1, "No filename given, aborting");
  else {
#ifdef USE_AIFF
    int len =3D strlen(argv[0]);
    if (len > 3) {
      if (!strncmp (&argv[0][len-4], ".aif", 4))
        aiffFormat =3D 1;
      else if (len > 4 && !strncmp (&argv[0][len-5], ".aiff", 5))
        aiffFormat =3D 1;
      else {
        if (strncmp (&argv[0][len-4], ".raw", 4))
          fprintf(stderr, "Unknown extension, using raw\n");
        aiffFormat =3D 0;
      }
    } else {
      fprintf(stderr, "No extension given, using raw\n");
      aiffFormat =3D 0;
    }
#endif

    if (!strcmp (argv[0], "-")) { /* file is stdout */
      sndFile =3D STDOUT_FILENO;
    } else {
      sndFile =3D open(argv[0], O_WRONLY | O_CREAT | O_TRUNC, 0644);
      if (sndFile < 0)
        err(1, "can't open output file %s", argv[0]);
    }
  }
 =20
  /* here we should have at least the filename */
  assert(argc >=3D 1);
 =20
  /*********************************************************************
   * Examine Time
   ********************************************************************/
  if (toread <=3D 0) {            /* no time given */
#ifdef USE_AIFF
    /* here we should check for freespace in case of PCM records */
    if (aiffFormat) {
      toread =3D MAX_BYTES;
      fprintf(stderr, "Recording until INT (control-c) or %li seconds.\n",
              MAX_TIME(params.r_size, params.r_channels, params.r_rate));
    } else {                    /* pcm recording */
#endif
      toread =3D 0;               /* this should be get_freespace(path) */
      fprintf(stderr, "Recording until INT (control-c).\n");
#ifdef USE_AIFF
    }
#endif
  } else
    fprintf(stderr,
            "Recording %d seconds (%d frames), send INT (control-c) to stop=
\n",
            TIME_FROM_BYTES(toread, params.r_size,
                            params.r_channels, params.r_rate),
            FRAMES_FROM_BYTES(toread, params.r_size, params.r_channels));
  /* (toread / (params.r_size/8)) / params.r_channels) */;
 =20
  snddev =3D initDSP(&params);    /* initialize DSP */
#ifdef USE_AIFF
  aiffSnd.ssnd.fd =3D snddev;
#endif

  /*********************************************************************
   * Print recording stats
   ********************************************************************/
  fprintf(stderr, "\
             read       write      units
DSP device : %-10s %1$-10s
Rate       : %-10d %-10d Hz
Channels   : %-10d %-10d
Size       : %-10d %-10d bits

Output format: ", params.device,
          params.r_rate, params.w_rate,
          params.r_channels, params.w_channels,
          params.r_size, params.w_size);

#ifdef USE_AIFF
  if (aiffFormat) fprintf(stderr, "AIFF\n");
  else
#endif
    fprintf(stderr, "PCM signed linear 2's complement\n");

#ifdef USE_AIFF =20
  if (aiffFormat) {
   =20
    signal(SIGINT, stopRec);    /* handle signals smoothly */
    signal(SIGHUP, stopRec);

    aiffSnd.comm.numChannels =3D params.w_channels;
    aiffSnd.comm.sampleSize =3D params.w_size;
    doubleToIEEEExtended((double)params.w_rate, aiffSnd.comm.sampleRate);
    aiffSnd.ssnd.ckDataSize =3D toread + 8;
    updateSizeFields(&aiffSnd);

#ifndef NDEBUG
    assert(!gettimeofday(&start, NULL));
#endif
    if (writeAIFFSound(sndFile, &aiffSnd) < 0)
      warn("error in writeAIFFSound");

    stopRec(0);
   =20
  } else                        /* RAW recording */
#endif
    {
      int readcount, time, eta;
      const int origToread =3D toread;
      int never_stop =3D 0;
      char *buffer =3D (char*) malloc(bufsize);
      if (!buffer) {
        perror ("can't allocate memory for read buffer");
        exit(1);
      }
   =20
      if (toread <=3D 0) {
        never_stop =3D 1;
        toread =3D bufsize;
      }

      signal( SIGINT, quit );
      signal( SIGHUP, quit );
 =20
#ifndef NDEBUG
      assert(!gettimeofday(&start, NULL));
#endif
   =20
      while (never_stop || toread > 0) {
        readcount =3D bufsize;
        if (readcount > toread)
          readcount =3D toread;
        readcount =3D read(snddev, buffer, readcount);
        if (readcount < 0) {
          perror("dspread");
          exit(1);
        }
        if (write(sndFile, buffer, readcount) < 0) {
          perror("failed to write to file");
          exit(1);
        }
        toread -=3D readcount;
     =20
        eta =3D TIME_FROM_BYTES(toread, params.w_size,
                              params.w_channels, params.w_rate);
        time =3D TIME_FROM_BYTES((origToread - toread), params.w_size,
                               params.w_channels, params.w_rate);
        fprintf(stderr, "\r%10d of %10d bytes read, %d:%02d:%02d / ETA %d:%=
02d:%02d",
                origToread - toread, origToread,
                time/360, (time%360)/60, time % 60,=20
                eta/360, (eta%360) / 60, eta % 60);
      }
      quit(0);
    }
  return 0;                     /* not reached */
} /* end main() */

--5G06lTa6Jq83wMTw--

--ZJcv+A0YCCLh2VIg
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (FreeBSD)
Comment: For info see http://www.gnupg.org

iEYEARECAAYFAjt65mEACgkQttcWHAnWiGdKnQCdF33Ry8d8X9rwklMkxTKlN4XW
+3IAn2hdk7BBX/bGylIGt3FPuDgZkoqU
=iepB
-----END PGP SIGNATURE-----

--ZJcv+A0YCCLh2VIg--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-multimedia" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010815171514.B471>