~ubuntu-branches/ubuntu/wily/oss4/wily

« back to all changes in this revision

Viewing changes to cmd/ossplay/ossplay.c

  • Committer: Bazaar Package Importer
  • Author(s): Romain Beauxis, Samuel Thibault, Romain Beauxis, Sebastien NOEL
  • Date: 2011-06-14 10:06:56 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110614100656-cx4oc7u426zn812z
Tags: 4.2-build2004-1
[ Samuel Thibault ]
* debian/control: Add liboss4-salsa2, liboss4-salsa-dev and
  liboss4-salsa-asound2 packages, equivalent to (and will replace) those from
  the oss-libsalsa package (Closes: #589127).
* debian/patches/liboss4-salsa.patch: New patch to rename libsalsa into
  liboss4-salsa to avoid conflicts in the archive for no good reason.
* debian/rules: Make in libOSSlib and libsalsa.
* debian/liboss4-salsa-dev.install, debian/liboss4-salsa2.install,
  debian/liboss4-salsa-asound2.links, debian/liboss4-salsa-dev.links:
  Install liboss4-salsa libraries like was done in the oss-libsalsa package.
* include-alsa: Add a copy of ALSA 1.0.5 headers: Cf ALSA_1.0.* symbols in
  libsalsa, this is the roughly supported version.
* debian/copyright: Update for new include-alsa files.
* alsa.pc: New file for compatibility with libasound-dev.
* debian/control:
  - Add Vcs-Browser and Vcs-Svn fields.
  - Use linux-any instead of the list of Linux archs (Closes: #604679).
  - Make dkms dependency linux-any only.
* debian/patches/hurd_iot.patch: New patch to fix soundcard.h usage in
  libsalsa on hurd-i386.
* debian/patches/libsalsa_fixes.patch: New patch to fix some printf usages
  and ioctl declaration in libsalsa.
* debian/patches/no_EBADE.patch: New patch to cope with hurd-i386 not having
  EBADE.
* debian/patches/CFLAGS.patch: New patch to make oss4 take debian/rules
  CFLAGS into account.
* debian/patches/snd_asoundlib_version.patch: New patch to add
  snd_asoundlib_version().
* debian/patches/generic_srccconf.patch: New patch to fix source
  configuration on unknown archs.

[ Romain Beauxis ]
* Fixed README.Debian to only mention dkms' modules.
* Switch to dpkg-source 3.0 (quilt) format
* Added DM-Upload-Allowed: yes

[ Sebastien NOEL ]
* New upstream release (Closes: #595298, #619272).
* Fix typo in initscript (Closes: #627149).
* debian/control: adjust linux-headers dependencies (Closes: #628879).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Purpose: Sources for the ossplay audio player and for the ossrecord
 
3
 *          audio recorder shipped with OSS.
 
4
 *
 
5
 * Description:
 
6
 * OSSPlay is a audio file player that supports most commonly used uncompressed
 
7
 * audio formats (.wav, .snd, .au, .aiff). It doesn't play compressed formats
 
8
 * such as MP3.
 
9
 * OSSRecord is a simple file recorder. It can write simple file formats
 
10
 * (.wav, .au, .aiff).
 
11
 *
 
12
 * This file contains the audio backend and misc. functions.
 
13
 *
 
14
 * This program is bit old and it uses some OSS features that may no longer be
 
15
 * required.
 
16
 */
 
17
/*
 
18
 *
 
19
 * This file is part of Open Sound System.
 
20
 *
 
21
 * Copyright (C) 4Front Technologies 1996-2008.
 
22
 *
 
23
 * This this source file is released under GPL v2 license (no other versions).
 
24
 * See the COPYING file included in the main directory of this source
 
25
 * distribution for the license terms and conditions.
 
26
 *
 
27
 */
 
28
 
 
29
#include "ossplay_decode.h"
 
30
#include "ossplay_parser.h"
 
31
#include "ossplay_wparser.h"
 
32
 
 
33
#include <signal.h>
 
34
#include <strings.h>
 
35
#include <unistd.h>
 
36
 
 
37
unsigned int amplification = 100;
 
38
int eflag = 0, force_speed = 0, force_fmt = 0, force_channels = 0,
 
39
    overwrite = 1, verbose = 0, quiet = 0;
 
40
flag from_stdin = 0, int_conv = 0, level_meters = 0, loop = 0, 
 
41
     raw_file = 0, raw_mode = 0;
 
42
double seek_time = 0;
 
43
long seek_byte = 0;
 
44
off_t (*ossplay_lseek) (int, off_t, int) = lseek;
 
45
 
 
46
char script[512] = "";
 
47
unsigned int nfiles = 1;
 
48
big_t datalimit = 0;
 
49
fctypes_t type = WAVE_FILE;
 
50
 
 
51
const format_t format_a[] = {
 
52
  {"S8",                AFMT_S8,                CRP,            AFMT_S16_NE},
 
53
  {"U8",                AFMT_U8,                CRP,            AFMT_S16_NE},
 
54
  {"S16_LE",            AFMT_S16_LE,            CRP,            AFMT_S16_NE},
 
55
  {"S16_BE",            AFMT_S16_BE,            CRP,            AFMT_S16_NE},
 
56
  {"U16_LE",            AFMT_U16_LE,            CRP,            AFMT_S16_NE},
 
57
  {"U16_BE",            AFMT_U16_BE,            CRP,            AFMT_S16_NE},
 
58
  {"S24_LE",            AFMT_S24_LE,            CRP,            0},
 
59
  {"S24_BE",            AFMT_S24_BE,            CRP,            0},
 
60
  {"S32_LE",            AFMT_S32_LE,            CRP,            AFMT_S32_NE},
 
61
  {"S32_BE",            AFMT_S32_BE,            CRP,            AFMT_S32_NE},
 
62
  {"A_LAW",             AFMT_A_LAW,             CRP,            AFMT_S16_NE},
 
63
  {"MU_LAW",            AFMT_MU_LAW,            CRP,            AFMT_S16_NE},
 
64
  {"FLOAT32_LE",        AFMT_FLOAT32_LE,        CP,             0},
 
65
  {"FLOAT32_BE",        AFMT_FLOAT32_BE,        CP,             0},
 
66
  {"DOUBLE64_LE",       AFMT_DOUBLE64_LE,       CP,             0},
 
67
  {"DOUBLE64_BE",       AFMT_DOUBLE64_BE,       CP,             0},
 
68
  {"S24_PACKED",        AFMT_S24_PACKED,        CRP,            0},
 
69
  {"S24_PACKED_BE",     AFMT_S24_PACKED_BE,     CP,             0},
 
70
  {"IMA_ADPCM",         AFMT_IMA_ADPCM,         CP,             0},
 
71
  {"IMA_ADPCM_3BITS",   AFMT_MS_IMA_ADPCM_3BITS,CP,             0},
 
72
  {"MS_ADPCM",          AFMT_MS_ADPCM,          CP,             0},
 
73
  {"CR_ADPCM_2",        AFMT_CR_ADPCM_2,        CP,             0},
 
74
  {"CR_ADPCM_3",        AFMT_CR_ADPCM_3,        CP,             0},
 
75
  {"CR_ADPCM_4",        AFMT_CR_ADPCM_4,        CP,             0},
 
76
  {"SPDIF_RAW",         AFMT_SPDIF_RAW,         CR,             0},
 
77
  {"FIBO_DELTA",        AFMT_FIBO_DELTA,        CP,             0},
 
78
  {"EXP_DELTA",         AFMT_EXP_DELTA,         CP,             0},
 
79
  {NULL,                0,                      CP,             0}
 
80
};
 
81
 
 
82
static const container_t container_a[] = {
 
83
  {"RAW",               RAW_FILE,       AFMT_S16_LE,    2,      44100},
 
84
  {"WAV",               WAVE_FILE,      AFMT_S16_LE,    2,      48000},
 
85
  {"AU",                AU_FILE,        AFMT_MU_LAW,    1,      8000},
 
86
  {"AIFF",              AIFF_FILE,      AFMT_S16_BE,    2,      48000},
 
87
  {"CAF",               CAF_FILE,       AFMT_S16_NE,    2,      48000},
 
88
  {NULL,                RAW_FILE,       0,              0,      0}
 
89
}; /* Order should match fctypes_t enum so that container_a[type] works */
 
90
 
 
91
static void describe_error (void);
 
92
static void find_devname (char *, const char *);
 
93
static fctypes_t select_container (const char *);
 
94
static int select_format (const char *, int);
 
95
static void ossplay_usage (const char *);
 
96
static void ossrecord_usage (const char *);
 
97
static void ossplay_getint (int);
 
98
static void print_play_verbose_info (const unsigned char *, ssize_t, void *);
 
99
static void print_record_verbose_info (const unsigned char *, ssize_t, void *);
 
100
 
 
101
big_t
 
102
be_int (const unsigned char * p, int l)
 
103
{
 
104
  int i;
 
105
  big_t val;
 
106
 
 
107
  val = 0;
 
108
 
 
109
  for (i = 0; i < l; i++)
 
110
    {
 
111
      val = (val << 8) | p[i];
 
112
    }
 
113
 
 
114
  return val;
 
115
}
 
116
 
 
117
big_t
 
118
le_int (const unsigned char * p, int l)
 
119
{
 
120
  int i;
 
121
  big_t val;
 
122
 
 
123
  val = 0;
 
124
 
 
125
  for (i = l - 1; i >= 0; i--)
 
126
    {
 
127
      val = (val << 8) | p[i];
 
128
    }
 
129
 
 
130
  return val;
 
131
}
 
132
 
 
133
static void
 
134
describe_error (void)
 
135
{
 
136
  switch (errno)
 
137
    {
 
138
    case ENXIO:
 
139
    case ENODEV:
 
140
      print_msg (ERRORM, "\nThe device file was found in /dev but\n"
 
141
                 "there is no driver for it currently loaded.\n"
 
142
                 "\n"
 
143
                 "You can start it by executing the soundon command as\n"
 
144
                 "super user (root).\n");
 
145
      break;
 
146
 
 
147
    case ENOSPC:
 
148
      print_msg (ERRORM, "\nThe soundcard driver was not installed\n"
 
149
                 "properly. The system is out of DMA compatible memory.\n"
 
150
                 "Please reboot your system and try again.\n");
 
151
 
 
152
      break;
 
153
 
 
154
    case ENOENT:
 
155
      print_msg (ERRORM, "\nThe sound device file is missing from /dev.\n"
 
156
                 "You should try re-installing OSS.\n");
 
157
      break;
 
158
 
 
159
    case EBUSY:
 
160
      print_msg (ERRORM,
 
161
                 "\nThere is some other application using this audio device.\n"
 
162
                 "Exit it and try again.\n");
 
163
      print_msg (ERRORM,
 
164
                 "You can possibly find out the conflicting application by"
 
165
                 "looking\n",
 
166
                 "at the printout produced by command 'ossinfo -a -v1'\n");
 
167
      break;
 
168
 
 
169
    default:;
 
170
    }
 
171
}
 
172
 
 
173
static void
 
174
find_devname (char * devname, const char * num)
 
175
{
 
176
/*
 
177
 * OSS 4.0 the audio device numbering may be different from the
 
178
 * legacy /dev/dsp# numbering reported by /dev/sndstat. Try to find the
 
179
 * device name (devnode) that matches the given device number.
 
180
 *
 
181
 * Prior versions of ossplay simply used the the /dev/dsp# number.
 
182
 */
 
183
  int dev;
 
184
  int mixer_fd;
 
185
  oss_audioinfo ai;
 
186
  const char * devmixer;
 
187
 
 
188
  if ((devmixer = getenv("OSS_MIXERDEV")) == NULL)
 
189
     devmixer = "/dev/mixer";
 
190
 
 
191
  if (sscanf (num, "%d", &dev) != 1)
 
192
    {
 
193
      print_msg (ERRORM, "Invalid audio device number '%s'\n", num);
 
194
      exit (E_SETUP_ERROR);
 
195
    }
 
196
 
 
197
  if ((mixer_fd = open (devmixer, O_RDWR, 0)) == -1)
 
198
    {
 
199
      perror_msg (devmixer);
 
200
      print_msg (WARNM, "Warning: Defaulting to /dev/dsp%s\n", num);
 
201
      snprintf (devname, OSS_DEVNODE_SIZE, "/dev/dsp%s", num);
 
202
      return;
 
203
    }
 
204
 
 
205
  ai.dev = dev;
 
206
 
 
207
  if (ioctl (mixer_fd, SNDCTL_AUDIOINFO, &ai) == -1)
 
208
    {
 
209
      perror_msg ("SNDCTL_AUDIOINFO");
 
210
      print_msg (WARNM, "Warning: Defaulting to /dev/dsp%s\n", num);
 
211
      snprintf (devname, OSS_DEVNODE_SIZE, "/dev/dsp%s", num);
 
212
      close (mixer_fd);
 
213
      return;
 
214
    }
 
215
 
 
216
  strncpy (devname, ai.devnode, OSS_DEVNODE_SIZE);
 
217
 
 
218
  close (mixer_fd);
 
219
  return;
 
220
}
 
221
 
 
222
const char *
 
223
filepart (const char *name)
 
224
{
 
225
  const char * s = name;
 
226
 
 
227
  if (name == NULL) return "";
 
228
 
 
229
  while (*name)
 
230
    {
 
231
      if (name[0] == '/' && name[1] != '\0')
 
232
        s = name + 1;
 
233
      name++;
 
234
    }
 
235
 
 
236
  return s;
 
237
}
 
238
 
 
239
float
 
240
format2bits (int format)
 
241
{
 
242
  switch (format)
 
243
    {
 
244
      case AFMT_CR_ADPCM_2: return 2;
 
245
      case AFMT_CR_ADPCM_3: return 2.6666F;
 
246
      case AFMT_MS_IMA_ADPCM_3BITS: return 3;
 
247
      case AFMT_CR_ADPCM_4:
 
248
      case AFMT_MAC_IMA_ADPCM:
 
249
      case AFMT_MS_IMA_ADPCM:
 
250
      case AFMT_IMA_ADPCM:
 
251
      case AFMT_MS_ADPCM:
 
252
      case AFMT_FIBO_DELTA:
 
253
      case AFMT_EXP_DELTA: return 4;
 
254
      case AFMT_MU_LAW:
 
255
      case AFMT_A_LAW:
 
256
      case AFMT_U8:
 
257
      case AFMT_S8: return 8;
 
258
      case AFMT_VORBIS:
 
259
      case AFMT_MPEG:
 
260
      case AFMT_S16_LE:
 
261
      case AFMT_S16_BE:
 
262
      case AFMT_U16_LE:
 
263
      case AFMT_U16_BE: return 16;
 
264
      case AFMT_S24_PACKED:
 
265
      case AFMT_S24_PACKED_BE: return 24;
 
266
      case AFMT_S24_LE:
 
267
      case AFMT_S24_BE:
 
268
      case AFMT_SPDIF_RAW:
 
269
      case AFMT_FLOAT32_LE:
 
270
      case AFMT_FLOAT32_BE:
 
271
      case AFMT_S32_LE:
 
272
      case AFMT_S32_BE: return 32;
 
273
      case AFMT_DOUBLE64_LE:
 
274
      case AFMT_DOUBLE64_BE: return 64;
 
275
      case AFMT_FLOAT: return sizeof (float) * 8;
 
276
      case AFMT_QUERY:
 
277
      default: return 0;
 
278
   }
 
279
}
 
280
 
 
281
void
 
282
close_device (dspdev_t * dsp)
 
283
{
 
284
  if (dsp->fd == -1) return;
 
285
  close (dsp->fd);
 
286
  dsp->fd = -1;
 
287
}
 
288
 
 
289
void
 
290
open_device (dspdev_t * dsp)
 
291
{
 
292
  const char * devdsp;
 
293
 
 
294
  if (dsp->fd >= 0)
 
295
     close_device (dsp);
 
296
 
 
297
  dsp->format = 0; dsp->channels = 0; dsp->speed = 0;
 
298
 
 
299
  if ((devdsp = getenv("OSS_AUDIODEV")) == NULL)
 
300
     devdsp = "/dev/dsp";
 
301
 
 
302
  if (raw_mode)
 
303
    dsp->flags |= O_EXCL;       /* Disable redirection to the virtual mixer */
 
304
 
 
305
  if (dsp->dname[0] == '\0') strcpy (dsp->dname, devdsp);
 
306
 
 
307
  if ((dsp->fd = open (dsp->dname, dsp->flags, 0)) == -1)
 
308
    {
 
309
      perror_msg (dsp->dname);
 
310
      describe_error ();
 
311
      exit (E_SETUP_ERROR);
 
312
    }
 
313
 
 
314
  if (raw_mode)
 
315
    {
 
316
      /*
 
317
       * Disable sample rate/format conversions.
 
318
       */
 
319
      int tmp = 0;
 
320
      ioctl (dsp->fd, SNDCTL_DSP_COOKEDMODE, &tmp);
 
321
    }
 
322
}
 
323
 
 
324
static void
 
325
ossplay_usage (const char * prog)
 
326
{
 
327
  print_msg (HELPM, "Usage: %s [options] filename(s)\n", prog?prog:"ossplay");
 
328
  print_msg (HELPM, "  Options:  -v             Verbose output.\n");
 
329
  print_msg (HELPM, "            -q             No informative printouts.\n");
 
330
  print_msg (HELPM, "            -d<devname>    Change output device.\n");
 
331
  print_msg (HELPM, "            -g<gain>       Change gain.\n");
 
332
  print_msg (HELPM, "            -s<rate>       Change playback rate.\n");
 
333
  print_msg (HELPM, "            -f<fmt>|?      Change/Query input format.\n");
 
334
  print_msg (HELPM, "            -c<channels>   Change number of channels.\n");
 
335
  print_msg (HELPM, "            -o<playtgt>|?  Select/Query output target.\n");
 
336
  print_msg (HELPM, "            -l             Loop playback indefinitely.\n");
 
337
  print_msg (HELPM, "            -W             Treat all input as raw PCM.\n");
 
338
  print_msg (HELPM, "            -S<secs>       Start playing from offset.\n");
 
339
  print_msg (HELPM,
 
340
             "            -R             Open sound device in raw mode.\n");
 
341
  exit (E_USAGE);
 
342
}
 
343
 
 
344
static void
 
345
ossrecord_usage (const char * prog)
 
346
{
 
347
  print_msg (HELPM, "Usage: %s [options] filename\n", prog?prog:"ossrecord");
 
348
  print_msg (HELPM, "  Options:  -v             Verbose output.\n");
 
349
  print_msg (HELPM, "            -d<device>     Change input device.\n");
 
350
  print_msg (HELPM, "            -c<channels>   Change number of channels\n");
 
351
  print_msg (HELPM, "            -L<level>      Change recording level.\n");
 
352
  print_msg (HELPM,
 
353
             "            -g<gain>       Change gain percentage.\n");
 
354
  print_msg (HELPM, "            -s<rate>       Change recording rate.\n");
 
355
  print_msg (HELPM, "            -f<fmt|?>      Change/Query sample format.\n");
 
356
  print_msg (HELPM,
 
357
             "            -F<cnt|?>      Change/Query container format.\n");
 
358
  print_msg (HELPM, "            -l             Display level meters.\n");
 
359
  print_msg (HELPM,
 
360
             "            -i<recsrc|?>   Select/Query recording source.\n");
 
361
  print_msg (HELPM,
 
362
             "            -m<nfiles>     Repeat recording <nfiles> times.\n");
 
363
  print_msg (HELPM,
 
364
             "            -r<command>    Run <command> after recording.\n");
 
365
  print_msg (HELPM,
 
366
             "            -t<maxsecs>    Record no more than <maxsecs> in a"
 
367
             " single recording.\n");
 
368
  print_msg (HELPM,
 
369
             "            -R             Open sound device in raw mode.\n");
 
370
  print_msg (HELPM, "            -O             Do not allow overwrite.\n");
 
371
  exit (E_USAGE);
 
372
}
 
373
 
 
374
const char *
 
375
sample_format_name (int sformat)
 
376
{
 
377
  int i;
 
378
 
 
379
  for (i = 0; format_a[i].fmt != 0; i++)
 
380
    if (format_a[i].fmt == sformat)
 
381
      return format_a[i].name;
 
382
 
 
383
  return "";
 
384
}
 
385
 
 
386
static fctypes_t
 
387
select_container (const char * optstr)
 
388
{
 
389
/*
 
390
 * Handling of the -F command line option (force container format).
 
391
 *
 
392
 * Empty or "?" shows the supported container format names.
 
393
 */
 
394
  int i;
 
395
 
 
396
  if ((!strcmp(optstr, "?")) || (*optstr == '\0'))
 
397
    {
 
398
      print_msg (STARTM, "\nSupported container format names are:\n\n");
 
399
      for (i = 0; container_a[i].name != NULL; i++)
 
400
        print_msg (CONTM, "%s ", container_a[i].name);
 
401
      print_msg (ENDM, "\n");
 
402
      exit (0);
 
403
    }
 
404
 
 
405
  for (i = 0; container_a[i].name != NULL; i++)
 
406
    if (!strcasecmp(container_a[i].name, optstr))
 
407
      return container_a[i].type;
 
408
 
 
409
  print_msg (ERRORM, "Unsupported container format name '%s'!\n", optstr);
 
410
  exit (E_USAGE);
 
411
}
 
412
 
 
413
static int
 
414
select_format (const char * optstr, int dir)
 
415
{
 
416
/*
 
417
 * Handling of the -f command line option (force input format).
 
418
 *
 
419
 * Empty or "?" shows the supported format names.
 
420
 */
 
421
  int i;
 
422
 
 
423
  if ((!strcmp(optstr, "?")) || (*optstr == '\0'))
 
424
    {
 
425
      print_msg (STARTM, "\nSupported format names are:\n\n");
 
426
      for (i = 0; format_a[i].name != NULL; i++)
 
427
        if (dir & format_a[i].dir)
 
428
          print_msg (CONTM, "%s ", format_a[i].name);
 
429
      print_msg (ENDM, "\n");
 
430
      exit (0);
 
431
    }
 
432
 
 
433
  for (i = 0; format_a[i].name != NULL; i++)
 
434
    if ((format_a[i].dir & dir) && (!strcasecmp(format_a[i].name, optstr)))
 
435
      return format_a[i].fmt;
 
436
 
 
437
  print_msg (ERRORM, "Unsupported format name '%s'!\n", optstr);
 
438
  exit (E_USAGE);
 
439
}
 
440
 
 
441
void
 
442
select_playtgt (dspdev_t * dsp)
 
443
{
 
444
/*
 
445
 * Handling of the -o command line option (playback target selection).
 
446
 *
 
447
 * Empty or "?" shows the available playback sources.
 
448
 */
 
449
  int i, src;
 
450
  oss_mixer_enuminfo ei;
 
451
 
 
452
  if (ioctl (dsp->fd, SNDCTL_DSP_GET_PLAYTGT_NAMES, &ei) == -1)
 
453
    {
 
454
      perror_msg ("SNDCTL_DSP_GET_PLAYTGT_NAMES");
 
455
      exit (E_SETUP_ERROR);
 
456
    }
 
457
 
 
458
  if (ioctl (dsp->fd, SNDCTL_DSP_GET_PLAYTGT, &src) == -1)
 
459
    {
 
460
      perror_msg ("SNDCTL_DSP_GET_PLAYTGT");
 
461
      exit (E_SETUP_ERROR);
 
462
    }
 
463
 
 
464
  if ((dsp->playtgt[0] == '\0') || (strcmp (dsp->playtgt, "?") == 0))
 
465
    {
 
466
      print_msg (STARTM,
 
467
                 "\nPossible playback targets for the selected device:\n\n");
 
468
 
 
469
      for (i = 0; i < ei.nvalues; i++)
 
470
        {
 
471
          print_msg (CONTM, "\t%s", ei.strings + ei.strindex[i]);
 
472
          if (i == src)
 
473
            print_msg (CONTM, " (currently selected)");
 
474
          print_msg (CONTM, "\n");
 
475
        }
 
476
      print_msg (ENDM, "\n");
 
477
      exit (0);
 
478
    }
 
479
 
 
480
  for (i = 0; i < ei.nvalues; i++)
 
481
    {
 
482
      char *s = ei.strings + ei.strindex[i];
 
483
      if (strcmp (s, dsp->playtgt) == 0)
 
484
        {
 
485
          src = i;
 
486
          if (ioctl (dsp->fd, SNDCTL_DSP_SET_PLAYTGT, &src) == -1)
 
487
            {
 
488
              perror_msg ("SNDCTL_DSP_SET_PLAYTGT");
 
489
              exit (E_SETUP_ERROR);
 
490
            }
 
491
 
 
492
          return;
 
493
        }
 
494
    }
 
495
 
 
496
  print_msg (ERRORM,
 
497
             "Unknown playback target name '%s' - use -o? to get the list\n",
 
498
             dsp->playtgt);
 
499
  exit (E_USAGE);
 
500
}
 
501
 
 
502
void
 
503
select_recsrc (dspdev_t * dsp)
 
504
{
 
505
/*
 
506
 * Handling of the -i command line option (recording source selection).
 
507
 *
 
508
 * Empty or "?" shows the available recording sources.
 
509
 */
 
510
  int i, src;
 
511
  oss_mixer_enuminfo ei;
 
512
 
 
513
  if (ioctl (dsp->fd, SNDCTL_DSP_GET_RECSRC_NAMES, &ei) == -1)
 
514
    {
 
515
      perror_msg ("SNDCTL_DSP_GET_RECSRC_NAMES");
 
516
      exit (E_SETUP_ERROR);
 
517
    }
 
518
 
 
519
  if (ioctl (dsp->fd, SNDCTL_DSP_GET_RECSRC, &src) == -1)
 
520
    {
 
521
      perror_msg ("SNDCTL_DSP_GET_RECSRC");
 
522
      exit (E_SETUP_ERROR);
 
523
    }
 
524
 
 
525
  if (dsp->recsrc[0] == '\0' || strcmp (dsp->recsrc, "?") == 0)
 
526
    {
 
527
      print_msg (STARTM,
 
528
                 "\nPossible recording sources for the selected device:\n\n");
 
529
 
 
530
      for (i = 0; i < ei.nvalues; i++)
 
531
        {
 
532
          print_msg (CONTM, "\t%s", ei.strings + ei.strindex[i]);
 
533
          if (i == src)
 
534
            print_msg (CONTM, " (currently selected)");
 
535
          print_msg (CONTM, "\n");
 
536
        }
 
537
      print_msg (ENDM, "\n");
 
538
      exit (0);
 
539
    }
 
540
 
 
541
  for (i = 0; i < ei.nvalues; i++)
 
542
    {
 
543
      char *s = ei.strings + ei.strindex[i];
 
544
      if (strcmp (s, dsp->recsrc) == 0)
 
545
        {
 
546
          src = i;
 
547
          if (ioctl (dsp->fd, SNDCTL_DSP_SET_RECSRC, &src) == -1)
 
548
            {
 
549
              perror_msg ("SNDCTL_DSP_SET_RECSRC");
 
550
              exit (E_SETUP_ERROR);
 
551
            }
 
552
          return;
 
553
        }
 
554
    }
 
555
 
 
556
  print_msg (ERRORM,
 
557
             "Unknown recording source name '%s' - use -i? to get the list\n",
 
558
             dsp->recsrc);
 
559
  exit (E_USAGE);
 
560
}
 
561
 
 
562
errors_t
 
563
setup_device (dspdev_t * dsp, int format, int channels, int speed)
 
564
{
 
565
  int tmp;
 
566
 
 
567
  if (dsp->speed != speed || dsp->format != format ||
 
568
      dsp->channels != channels || dsp->fd == -1)
 
569
    {
 
570
#if 0
 
571
      ioctl (dsp->fd, SNDCTL_DSP_SYNC, NULL);
 
572
      ioctl (dsp->fd, SNDCTL_DSP_HALT, NULL);
 
573
#else
 
574
      close_device (dsp);
 
575
      open_device (dsp);
 
576
      if (dsp->playtgt != NULL) select_playtgt (dsp);
 
577
      if (dsp->recsrc != NULL)  select_recsrc (dsp);
 
578
#endif
 
579
    }
 
580
  else
 
581
    {
 
582
      ioctl (dsp->fd, SNDCTL_SETSONG, dsp->current_songname);
 
583
      return E_OK;
 
584
    }
 
585
 
 
586
  /*
 
587
   * Report the current filename as the song name.
 
588
   */
 
589
  ioctl (dsp->fd, SNDCTL_SETSONG, dsp->current_songname);
 
590
 
 
591
  tmp = APF_NORMAL;
 
592
  ioctl (dsp->fd, SNDCTL_DSP_PROFILE, &tmp);
 
593
 
 
594
  tmp = format;
 
595
 
 
596
  if (ioctl (dsp->fd, SNDCTL_DSP_SETFMT, &tmp) == -1)
 
597
    {
 
598
      perror_msg (dsp->dname);
 
599
      print_msg (ERRORM, "Failed to select bits/sample\n");
 
600
      return E_SETUP_ERROR;
 
601
    }
 
602
 
 
603
  if (tmp != format)
 
604
    {
 
605
      print_msg (ERRORM, "%s doesn't support this audio format (%x/%x).\n",
 
606
                 dsp->dname, format, tmp);
 
607
      return E_FORMAT_UNSUPPORTED;
 
608
    }
 
609
 
 
610
  tmp = channels;
 
611
 
 
612
  if (ioctl (dsp->fd, SNDCTL_DSP_CHANNELS, &tmp) == -1)
 
613
    {
 
614
      perror_msg (dsp->dname);
 
615
      print_msg (ERRORM, "Failed to select number of channels.\n");
 
616
      return E_SETUP_ERROR;
 
617
    }
 
618
 
 
619
  if (tmp != channels)
 
620
    {
 
621
#ifdef SRC_SUPPORT
 
622
      /* We'll convert mono to stereo, so it's no use warning */
 
623
      if ((channels != 1) || (tmp != 2))
 
624
#endif
 
625
        print_msg (ERRORM, "%s doesn't support %d channels (%d).\n",
 
626
                   dsp->dname, channels, tmp);
 
627
      return E_CHANNELS_UNSUPPORTED;
 
628
    }
 
629
 
 
630
  tmp = speed;
 
631
 
 
632
  if (ioctl (dsp->fd, SNDCTL_DSP_SPEED, &tmp) == -1)
 
633
    {
 
634
      perror_msg (dsp->dname);
 
635
      print_msg (ERRORM, "Failed to select sampling rate.\n");
 
636
      return E_SETUP_ERROR;
 
637
    }
 
638
 
 
639
#ifndef SRC_SUPPORT
 
640
  if (tmp != speed)
 
641
    {
 
642
      print_msg (WARNM, "Warning: Playback using %d Hz (file %d Hz)\n",
 
643
                 tmp, speed);
 
644
    }
 
645
#endif
 
646
 
 
647
  dsp->speed = tmp;
 
648
  dsp->channels = channels;
 
649
  dsp->format = format;
 
650
 
 
651
  if (verbose > 1)
 
652
    print_msg (VERBOSEM, "Setup device %s/%d/%d\n",
 
653
               sample_format_name (dsp->format), dsp->channels, dsp->speed);
 
654
 
 
655
  if (dsp->reclevel != 0)
 
656
    {
 
657
      tmp = dsp->reclevel | (dsp->reclevel << 8);
 
658
 
 
659
      if (ioctl (dsp->fd, SNDCTL_DSP_SETRECVOL, &tmp) == -1)
 
660
        perror ("SNDCTL_DSP_SETRECVOL");
 
661
    }
 
662
 
 
663
  return E_OK;
 
664
}
 
665
 
 
666
static void
 
667
ossplay_getint (int signum)
 
668
{
 
669
#if 0
 
670
  if (eflag == signum + 128)
 
671
    {
 
672
      signal (signum, SIG_DFL);
 
673
      kill (getpid(), signum);
 
674
    }
 
675
#endif
 
676
  eflag = signum + 128;
 
677
}
 
678
 
 
679
int
 
680
ossplay_parse_opts (int argc, char ** argv, dspdev_t * dsp)
 
681
{
 
682
  extern char * optarg;
 
683
  extern int optind;
 
684
  char * p;
 
685
  int c;
 
686
 
 
687
  while ((c = getopt (argc, argv, "FRS:Wc:d:f:g:hlo:qs:v")) != EOF)
 
688
    {
 
689
      switch (c)
 
690
        {
 
691
        case 'v':
 
692
          verbose++;
 
693
          quiet = 0;
 
694
          int_conv = 2;
 
695
          break;
 
696
 
 
697
        case 'R':
 
698
          raw_mode = 1;
 
699
          break;
 
700
 
 
701
        case 'q':
 
702
          quiet++;
 
703
          verbose = 0;
 
704
          if (int_conv == 2) int_conv = 0;
 
705
          break;
 
706
 
 
707
        case 'd':
 
708
          if (*optarg >= '0' && *optarg <= '9') /* Only device number given */
 
709
            find_devname (dsp->dname, optarg);
 
710
          else
 
711
            snprintf (dsp->dname, OSS_DEVNODE_SIZE, "%s", optarg);
 
712
          break;
 
713
 
 
714
        case 'o':
 
715
          if (!strcmp(optarg, "?"))
 
716
            {
 
717
              dsp->playtgt = optarg;
 
718
              dsp->flags = O_WRONLY;
 
719
              open_device (dsp);
 
720
              select_playtgt (dsp);
 
721
            }
 
722
          dsp->playtgt = optarg;
 
723
          break;
 
724
 
 
725
        case 'f':
 
726
          force_fmt = select_format (optarg, CP);
 
727
          break;
 
728
 
 
729
        case 's':
 
730
          sscanf (optarg, "%d", &force_speed);
 
731
          break;
 
732
 
 
733
        case 'c':
 
734
          sscanf (optarg, "%d", &force_channels);
 
735
          break;
 
736
 
 
737
        case 'g':
 
738
          sscanf (optarg, "%u", &amplification);
 
739
          int_conv = 1;
 
740
          break;
 
741
 
 
742
        case 'l':
 
743
          loop = 1;
 
744
          break;
 
745
 
 
746
        case 'F':
 
747
        case 'W':
 
748
          raw_file = 1;
 
749
          break;
 
750
 
 
751
        case 'S':
 
752
          c = strlen (optarg);
 
753
          if ((c > 0) && ((optarg[c - 1] == 'b') || (optarg[c - 1] == 'B')))
 
754
            {
 
755
              errno = 0;
 
756
              seek_byte = strtol (optarg, &p, 10);
 
757
              if ((*p != '\0') || (seek_byte < 0)) ossplay_usage (argv[0]);
 
758
            }
 
759
          else
 
760
            {
 
761
              errno = 0;
 
762
              seek_time = strtod (optarg, &p);
 
763
              if ((*p != '\0') || (errno) || (seek_time < 0)) ossplay_usage (argv[0]);
 
764
            }
 
765
          break;
 
766
 
 
767
        default:
 
768
          ossplay_usage (argv[0]);
 
769
        }
 
770
 
 
771
    }
 
772
 
 
773
  if (argc < optind + 1)
 
774
    ossplay_usage (argv[0]);
 
775
 
 
776
#ifdef SIGQUIT
 
777
  signal (SIGQUIT, ossplay_getint);
 
778
#endif
 
779
  return optind;
 
780
}
 
781
 
 
782
int
 
783
ossrecord_parse_opts (int argc, char ** argv, dspdev_t * dsp)
 
784
{
 
785
  int c;
 
786
  extern char * optarg;
 
787
  extern int optind;
 
788
 
 
789
  if (argc < 2)
 
790
    ossrecord_usage (argv[0]);
 
791
 
 
792
  while ((c = getopt (argc, argv, "F:L:MORSb:c:d:f:g:hi:lm:r:s:t:wv")) != EOF)
 
793
    switch (c)
 
794
      {
 
795
        case 'F':
 
796
          type = select_container (optarg);
 
797
          break;
 
798
 
 
799
        case 'L':
 
800
          dsp->reclevel = atoi (optarg);
 
801
          if (dsp->reclevel < 1 || dsp->reclevel > 100)
 
802
            {
 
803
              print_msg (ERRORM, "%s: Bad recording level '%s'\n",
 
804
                         argv[0]?argv[0]:"", optarg);
 
805
              exit (-1);
 
806
            }
 
807
          break;
 
808
 
 
809
        case 'M':
 
810
          force_channels = 1;
 
811
          break;
 
812
 
 
813
        case 'R':
 
814
          raw_mode = 1;
 
815
          break;
 
816
 
 
817
        case 'S':
 
818
          force_channels = 2;
 
819
          break;
 
820
 
 
821
        case 'b':
 
822
          c = atoi (optarg);
 
823
          c += c % 8; /* Simple WAV format always pads to a multiple of 8 */
 
824
          switch (c)
 
825
            {
 
826
              case 8: force_fmt = AFMT_U8; break;
 
827
              case 16: force_fmt = AFMT_S16_LE; break;
 
828
              case 24: force_fmt = AFMT_S24_PACKED; break;
 
829
              case 32: force_fmt = AFMT_S32_LE; break;
 
830
              default:
 
831
                print_msg (ERRORM, "Error: Unsupported number of bits %d\n", c);
 
832
                exit (E_FORMAT_UNSUPPORTED);
 
833
            }
 
834
          break;
 
835
 
 
836
        case 'c':
 
837
          sscanf (optarg, "%d", &force_channels);
 
838
          break;
 
839
 
 
840
        case 'd':
 
841
          if (*optarg >= '0' && *optarg <= '9') /* Only device number given */
 
842
            find_devname (dsp->dname, optarg);
 
843
          else
 
844
            snprintf (dsp->dname, OSS_DEVNODE_SIZE, "%s", optarg);
 
845
          break;
 
846
 
 
847
        case 'f':
 
848
          force_fmt = select_format (optarg, CR);
 
849
          break;
 
850
 
 
851
        case 'g':
 
852
          sscanf (optarg, "%u", &amplification);
 
853
          if (amplification == 0) ossrecord_usage (argv[0]);
 
854
 
 
855
        case 'l':
 
856
          level_meters = 1;
 
857
          verbose = 1;
 
858
          break;
 
859
 
 
860
        case 'i':
 
861
          if (!strcmp(optarg, "?"))
 
862
            {
 
863
              dsp->recsrc = optarg;
 
864
              dsp->flags = O_RDONLY;
 
865
              open_device (dsp);
 
866
              select_recsrc (dsp);
 
867
            }
 
868
          dsp->recsrc = optarg;
 
869
          break;
 
870
 
 
871
        case 'm':
 
872
          sscanf (optarg, "%u", &nfiles);
 
873
          break;
 
874
 
 
875
        case 's':
 
876
          sscanf (optarg, "%d", &force_speed);
 
877
          if (force_speed == 0)
 
878
            {
 
879
              print_msg (ERRORM, "Bad sampling rate given\n");
 
880
              exit (E_USAGE);
 
881
            }
 
882
          if (force_speed < 1000) force_speed *= 1000;
 
883
          break;
 
884
 
 
885
        case 'r':
 
886
          c = snprintf (script, sizeof (script), "%s", optarg);
 
887
          if (((size_t)c >= sizeof (script)) || (c < 0))
 
888
            {
 
889
              print_msg (ERRORM, "-r argument is too long!\n");
 
890
              exit (E_USAGE);
 
891
            }
 
892
          break;
 
893
 
 
894
        case 't':
 
895
          sscanf (optarg, _PRIbig_t, &datalimit);
 
896
          break;
 
897
 
 
898
        case 'O':
 
899
          overwrite = 0;
 
900
          break;
 
901
 
 
902
        case 'w':
 
903
          break;
 
904
 
 
905
        case 'v':
 
906
          verbose = 1;
 
907
          break;
 
908
 
 
909
        case 'h':
 
910
        default:
 
911
          ossrecord_usage (argv[0]);
 
912
      }
 
913
 
 
914
  if (argc != optind + 1)
 
915
  /* No file or multiple file names given */
 
916
      ossrecord_usage (argv[0]);
 
917
 
 
918
  if (force_fmt == 0) force_fmt = container_a[type].dformat;
 
919
  if (force_channels == 0) force_channels = container_a[type].dchannels;
 
920
  if (force_speed == 0) force_speed = container_a[type].dspeed;
 
921
  switch (force_fmt)
 
922
    {
 
923
      case AFMT_S8:
 
924
      case AFMT_U8:
 
925
      case AFMT_S16_NE:
 
926
      case AFMT_S24_NE:
 
927
      case AFMT_S32_NE: break;
 
928
      default: level_meters = 0; /* Not implemented */
 
929
    }
 
930
 
 
931
  if ((signal (SIGSEGV, ossplay_getint) == SIG_ERR) ||
 
932
#ifdef SIGPIPE
 
933
      (signal (SIGPIPE, ossplay_getint) == SIG_ERR) ||
 
934
#endif
 
935
      (signal (SIGTERM, ossplay_getint) == SIG_ERR) ||
 
936
#ifdef SIGQUIT
 
937
      (signal (SIGQUIT, ossplay_getint) == SIG_ERR) ||
 
938
#endif
 
939
      (signal (SIGINT, ossplay_getint) == SIG_ERR))
 
940
    print_msg (WARNM, "Signal handler not set up!\n");
 
941
 
 
942
  if (verbose)
 
943
    {
 
944
      oss_audioinfo ai;
 
945
 
 
946
      ai.dev = -1;
 
947
 
 
948
      if (ioctl(dsp->fd, SNDCTL_ENGINEINFO, &ai) != -1)
 
949
        print_msg (VERBOSEM, "Recording from %s\n", ai.name);
 
950
   }
 
951
 
 
952
  return optind;
 
953
}
 
954
 
 
955
ldouble_t
 
956
ossplay_ldexpl (ldouble_t num, int exp)
 
957
{
 
958
  /*
 
959
   * Very simple emulation of ldexpl to avoid linking to libm or assuming
 
960
   * anything about float representation.
 
961
   */
 
962
  if (exp > 0)
 
963
    {
 
964
      while (exp > 31)
 
965
        {
 
966
          num *= 1UL << 31;
 
967
          exp -= 31;
 
968
        }
 
969
      num *= 1UL << exp;
 
970
    }
 
971
  else if (exp < 0)
 
972
    {
 
973
      while (exp < -31)
 
974
        {
 
975
          num /= 1UL << 31;
 
976
          exp += 31;
 
977
        }
 
978
      num /= 1UL << -exp;
 
979
    }
 
980
 
 
981
  return num;
 
982
}
 
983
 
 
984
static void
 
985
print_play_verbose_info (const unsigned char * buf, ssize_t l, void * metadata)
 
986
{
 
987
/*
 
988
 * Display a rough recording level meter, and the elapsed time.
 
989
 */
 
990
 
 
991
  verbose_values_t * val = (verbose_values_t *)metadata;
 
992
 
 
993
  val->secs += l/val->constant;
 
994
  if (val->secs < val->next_sec) return;
 
995
  val->next_sec += PLAY_UPDATE_INTERVAL/1000;
 
996
  /*
 
997
   * This check is done to ensure an update at the end of the playback.
 
998
   * Note that some files lie about total time, so the second condition is
 
999
   * necessary so that updates will still be constricted by PLAY_UPDATE_INTERVAL.
 
1000
   */
 
1001
  if ((val->next_sec > val->tsecs) && (val->secs < val->tsecs)) val->next_sec = val->tsecs;
 
1002
 
 
1003
  print_update (get_db_level (buf, l, val->format), val->secs, val->tstring);
 
1004
 
 
1005
  return;
 
1006
}
 
1007
 
 
1008
static void
 
1009
print_record_verbose_info (const unsigned char * buf, ssize_t l,
 
1010
                           void * metadata)
 
1011
{
 
1012
/*
 
1013
 * Display a rough recording level meter if enabled, and the elapsed time.
 
1014
 */
 
1015
 
 
1016
  verbose_values_t * val = (verbose_values_t *)metadata;
 
1017
  int update_dots = 1;
 
1018
 
 
1019
  val->secs += l / val->constant;
 
1020
 
 
1021
  if (val->secs >= val->next_sec)
 
1022
    {
 
1023
      val->next_sec += REC_UPDATE_INTERVAL/1000;
 
1024
      if ((val->tsecs) && (val->next_sec > val->tsecs))
 
1025
        val->next_sec = val->tsecs;
 
1026
      if (level_meters)
 
1027
        {
 
1028
          val->secs_timer2 = val->next_sec_timer2 = val->secs;
 
1029
          goto print_level;
 
1030
        }
 
1031
      print_record_update (-1, val->secs, val->tstring, 1);
 
1032
    }
 
1033
  else if ((level_meters) && (val->secs >= val->next_sec_timer2))
 
1034
    {
 
1035
      update_dots = 0;
 
1036
print_level:
 
1037
      val->next_sec_timer2 += LMETER_UPDATE_INTERVAL/1000;
 
1038
      if ((val->tsecs) && (val->next_sec_timer2 > val->tsecs))
 
1039
        val->next_sec_timer2 = val->tsecs;
 
1040
      print_record_update (get_db_level (buf, l, val->format), val->secs_timer2,
 
1041
                           val->tstring, update_dots);
 
1042
    }
 
1043
}
 
1044
 
 
1045
int
 
1046
play (dspdev_t * dsp, int fd, big_t * datamark, big_t bsize, double total_time,
 
1047
      double constant, readfunc_t * readf, decoders_queue_t * dec, seekfunc_t * seekf)
 
1048
{
 
1049
#define EXITPLAY(code) \
 
1050
  do { \
 
1051
    ossplay_free (buf); \
 
1052
    ossplay_free (verbose_meta); \
 
1053
    clear_update (); \
 
1054
    ioctl (dsp->fd, SNDCTL_DSP_HALT_OUTPUT, NULL); \
 
1055
    errno = 0; \
 
1056
    return (code); \
 
1057
  } while (0)
 
1058
 
 
1059
  big_t rsize = bsize;
 
1060
  big_t filesize = *datamark;
 
1061
  ssize_t outl;
 
1062
  unsigned char * buf, * obuf, contflag = 0;
 
1063
  decoders_queue_t * d;
 
1064
  verbose_values_t * verbose_meta = NULL;
 
1065
 
 
1066
  buf = (unsigned char *)ossplay_malloc (bsize);
 
1067
 
 
1068
  if (verbose)
 
1069
    {
 
1070
      verbose_meta = setup_verbose (dsp->format,
 
1071
                              format2bits(dsp->format) * dsp->channels *
 
1072
                              dsp->speed / 8.0, total_time);
 
1073
      if (seek_time == 0) print_play_verbose_info (NULL, 0, verbose_meta);
 
1074
    }
 
1075
 
 
1076
  *datamark = 0;
 
1077
 
 
1078
  while (*datamark < filesize)
 
1079
    {
 
1080
      if (eflag) EXITPLAY (eflag);
 
1081
 
 
1082
      rsize = bsize;
 
1083
      if (rsize > filesize - *datamark) rsize = filesize - *datamark;
 
1084
 
 
1085
      if ((seek_time != 0) && (seekf != NULL))
 
1086
        {
 
1087
          errors_t ret;
 
1088
 
 
1089
          ret = seekf (fd, datamark, filesize, constant, rsize, dsp->channels,
 
1090
                       dec->metadata);
 
1091
          if (ret == E_OK)
 
1092
            {
 
1093
              if (verbose)
 
1094
                {
 
1095
                  verbose_meta->secs = (double)seek_time;
 
1096
                  verbose_meta->next_sec = (double)seek_time;
 
1097
                  print_play_verbose_info (NULL, 0, verbose_meta);
 
1098
                }
 
1099
              seek_time = 0;
 
1100
              continue;
 
1101
            }
 
1102
          else if (ret == SEEK_CONT_AFTER_DECODE) contflag = 1;
 
1103
          else EXITPLAY (ret);
 
1104
        }
 
1105
 
 
1106
      if ((outl = readf (fd, buf, rsize, dec->metadata)) <= 0)
 
1107
        {
 
1108
          if (errno) perror_msg ("read");
 
1109
          if ((filesize != BIG_SPECIAL) && (*datamark < filesize) && (!eflag))
 
1110
            {
 
1111
              print_msg (NOTIFYM, "Sound data ended prematurely!\n");
 
1112
            }
 
1113
          EXITPLAY (eflag);
 
1114
        }
 
1115
      *datamark += outl;
 
1116
 
 
1117
      if (contflag)
 
1118
        {
 
1119
          contflag = 0;
 
1120
          continue;
 
1121
        }
 
1122
 
 
1123
      obuf = buf; d = dec;
 
1124
      do
 
1125
        {
 
1126
          outl = d->decoder (&(d->outbuf), obuf, outl, d->metadata);
 
1127
          obuf = d->outbuf;
 
1128
          d = d->next;
 
1129
        }
 
1130
      while (d != NULL);
 
1131
 
 
1132
      if (verbose) print_play_verbose_info (obuf, outl, verbose_meta);
 
1133
      if (write (dsp->fd, obuf, outl) == -1)
 
1134
        {
 
1135
          if ((errno == EINTR) && (eflag)) EXITPLAY (eflag);
 
1136
          ossplay_free (buf);
 
1137
          perror_msg ("audio write");
 
1138
          exit (E_DECODE);
 
1139
        }
 
1140
    }
 
1141
 
 
1142
  ossplay_free (buf);
 
1143
  ossplay_free (verbose_meta);
 
1144
  clear_update ();
 
1145
  return 0;
 
1146
}
 
1147
 
 
1148
int
 
1149
record (dspdev_t * dsp, FILE * wave_fp, const char * filename, double constant,
 
1150
        big_t datalimit, big_t * data_size, decoders_queue_t * dec)
 
1151
{
 
1152
#define EXITREC(code) \
 
1153
  do { \
 
1154
    ossplay_free (buf); \
 
1155
    ossplay_free (verbose_meta); \
 
1156
    clear_update (); \
 
1157
    if ((eflag) && (verbose)) \
 
1158
      print_msg (VERBOSEM, "\nStopped (%d).\n", eflag-128); \
 
1159
    ioctl (dsp->fd, SNDCTL_DSP_HALT_INPUT, NULL); \
 
1160
    return (code); \
 
1161
  } while(0)
 
1162
 
 
1163
  ssize_t l, outl;
 
1164
  decoders_queue_t * d;
 
1165
  unsigned char * buf, * obuf;
 
1166
  verbose_values_t * verbose_meta = NULL;
 
1167
 
 
1168
  if (verbose)
 
1169
    {
 
1170
      verbose_meta = setup_verbose (dsp->format, constant, datalimit/constant);
 
1171
      strncpy (verbose_meta->tstring, filename, 20)[19] = 0;
 
1172
    }
 
1173
 
 
1174
  *data_size = 0;
 
1175
  buf = (unsigned char *)ossplay_malloc (RECBUF_SIZE);
 
1176
   /*LINTED*/ while (1)
 
1177
    {
 
1178
      if ((l = read (dsp->fd, buf, RECBUF_SIZE)) < 0)
 
1179
        {
 
1180
          if ((errno == EINTR) && (eflag)) EXITREC (eflag);
 
1181
          if (errno == ECONNRESET) EXITREC (E_ENCODE); /* Device disconnected */
 
1182
          perror_msg (dsp->dname);
 
1183
          EXITREC (E_ENCODE);
 
1184
        }
 
1185
      if (l == 0)
 
1186
        {
 
1187
          print_msg (ERRORM, "Unexpected EOF on audio device\n");
 
1188
          EXITREC (eflag);
 
1189
        }
 
1190
 
 
1191
      obuf = buf; d = dec; outl = l;
 
1192
      do
 
1193
        {
 
1194
          outl = d->decoder (&(d->outbuf), obuf, outl, d->metadata);
 
1195
          obuf = d->outbuf;
 
1196
          d = d->next;
 
1197
        }
 
1198
      while (d != NULL);
 
1199
 
 
1200
      if (eflag) EXITREC (eflag);
 
1201
 
 
1202
      if (fwrite (obuf, outl, 1, wave_fp) != 1)
 
1203
        {
 
1204
          if ((errno == EINTR) && (eflag)) EXITREC (eflag);
 
1205
          perror_msg (filename);
 
1206
          EXITREC (E_ENCODE);
 
1207
        }
 
1208
 
 
1209
      *data_size += outl;
 
1210
      if (verbose) print_record_verbose_info (obuf, outl, verbose_meta);
 
1211
 
 
1212
      if ((datalimit != 0) && (*data_size >= datalimit)) break;
 
1213
    }
 
1214
 
 
1215
  ossplay_free (buf);
 
1216
  ossplay_free (verbose_meta);
 
1217
  clear_update ();
 
1218
  print_msg (VERBOSEM, "\nDone.\n");
 
1219
  return 0;
 
1220
}
 
1221
 
 
1222
errors_t
 
1223
silence (dspdev_t * dsp, big_t len, int speed)
 
1224
{
 
1225
  errors_t ret;
 
1226
  ssize_t i;
 
1227
  unsigned char empty[1024];
 
1228
 
 
1229
  ret = setup_device (dsp, AFMT_U8, 1, speed);
 
1230
 
 
1231
  if (ret == E_FORMAT_UNSUPPORTED)
 
1232
    {
 
1233
      len *= 4;
 
1234
      if ((ret = setup_device (dsp, AFMT_S16_NE, 2, speed))) return ret;
 
1235
    }
 
1236
  else if (ret) return ret;
 
1237
 
 
1238
  memset (empty, 0, 1024 * sizeof (unsigned char));
 
1239
 
 
1240
  while (len > 0)
 
1241
    {
 
1242
      i = 1024;
 
1243
      if ((big_t)i > len) i = len;
 
1244
      if ((i = write (dsp->fd, empty, i)) < 0) return -1;
 
1245
 
 
1246
      len -= i;
 
1247
    }
 
1248
 
 
1249
  return E_OK;
 
1250
}