14765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/* 24765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** Copyright 2010, The Android Open-Source Project 34765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. 44765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** 54765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** Licensed under the Apache License, Version 2.0 (the "License"); 64765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** you may not use this file except in compliance with the License. 74765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** You may obtain a copy of the License at 84765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** 94765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** http://www.apache.org/licenses/LICENSE-2.0 104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** 114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** Unless required by applicable law or agreed to in writing, software 124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** distributed under the License is distributed on an "AS IS" BASIS, 134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** See the License for the specific language governing permissions and 154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev** limitations under the License. 164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev*/ 174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdio.h> 194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdlib.h> 204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <fcntl.h> 214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <unistd.h> 224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdint.h> 234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <string.h> 244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <signal.h> 254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <errno.h> 264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <sys/poll.h> 274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <sys/ioctl.h> 284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <getopt.h> 294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <limits.h> 304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include "alsa_audio.h" 324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define ID_RIFF 0x46464952 344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define ID_WAVE 0x45564157 354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define ID_FMT 0x20746d66 364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define ID_DATA 0x61746164 374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define FORMAT_PCM 1 394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#ifndef ANDROID 414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define strlcat g_strlcat 424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define strlcpy g_strlcpy 434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic struct wav_header hdr; 464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int fd; 474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic struct pcm *pcm; 489746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudanistatic int debug = 0; 499746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudanistatic int pcm_flag = 1; 509746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudanistatic int duration = 0; 514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic char *filename; 524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic char *data; 534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int format = SNDRV_PCM_FORMAT_S16_LE; 544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int period = 0; 554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int piped = 0; 564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic struct option long_options[] = 584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {"pcm", 0, 0, 'P'}, 604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {"debug", 0, 0, 'V'}, 614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {"Mmap", 0, 0, 'M'}, 624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {"HW", 1, 0, 'D'}, 634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {"Rate", 1, 0, 'R'}, 644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {"channel", 1, 0, 'C'}, 654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {"duration", 1, 0, 'T'}, 664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {"format", 1, 0, 'F'}, 674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {"period", 1, 0, 'B'}, 684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {0, 0, 0, 0} 694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; 704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstruct wav_header { 724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t riff_id; 734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t riff_sz; 744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t riff_fmt; 754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t fmt_id; 764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t fmt_sz; 774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint16_t audio_format; 784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint16_t num_channels; 794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t sample_rate; 804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */ 814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint16_t block_align; /* num_channels * bps / 8 */ 824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint16_t bits_per_sample; 834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t data_id; 844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t data_sz; 854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; 864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int set_params(struct pcm *pcm) 884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev struct snd_pcm_hw_params *params; 904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev struct snd_pcm_sw_params *sparams; 914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned long periodSize, bufferSize, reqBuffSize; 934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned int periodTime, bufferTime; 944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned int requestedRate = pcm->rate; 954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev params = (struct snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params)); 974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!params) { 984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Failed to allocate ALSA hardware parameters!"); 994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -ENOMEM; 1004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_init(params); 1034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS, 1054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (pcm->flags & PCM_MMAP)? SNDRV_PCM_ACCESS_MMAP_INTERLEAVED : SNDRV_PCM_ACCESS_RW_INTERLEAVED); 1064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, pcm->format); 1074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev SNDRV_PCM_SUBFORMAT_STD); 1094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (period) 1104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_min(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, period); 1114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 1124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_min(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 10); 1134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16); 1144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS, 1154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->channels * 16); 1164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS, 1174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->channels); 1184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, pcm->rate); 1194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_set_hw_refine(pcm, params); 1214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param_set_hw_params(pcm, params)) { 1234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:cannot set hw params"); 1244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 1254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) 1274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param_dump(params); 1284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->buffer_size = pcm_buffer_size(params); 1304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->period_size = pcm_period_size(params); 1314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->period_cnt = pcm->buffer_size/pcm->period_size; 1324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) { 1334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf (stderr,"period_size (%d)", pcm->period_size); 1344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf (stderr," buffer_size (%d)", pcm->buffer_size); 1354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf (stderr," period_cnt (%d)\n", pcm->period_cnt); 1364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams = (struct snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params)); 1384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!sparams) { 1394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Failed to allocate ALSA software parameters!\n"); 1404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -ENOMEM; 1414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; 1434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->period_step = 1; 1444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (pcm->flags & PCM_MONO) { 1464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->avail_min = pcm->period_size/2; 1474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->xfer_align = pcm->period_size/2; 1484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (pcm->flags & PCM_QUAD) { 1494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->avail_min = pcm->period_size/8; 1504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->xfer_align = pcm->period_size/8; 1514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (pcm->flags & PCM_5POINT1) { 1524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->avail_min = pcm->period_size/12; 1534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->xfer_align = pcm->period_size/12; 1544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 1554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->avail_min = pcm->period_size/4; 1564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->xfer_align = pcm->period_size/4; 1574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->start_threshold = 1; 1604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->stop_threshold = INT_MAX; 1614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->silence_size = 0; 1624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sparams->silence_threshold = 0; 1634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param_set_sw_params(pcm, sparams)) { 1654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:cannot set sw params"); 1664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 1674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) { 1694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf (stderr,"avail_min (%lu)\n", sparams->avail_min); 1704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf (stderr,"start_threshold (%lu)\n", sparams->start_threshold); 1714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf (stderr,"stop_threshold (%lu)\n", sparams->stop_threshold); 1724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf (stderr,"xfer_align (%lu)\n", sparams->xfer_align); 1734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return 0; 1754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 1774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint record_file(unsigned rate, unsigned channels, int fd, unsigned count, unsigned flags, const char *device) 1794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 1804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned xfer, bufsize; 1814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int r, avail; 1824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int nfds = 1; 1834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev static int start = 0; 1844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev struct snd_xferi x; 1854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long frames; 1864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned offset = 0; 1874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int err; 1884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev struct pollfd pfd[1]; 1894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int rec_size = 0; 1904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flags |= PCM_IN; 1924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (channels == 1) 1944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flags |= PCM_MONO; 1954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else if (channels == 4) 1964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flags |= PCM_QUAD; 1974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else if (channels == 6) 1984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flags |= PCM_5POINT1; 1994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 2004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flags |= PCM_STEREO; 2014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm = pcm_open(flags, device); 2034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!pcm_ready(pcm)) { 2044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm_close(pcm); 2054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev goto fail; 2064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->channels = channels; 2084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->rate = rate; 2094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->flags = flags; 2104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->format = format; 2114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (set_params(pcm)) { 2124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:params setting failed\n"); 2134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm_close(pcm); 2144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -EINVAL; 2154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!pcm_flag) { 2184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (pcm_prepare(pcm)) { 2194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Failed in pcm_prepare\n"); 2204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm_close(pcm); 2214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 2224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START)) { 2244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec: Hostless IOCTL_START Error no %d \n", errno); 2254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm_close(pcm); 2264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 2274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev while(1); 2294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (flags & PCM_MMAP) { 2324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev u_int8_t *dst_addr = NULL; 2334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev struct snd_pcm_sync_ptr *sync_ptr1 = pcm->sync_ptr; 2344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned int tmp; 2354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mmap_buffer(pcm)) { 2374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:params setting failed\n"); 2384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm_close(pcm); 2394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -EINVAL; 2404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) 2424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:mmap_buffer done\n"); 2434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (pcm_prepare(pcm)) { 2454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Failed in pcm_prepare\n"); 2464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm_close(pcm); 2474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 2484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufsize = pcm->period_size; 2514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) 2524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:bufsize = %d\n", bufsize); 2534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START)) { 2544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (errno == EPIPE) { 2554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Failed in SNDRV_PCM_IOCTL_START\n"); 2564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev /* we failed to make our window -- try to restart */ 2574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->running = 0; 2584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 2594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Error no %d \n", errno); 2604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 2614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pfd[0].fd = pcm->fd; 2654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pfd[0].events = POLLIN; 2664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.data_sz = 0; 2684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (pcm->flags & PCM_MONO) { 2694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev frames = bufsize / 2; 2704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (pcm->flags & PCM_QUAD) { 2714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev frames = bufsize / 8; 2724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (pcm->flags & PCM_5POINT1) { 2734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev frames = bufsize / 12; 2744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else{ 2754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev frames = bufsize / 4; 2764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev x.frames = frames; 2784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(;;) { 2794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!pcm->running) { 2804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (pcm_prepare(pcm)) 2814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return --errno; 2824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev start = 0; 2834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev /* Sync the current Application pointer from the kernel */ 2854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL | SNDRV_PCM_SYNC_PTR_AVAIL_MIN;//SNDRV_PCM_SYNC_PTR_HWSYNC; 2864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = sync_ptr(pcm); 2874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err == EPIPE) { 2884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Failed in sync_ptr \n"); 2894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev /* we failed to make our window -- try to restart */ 2904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev //pcm->overruns++; 2914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->running = 0; 2924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev continue; 2934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev /* 2954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Check for the available data in driver. If available data is 2964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * less than avail_min we need to wait 2974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev */ 2984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev avail = pcm_avail(pcm); 2994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) 3004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:avail 1 = %d frames = %ld\n",avail, frames); 3014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (avail < 0) 3024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return avail; 3034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (avail < pcm->sw_p->avail_min) { 3044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev poll(pfd, nfds, TIMEOUT_INFINITE); 3054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev continue; 3064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (x.frames > avail) 3084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev frames = avail; 3094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev /* 3104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Now that we have data size greater than avail_min available to 3114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * to be read we need to calcutate the buffer offset where we can 3124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * start reading from. 3134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev */ 3144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev dst_addr = dst_address(pcm); 3154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev /* 3174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Write to the file at the destination address from kernel mmaped buffer 3184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * This reduces a extra copy of intermediate buffer. 3194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev */ 3204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (write(fd, dst_addr, bufsize) != bufsize) { 3214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:could not write %d bytes\n", bufsize); 3224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 3234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev x.frames -= frames; 3254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->sync_ptr->c.control.appl_ptr += frames; 3264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->sync_ptr->flags = 0; 3274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = sync_ptr(pcm); 3284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err == EPIPE) { 3294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Failed in sync_ptr \n"); 3304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev /* we failed to make our window -- try to restart */ 3314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm->running = 0; 3324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev continue; 3334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev rec_size += bufsize; 3354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.data_sz += bufsize; 3364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.riff_sz = hdr.data_sz + 44 - 8; 3374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!piped) { 3384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev lseek(fd, 0, SEEK_SET); 3394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev write(fd, &hdr, sizeof(hdr)); 3404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev lseek(fd, 0, SEEK_END); 3414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (rec_size >= count) 3434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 3464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufsize = pcm->period_size; 3474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (pcm_prepare(pcm)) { 3484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Failed in pcm_prepare\n"); 3494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm_close(pcm); 3504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 3514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev data = calloc(1, bufsize); 3544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!data) { 3554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:could not allocate %d bytes\n", bufsize); 3564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -ENOMEM; 3574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev while (!pcm_read(pcm, data, bufsize)) { 3604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (write(fd, data, bufsize) != bufsize) { 3614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:could not write %d bytes\n", bufsize); 3624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev rec_size += bufsize; 3654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.data_sz += bufsize; 3664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.riff_sz = hdr.data_sz + 44 - 8; 3674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!piped) { 3684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev lseek(fd, 0, SEEK_SET); 3694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev write(fd, &hdr, sizeof(hdr)); 3704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev lseek(fd, 0, SEEK_END); 3714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (rec_size >= count) 3734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 3744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, " rec_size =%d count =%d\n", rec_size, count); 3774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev close(fd); 3784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(data); 3794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm_close(pcm); 3804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return hdr.data_sz; 3814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevfail: 3834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:pcm error: %s\n", pcm_error(pcm)); 3844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 3854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint rec_raw(const char *fg, const char *device, int rate, int ch, 3884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev const char *fn) 3894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned flag = 0; 3914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t rec_max_sz = 2147483648LL; 3924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t count; 3934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int i = 0; 3944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!fn) { 3964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fd = fileno(stdout); 3974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev piped = 1; 3984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 3994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664); 4004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (fd < 0) { 4014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:arec: cannot open '%s'\n", fn); 4024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -EBADFD; 4034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (duration == 0) { 4064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev count = rec_max_sz; 4074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 4084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev count = rate * ch * 2; 4094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev count *= (uint32_t)duration; 4104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev count = count < rec_max_sz ? count : rec_max_sz; 4124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) 4134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "arec: %d ch, %d hz, %d bit, format %x\n", 4144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ch, rate, 16, format); 4154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!strncmp(fg, "M", sizeof("M"))) { 4174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flag = PCM_MMAP; 4184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (!strncmp(fg, "N", sizeof("N"))) { 4194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flag = PCM_NMMAP; 4204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return record_file(rate, ch, fd, count, flag, device); 4224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint rec_wav(const char *fg, const char *device, int rate, int ch, const char *fn) 4254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 4264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned flag = 0; 4274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t rec_max_sz = 2147483648LL; 4284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t count = 0; 4294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int i = 0; 4304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (pcm_flag) { 4324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!fn) { 4334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fd = fileno(stdout); 4344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev piped = 1; 4354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 4364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664); 4374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (fd < 0) { 4384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:arec: cannot open '%s'\n", fn); 4394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -EBADFD; 4404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev memset(&hdr, 0, sizeof(struct wav_header)); 4434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.riff_id = ID_RIFF; 4444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.riff_fmt = ID_WAVE; 4454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.fmt_id = ID_FMT; 4464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.fmt_sz = 16; 4474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.audio_format = FORMAT_PCM; 4484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.num_channels = ch; 4494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.sample_rate = rate; 4504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.bits_per_sample = 16; 4514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.byte_rate = (rate * ch * hdr.bits_per_sample) / 8; 4524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.block_align = ( hdr.bits_per_sample * ch ) / 8; 4534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.data_id = ID_DATA; 4544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.data_sz = 0; 4554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (duration == 0) { 4574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev count = rec_max_sz; 4584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 4594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev count = rate * ch * 2; 4604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev count *= (uint32_t)duration; 4614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.riff_sz = hdr.data_sz + 44 - 8; 4634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { 4644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) 4654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "arec: cannot write header\n"); 4664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -errno; 4674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) 4694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "arec: %d ch, %d hz, %d bit, %s\n", 4704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample, 4714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown"); 4724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 4734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.sample_rate = rate; 4744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.num_channels = ch; 4754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!strncmp(fg, "M", sizeof("M"))) { 4784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flag = PCM_MMAP; 4794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (!strncmp(fg, "N", sizeof("N"))) { 4804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flag = PCM_NMMAP; 4814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return record_file(hdr.sample_rate, hdr.num_channels, fd, count, flag, device); 4834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic void signal_handler(int sig) 4864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 4874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long file_size; 4884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev FILE *fp; 4894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Aborted by signal %s...\n", strsignal(sig)); 4914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:lseeked to %d", (int) lseek(fd, 0, SEEK_SET)); 4924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hdr.riff_sz = hdr.data_sz + 44 - 8; 4934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec: hdr.data_sz =%d\n", hdr.data_sz); 4944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec: hdr.riff_sz =%d\n", hdr.riff_sz); 4954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { 4964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (debug) 4974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:arec: cannot write header\n"); 4984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else 4994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fd = -1; 5004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (fd > 1) { 5024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev close(fd); 5034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fd = -1; 5044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(filename); 5064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(data); 5074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm = NULL; 5084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev raise(sig); 5094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 5104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint main(int argc, char **argv) 5124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 5134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int rate = 48000; 5144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int ch = 1; 5154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int i = 0; 5164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int option_index = 0; 5174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int c; 5184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char *mmap = "N"; 5194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char *device = "hw:0,0"; 5204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev struct sigaction sa; 5214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int rc = 0; 5224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (argc < 2) { 5244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev printf("\nUsage: arec [options] <file>\n" 5254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "options:\n" 5264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-D <hw:C,D> -- Alsa PCM by name\n" 5274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-M -- Mmap stream\n" 5284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-P -- Hostless steam[No PCM]\n" 5294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-V -- verbose\n" 5304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-C -- Channels\n" 5314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-R -- Rate\n" 5324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-T -- Time in seconds for recording\n" 5334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-F -- Format\n" 5344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-B -- Period\n" 5354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "<file> \n"); 5364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (i = 0; i < SNDRV_PCM_FORMAT_LAST; ++i) 5374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (get_format_name(i)) 5384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "%s ", get_format_name(i)); 5394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "\nSome of these may not be available on selected hardware\n"); 5404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return 0; 5414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev while ((c = getopt_long(argc, argv, "PVMD:R:C:T:F:B:", long_options, &option_index)) != -1) { 5434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch (c) { 5444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 'P': 5454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev pcm_flag = 0; 5464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 'V': 5484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev debug = 1; 5494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 'M': 5514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mmap = "M"; 5524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 'D': 5544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev device = optarg; 5554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 'R': 5574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev rate = (int)strtol(optarg, NULL, 0); 5584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 'C': 5604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ch = (int)strtol(optarg, NULL, 0); 5614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 'T': 5634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev duration = (int)strtol(optarg, NULL, 0); 5644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 'F': 5664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev format = (int)get_format(optarg); 5674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case 'B': 5694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev period = (int)strtol(optarg, NULL, 0); 5704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 5724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev printf("\nUsage: arec [options] <file>\n" 5734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "options:\n" 5744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-D <hw:C,D> -- Alsa PCM by name\n" 5754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-M -- Mmap stream\n" 5764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-P -- Hostless steam[No PCM]\n" 5774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-V -- verbose\n" 5784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-C -- Channels\n" 5794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-R -- Rate\n" 5804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-T -- Time in seconds for recording\n" 5814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-F -- Format\n" 5824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "-B -- Period\n" 5834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "<file> \n"); 5844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (i = 0; i < SNDRV_PCM_FORMAT_LAST; ++i) 5854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (get_format_name(i)) 5864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "%s ", get_format_name(i)); 5874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "\nSome of these may not be available on selected hardware\n"); 5884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -EINVAL; 5894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev filename = (char*) calloc(1, 30); 5924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!filename) { 5934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fprintf(stderr, "Arec:Failed to allocate filename!"); 5944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return -ENOMEM; 5954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (optind > argc - 1) { 5974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(filename); 5984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev filename = NULL; 5994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 6004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(filename, argv[optind++], 30); 6014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev memset(&sa, 0, sizeof(sa)); 6044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sa.sa_handler = &signal_handler; 6054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sigaction(SIGABRT, &sa, NULL); 6064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (pcm_flag) { 6084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (format == SNDRV_PCM_FORMAT_S16_LE) 6094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev rc = rec_wav(mmap, device, rate, ch, filename); 6104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 6114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev rc = rec_raw(mmap, device, rate, ch, filename); 6124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 6134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev rc = rec_wav(mmap, device, rate, ch, "dummy"); 6144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (filename) 6164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(filename); 6174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return rc; 6194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 6204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 621