xref: /OK3568_Linux_fs/app/forlinx/flapp/src/plugins/allwinner/audiorecorder/widget.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 #include "widget.h"
2 #include "ui_widget.h"
3 
4 #include <QFileDialog>
5 #include <QTimer>
6 #include <QTime>
7 #include <QDebug>
8 #include <QCoreApplication>
9 
Widget(QWidget * parent)10 Widget::Widget(QWidget *parent)
11     : IWidget(parent)
12     , ui(new Ui::Widget)
13 {
14     ui->setupUi(this);
15     ui->lcdNumber->setDigitCount(8);
16 
17     ui->dirEdit->installEventFilter(this);
18 
19     capturing = false;
20     record_init();
21 
22     connect(&timer, &QTimer::timeout, this, [=](){
23         QTime m_time;
24         m_time.setHMS(0, 0, 0, 0);
25         QString timestr = m_time.addSecs(startTime.secsTo(QDateTime::currentDateTime())).toString("hh:mm:ss");
26         ui->lcdNumber->display(timestr);
27     });
28 }
29 
~Widget()30 Widget::~Widget()
31 {
32     delete ui;
33 }
34 
id()35 QString Widget::id()
36 {
37     return  "audiorecorder";
38 }
39 
record_init()40 void Widget::record_init()
41 {
42     card = 3;
43     device = 0;
44     ahub_card = 1;
45     ahub_device = 1;
46 
47     channels = 2;
48     rate = 44100;
49     bits = 16;
50     period_size = 1024;
51     period_count = 4;
52     format = PCM_FORMAT_S16_LE;
53 
54     header.riff_id = ID_RIFF;
55     header.riff_sz = 0;
56     header.riff_fmt = ID_WAVE;
57     header.fmt_id = ID_FMT;
58     header.fmt_sz = 16;
59     header.audio_format = FORMAT_PCM;
60     header.num_channels = channels;
61     header.sample_rate = rate;
62 
63     header.bits_per_sample = pcm_format_to_bits(format);
64     header.byte_rate = (header.bits_per_sample / 8) * channels * rate;
65     header.block_align = channels * (header.bits_per_sample / 8);
66     header.data_id = ID_DATA;
67 }
68 
69 
capture_sample()70 unsigned int Widget::capture_sample()
71 {
72     struct pcm_config config;
73     struct pcm *pcm;
74     struct pcm *ahub_pcm;
75     char *buffer;
76     unsigned int size;
77     unsigned int frames = 0;
78     unsigned int bytes_read = 0;
79 
80     memset(&config, 0, sizeof(config));
81     config.channels = channels;
82     config.rate = rate;
83     config.period_size = period_size;
84     config.period_count = period_count;
85     config.format = format;
86     config.start_threshold = 0;
87     config.stop_threshold = period_count * period_size;
88     config.silence_threshold = 0;
89 
90     pcm = pcm_open(card, device, PCM_IN, &config);
91     if (!pcm || !pcm_is_ready(pcm)) {
92         fprintf(stderr, "Unable to open PCM device (%s)\n",
93                 pcm_get_error(pcm));
94         return -1;
95     }
96     pcm_start(pcm);
97 
98     ahub_pcm = pcm_open(ahub_card, ahub_device, PCM_IN, &config);
99     if (!ahub_pcm || !pcm_is_ready(ahub_pcm)) {
100         fprintf(stderr, "Unable to open AHub device %d (%s)\n",
101                 ahub_device, pcm_get_error(ahub_pcm));
102         pcm_close(pcm);
103         return -1;
104     }
105 
106     size = pcm_frames_to_bytes(ahub_pcm, pcm_get_buffer_size(ahub_pcm));
107     buffer = (char *)malloc(size);
108     if (!buffer) {
109         fprintf(stderr, "Unable to allocate %d bytes\n", size);
110         free(buffer);
111         pcm_close(ahub_pcm);
112         pcm_close(pcm);
113         return -1;
114     }
115 
116     printf("Capturing sample: %u ch, %u hz, %u bit, malloc buffer:%d\n",
117             channels, rate, pcm_format_to_bits(format), size);
118 
119     while (capturing && !pcm_read(ahub_pcm, buffer, size)) {
120 
121         if (fwrite(buffer, 1, size, file) != size) {
122             fprintf(stderr,"Error capturing sample\n");
123             break;
124         }
125         bytes_read += size;
126         QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
127     }
128 
129     frames = pcm_bytes_to_frames(ahub_pcm, bytes_read);
130 
131     free(buffer);
132     pcm_close(ahub_pcm);
133     pcm_close(pcm);
134 
135     return frames;
136 }
137 
138 
on_pushButton_clicked()139 void Widget::on_pushButton_clicked()
140 {
141     QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"),
142                                                      "/",
143                                                      QFileDialog::ShowDirsOnly
144                                                      | QFileDialog::DontResolveSymlinks);
145     if (!dir.isEmpty())
146         ui->dirEdit->setText(dir + "/record.wav");
147 }
148 
on_startBtn_clicked()149 void Widget::on_startBtn_clicked()
150 {
151     file = fopen(ui->dirEdit->text().toLocal8Bit().data(), "wb");
152     if (!file) {
153         qDebug()<<ui->dirEdit->text()<<" open failed";
154         return;
155     }
156 
157     ui->startBtn->setEnabled(false);
158     capturing = true;
159 
160     /* leave enough room for header */
161     fseek(file, sizeof(struct wav_header), SEEK_SET);
162 
163     startTime = QDateTime::currentDateTime();
164     timer.start(10);
165 
166     int frames = capture_sample();
167 
168     /* write header now all information is known */
169     header.data_sz = frames * header.block_align;
170     header.riff_sz = header.data_sz + sizeof(header) - 8;
171     fseek(file, 0, SEEK_SET);
172     fwrite(&header, sizeof(struct wav_header), 1, file);
173     fclose(file);
174 }
175 
on_stopBtn_clicked()176 void Widget::on_stopBtn_clicked()
177 {
178     timer.stop();
179     capturing = false;
180     ui->startBtn->setEnabled(true);
181 }
182