blob: 405cedaabac91dda37b0fd33cd38d272879ee9cf [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001/**
2 * \file mbtk_audio_alsa.c
3 * \brief A Documented file.
4 *
5 * Detailed description
6 * \Author: js.wang <js.wang@mobiletek.cn>
7 * \Version: 1.0.0
8 * \Date: 2020-09-21
9 */
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14#include <sys/types.h>
15#include <errno.h>
16#include <fcntl.h>
17#include <pthread.h>
18
19#include "audio_if_types.h"
20#include "audio_if_ubus.h"
21#include "audio_if_parameter.h"
22#include "audio_if.h"
23#include "audio_if_api.h"
24#include <unistd.h>
25#include <sys/stat.h>
26#include "audio_if_audio_hw_mrvl.h"
27#include "audio_hw_mrvl.h"
28#include <cutils/str_parms.h>
29#include "vcm.h"
30#include "voice_control.h"
31#include "mbtk_audio.h"
32
33
34// #define DEBUG 1
35
36#ifdef DEBUG
37 #define mbtk_audio_log(...) printf(__VA_ARGS__)
38#else
39 #define mbtk_audio_log(...)
40#endif
41
42typedef int (*_play_callback)(int hdl, int result);
43
44#define FAILURE -1
45#define ID_RIFF 0x46464952
46#define ID_WAVE 0x45564157
47#define ID_FMT 0x20746d66
48#define ID_DATA 0x61746164
49#define FORMAT_PCM 1
50
51
52
53struct mopen_audio_t
54{
55 int device;
56 audio_hw_device_t *audio_ahw_dev_ubus;
57 struct audio_stream_in *stream_in;
58 struct audio_stream_out *stream_out;
59 int pcm_packet_size; //320:NB, 640:WB
60 int pipe_data;
61 int fd[2];
62 pthread_t pid;
63 mbtk_audio_state_enum state;
64 pthread_mutex_t _cond_mutex;
65 pthread_mutex_t _stream_mutex;
66 void *usrData;
67};
68struct record_cb_s
69{
70 mbtk_audio_record_cb_func _cb;
71 void *cb_data;
72};
73
74static struct mopen_audio_t *internal_hdl = NULL;
75
76
77int mbtk_wav_pcm16Le_check(int fd)
78{
79 printf("MBTK_wav_pcm16Le_check()----------strart5, fd:%d\n", fd);
80 struct wav_header hdr;
81
82 if (fd <= 0)
83 return -1;
84
85 if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
86 {
87 printf("\n%s: cannot read header\n", __FUNCTION__);
88 return -1;
89 }
90
91 printf("hdr.riff_id:%X, hdr.riff_fmt:%X, hdr.fmt_id:%X", hdr.riff_id, hdr.riff_fmt, hdr.fmt_id);
92
93 if ((hdr.riff_id != ID_RIFF)
94 || (hdr.riff_fmt != ID_WAVE)
95 || (hdr.fmt_id != ID_FMT))
96 {
97 printf("\n%s: is not a riff/wave file\n", __FUNCTION__);
98 return -1;
99 }
100
101 if ((hdr.audio_format != FORMAT_PCM) || (hdr.fmt_sz != 16)) {
102 printf("\n%s: is not pcm format\n", __FUNCTION__);
103 return -1;
104 }
105
106 if (hdr.bits_per_sample != 16) {
107 printf("\n%s: is not 16bit per sample\n", __FUNCTION__);
108 return -1;
109 }
110
111 printf("audio_format: %d,num_channels: %d,sample_rate: %d,byte_rate: %d,bits_per_sample: %d data_sz: %d\n",
112 hdr.audio_format, hdr.num_channels, hdr.sample_rate, hdr.byte_rate, hdr.bits_per_sample, hdr.data_sz);
113
114 return hdr.data_sz;
115}
116
117
118static void simulateOffhook(struct mopen_audio_t *aud_hdl, unsigned int onoff)
119{
120 unsigned int pcm_on;
121 unsigned int DTMFDetectiononoff;
122 unsigned int dialToneToOthersTones;
123 unsigned int dialTonesToOthersDialTones;
124 unsigned int dialVadDuration;
125
126 pcm_on = onoff;
127 //send the command of "AUDIOSTUB_PCMCTL"
128 aud_hdl->audio_ahw_dev_ubus->switch_pcm(aud_hdl->audio_ahw_dev_ubus, pcm_on);
129
130 DTMFDetectiononoff = onoff;
131 dialToneToOthersTones = 50;
132 dialTonesToOthersDialTones = 4;
133 dialVadDuration = 3;
134 //send the command of "AUDIOSTUB_DTMFDETECTIONCTL"
135 //vcm_DTMFDetection(1, 50, 4, 3);
136 vcm_DTMFDetection(DTMFDetectiononoff, dialToneToOthersTones, dialTonesToOthersDialTones, dialVadDuration);
137
138 return;
139}
140static int config_parameters(int in_out, int NBWB)
141{
142 unsigned int direction = 0xFF, type, srcdst, priority, dest;
143 char kvpair[128];
144 struct str_parms *param = NULL;
145 int data[5];
146 const char *key = NULL;
147 bool update_vcm = false;
148
149 direction = in_out;/* 0-play, 1-record */
150 type = NBWB; /* 0:PCM_NB_BUF_SIZE, 1:PCM_WB_BUF_SIZE */
151 srcdst = 1;/* 0-None, 1-Near end, 2-Far end, 3-Both ends */
152 priority = 1;/* 0-Do not combine(override), 1-Combine */
153 dest = 1;/* 0-Near codec, 1-Near Vocoder */
154
155 memset(kvpair, 0x00, sizeof(kvpair));
156 sprintf(kvpair, "%s=%d;%s=%d;%s=%d;%s=%d;%s=%d", VCM_CONFIG_DIRECTION, direction,
157 VCM_CONFIG_TYPE, type, VCM_CONFIG_SRC_DST, srcdst,
158 VCM_CONFIG_PRIORITY, priority, VCM_CONFIG_DEST, dest);
159
160 mbtk_audio_log("%s: config information kvpair is %s.\n", __FUNCTION__, kvpair);
161
162 //extract the parameter and config from string
163 param = str_parms_create_str(kvpair);
164 if (!param) {
165 printf("%s: param create str is null!", __FUNCTION__);
166 return -1;
167 }
168
169 //set vcm configurations
170 key = VCM_CONFIG_DIRECTION;
171 if (str_parms_get_int(param, key, &data[0]) == 0) {
172 update_vcm = true;
173 str_parms_del(param, key);
174 }
175 key = VCM_CONFIG_TYPE;
176 if (str_parms_get_int(param, key, &data[1]) == 0) {
177 update_vcm = true;
178 str_parms_del(param, key);
179 }
180 key = VCM_CONFIG_SRC_DST;
181 if (str_parms_get_int(param, key, &data[2]) == 0) {
182 update_vcm = true;
183 str_parms_del(param, key);
184 }
185 key = VCM_CONFIG_PRIORITY;
186 if (str_parms_get_int(param, key, &data[3]) == 0) {
187 update_vcm = true;
188 str_parms_del(param, key);
189 }
190 key = VCM_CONFIG_DEST;
191 if (str_parms_get_int(param, key, &data[4]) == 0) {
192 update_vcm = true;
193 str_parms_del(param, key);
194 }
195
196 //printf("Direction is %d, Type is %d, Src_Dst is %d, Priority is %d, Dest is %d. \n",data[0], data[1], data[2], data[3], data[4]);
197
198 if (update_vcm) {
199 configure_vcm(data); /*TODO check if all inputs got all values successfully*/
200 }
201
202 return 0;
203}
204
205void mbtk_audio_set_status(void* hdl, mbtk_audio_state_enum _status)
206{
207 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)hdl;
208 if (NULL == hdl || NULL == internal_hdl)
209 return 0;
210 pthread_mutex_lock(&pcxt->_cond_mutex);
211 pcxt->state = _status;
212 pthread_mutex_unlock(&pcxt->_cond_mutex);
213}
214
215static void* mbtk_record_pthread(void* hdl)
216{
217 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)hdl;
218 struct record_cb_s *_usrData = (struct record_cb_s *)pcxt->usrData;
219 unsigned bufsize = 0;
220 char *data = NULL;
221 int len;
222
223 if (NULL == hdl)
224 return NULL;
225
226 bufsize = pcxt->pcm_packet_size;
227 data = calloc(1, bufsize);
228 if (!data) {
229 fprintf(stderr, "\n%s:could not allocate %d bytes\n", __FUNCTION__, bufsize);
230 return NULL;
231 }
232
233 mbtk_audio_set_status(hdl, AUDIO_RUNNING);
234
235 while (pcxt->state != AUDIO_STOP)
236 {
237 len = pcxt->stream_in->read(pcxt->stream_in, data, bufsize);
238 if (len < 0) {
239 printf("%s: error reading!\n", __FUNCTION__);
240 break;
241 }
242 if ((bufsize > 0) && (NULL != _usrData->_cb))
243 {
244 _usrData->_cb(2, data, bufsize);
245 }
246 }
247 pcxt->pid = 0;
248 if(pcxt->usrData)
249 {
250 free(pcxt->usrData);
251 pcxt->usrData = NULL;
252 }
253 free(data);
254 mbtk_audio_log("pcm pthread end-\n");
255 return NULL;
256}
257
258static void* mbtk_play_pthread(void* hdl)
259{
260 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)hdl;
261 _play_callback audio_play_cb = (_play_callback)pcxt->usrData;
262 unsigned bufsize = 0;
263 char *data = NULL;
264 int first_set = 0;
265 int ret = 0;
266 int rc;
267
268 pthread_detach(pthread_self());
269 if (NULL == hdl)
270 return NULL;
271
272 bufsize = pcxt->pcm_packet_size;
273 data = calloc(1, bufsize);
274 if (!data) {
275 fprintf(stderr, "\n%s:could not allocate %d bytes\n",__FUNCTION__,bufsize);
276 pthread_exit(NULL);
277 }
278
279 while (pcxt->state != AUDIO_STOP && 0 != pcxt->pipe_data)
280 {
281 ret = read(pcxt->fd[0], data, bufsize);
282 // printf("%s:read : %d bytes\n", __FUNCTION__, ret);
283 if(ret == 0) {
284 mbtk_audio_log("%s %d [%d]", __FUNCTION__, __LINE__, ret);
285 continue;
286 }
287 if(ret < 0) {
288 mbtk_audio_log("%s %d [%d]", __FUNCTION__, __LINE__, ret);
289 break;
290 }
291 if ((0 == first_set || AUDIO_RESUME == pcxt->state))
292 {
293 first_set = 1;
294 mbtk_audio_set_status(hdl, AUDIO_RUNNING);
295 }
296
297 pthread_mutex_lock(&pcxt->_stream_mutex);
298 pcxt->pipe_data -= ret;
299 pthread_mutex_unlock(&pcxt->_stream_mutex);
300 if(pcxt->pipe_data < 0)
301 pcxt->pipe_data = 0;
302 if(ret < pcxt->pcm_packet_size)
303 printf("pcm %d - %d\n", pcxt->pipe_data, ret);
304
305 rc = pcxt->stream_out->write(pcxt->stream_out, data, ret);
306 if (rc < 0) {
307 printf("%s: error writing (child).\n", __FUNCTION__);
308 break;
309 } else if (rc < (signed int)pcxt->pcm_packet_size) {
310 printf("%s: wrote less than buffer size, rc=%d.\n", __FUNCTION__, rc);
311 break;
312 }
313 }
314
315 if (pcxt->fd[0] != 0 && pcxt->fd[1] != 0)
316 {
317 close(pcxt->fd[0]);
318 close(pcxt->fd[1]);
319 pcxt->fd[0] = 0;
320 pcxt->fd[1] = 0;
321 /* printf("close pcxt->fd!\n"); */
322 }
323 if (audio_play_cb)
324 audio_play_cb(pcxt, 5);
325 pcxt->pid = 0;
326// mbtk_audio_set_status(hdl, AUDIO_STOP);
327 mbtk_audio_set_status(hdl, AUDIO_OPEN);
328 free(data);
329 mbtk_audio_log("\n%s:exit!\n", __FUNCTION__);
330 pthread_exit(NULL);
331
332 return NULL;
333}
334
335static int audio_init_play_pthread(void* hdl)
336{
337 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)hdl;
338 _play_callback audio_play_cb = (_play_callback)pcxt->usrData;
339 int ret;
340
341 if (pcxt->fd[0] == 0 && pcxt->fd[1] == 0) {
342 if(pipe(pcxt->fd) == 0) {
343
344 pcxt->pipe_data = 0;
345 fcntl(pcxt->fd[0], F_SETFL, O_NONBLOCK);
346 fcntl(pcxt->fd[1], F_SETFL, O_NONBLOCK);
347 } else {
348 fprintf(stderr, "\n%d: create pipe error\n", __LINE__);
349 return -1;
350 }
351 }
352 if (pcxt->pid == 0) {
353 if (audio_play_cb)
354 audio_play_cb(pcxt, 0);
355 mbtk_audio_set_status(pcxt, AUDIO_RUNNING);
356 ret = pthread_create(&pcxt->pid, NULL, mbtk_play_pthread, hdl);
357 if (ret != 0)
358 {
359 fprintf(stderr, "\n%s: Failed create pthread\n",__FUNCTION__);
360 return ret;
361 }
362 }
363
364 return 0;
365}
366
367int mbtk_audio_play_wait_end(void* hdl)
368{
369 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)hdl;
370
371 if (NULL == hdl)
372 {
373 fprintf(stderr, "\n%s: intput invalid params\n",__FUNCTION__);
374 return -1;
375 }
376
377 if(pcxt->pid != 0)
378 {
379 do{
380 usleep(10000);
381 }
382 while(pcxt->state != AUDIO_STOP);
383 pcxt->pid = 0;
384 }
385
386 return 0;
387}
388
389static int audio_open_pcm(void *dev_hdl, int num_channels, int rate, int in_out)
390{
391 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)dev_hdl;
392 int nb_wb;
393
394 //Support 8k/16k & mono wave file
395 if (((rate != 8000) && (rate != 16000))
396 || (num_channels != 1) ) {
397 printf("%s: error wave file:rate = %d, num_channels = %d!! \n",
398 __FUNCTION__,rate, num_channels);
399 return -1;
400 }
401
402 printf("%s: success open, rate = %d, num_channels = %d.\n",
403 __FUNCTION__, rate, num_channels);
404
405 if ((8000 == rate) && (1 == num_channels)) {
406 nb_wb = 0;//NB
407 pcxt->pcm_packet_size = PCM_NB_BUF_SIZE;
408 } else if ((16000 == rate) && (1 == num_channels)) {
409 nb_wb = 1;//WB
410 pcxt->pcm_packet_size = PCM_WB_BUF_SIZE;
411 }
412
413 //config playback parameters.
414 config_parameters(in_out, nb_wb);
415 pcxt->device = in_out;
416 return 0;
417}
418
419mbtk_audio_handle mbtk_audio_open(mbtk_audio_dev_enum dev, int flag, int rate, void *usrData)
420{
421 int value = 1;
422 struct mopen_audio_t *aud_hdl = NULL;
423 int ret;
424
425 // if (dev <= AUDIO_NULL || dev >= AUDIO_MAX)
426 // {
427 // printf("invaild PCM dev\n");
428 // return NULL;
429 // }
430 if(internal_hdl)
431 {
432 printf("Audio device inited\n");
433 return internal_hdl;
434 }
435 aud_hdl = (struct mopen_audio_t *) calloc(1, sizeof(struct mopen_audio_t));
436 if (!aud_hdl)
437 {
438 fprintf(stderr, "\n%s:Failed to allocate audio hdl!, errno=%d\n", __FUNCTION__, errno);
439 return NULL;
440 }
441 memset(aud_hdl, 0, sizeof(struct mopen_audio_t));
442
443 //init global variables
444 aud_hdl->audio_ahw_dev_ubus = audio_hal_install();
445 if (aud_hdl->audio_ahw_dev_ubus == NULL) {
446 printf("%s: audio_hal_install failed!\n", __FUNCTION__);
447 goto error;
448 }
449
450 if(1 == dev)
451 {
452 //send the command of "AUDIOSTUB_PCMCTL" and "AUDIOSTUB_DTMFDETECTIONCTL" to simulate telephone offhook.
453 // ASR Question #80497 Using it causes the recording to crash
454 // simulateOffhook(aud_hdl, 1);
455 //config playback parameters.
456 config_parameters(0, 0);
457 }
458 ret = audio_open_pcm(aud_hdl, flag, rate, dev);
459 if (ret)
460 {
461 printf("\n%s: pcm open error, errno=%d\n", __FUNCTION__, errno);
462 goto error;
463 }
464 if(1 == dev)
465 {
466 //open the audiostub_ctl, prepare for record and playback
467 VCMInit();
468 //open record stream
469 ret = aud_hdl->audio_ahw_dev_ubus->open_input_stream(aud_hdl->audio_ahw_dev_ubus, 0,
470 aud_hdl->audio_ahw_dev_ubus->get_supported_devices(aud_hdl->audio_ahw_dev_ubus),
471 NULL, &aud_hdl->stream_in, 0, 0, AUDIO_SOURCE_VOICE_CALL);
472 }
473 else
474 {
475 ret = aud_hdl->audio_ahw_dev_ubus->open_output_stream(aud_hdl->audio_ahw_dev_ubus, 0,
476 aud_hdl->audio_ahw_dev_ubus->get_supported_devices(aud_hdl->audio_ahw_dev_ubus),
477 AUDIO_OUTPUT_FLAG_DIRECT, NULL, &aud_hdl->stream_out, 0);
478 }
479
480 if (ret < 0) {
481 printf("%s: error opening output device. rc = %d\n", __FUNCTION__, ret);
482 goto error;
483 }
484 pthread_mutex_init(&aud_hdl->_cond_mutex, NULL);
485 pthread_mutex_init(&aud_hdl->_stream_mutex, NULL);
486 aud_hdl->usrData = usrData;
487 aud_hdl->state = AUDIO_OPEN;
488 /* printf("Mbtk_Audio_Open aud_hdl[%x][%x][%x]\n", aud_hdl, aud_hdl->_mixer_ctl, aud_hdl->_pcm); */
489 internal_hdl = aud_hdl;
490
491 return (void *)aud_hdl;
492
493error:
494 value = 0;
495 free(aud_hdl);
496 return NULL;
497}
498
499
500int mbtk_audio_play_stream_old(void *dev_hdl, const void *pData, int len)
501{
502 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)dev_hdl;
503
504 if (NULL == pcxt || NULL == internal_hdl)
505 return -1;
506
507 if (len > 1024) {
508 printf("audio play stream max size ( < 1024): %d\n", len);
509 return -2;
510 }
511
512 if (pcxt->state == AUDIO_STOP) {
513 return 0;
514 }
515 audio_init_play_pthread(pcxt);
516
517 pthread_mutex_lock(&pcxt->_stream_mutex);
518 pcxt->pipe_data += len;
519 pthread_mutex_unlock(&pcxt->_stream_mutex);
520 while(pcxt->state != AUDIO_STOP && (pcxt->pipe_data > 40960 || pcxt->fd[1] < 0 || pcxt->fd[1] == 0)) {
521 // printf("%s:wait %d %d\n", __FUNCTION__, pcxt->pipe_data, pcxt->fd[1]);
522 usleep(50000);
523 }
524
525 if(pcxt->fd[1] > 0) {
526 if (len != write(pcxt->fd[1], pData, len)) {
527 fprintf(stderr, "\n%s: pcm_write failed [%d %d]\n", __FUNCTION__, pcxt->fd[1], errno);
528 return -errno;
529 }
530 }
531
532 return 0;
533}
534
535int mbtk_audio_play_stream(void *dev_hdl, const void *pData, int len)
536{
537// printf("%s,--len:%d\n", __func__, len);
538 unsigned bufsize = 0;
539 char *data = NULL;
540 int first_set = 0;
541 int res = 0;
542 int ret = 0;
543 int read_size = 0;
544 char *p = (char *)pData;
545
546 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)dev_hdl;
547
548 if (NULL == dev_hdl || NULL == internal_hdl || pData == NULL)
549 return -1;
550
551 if(AUDIO_RUNNING == pcxt->state)
552 return -2;
553
554 bufsize = pcxt->pcm_packet_size;
555 data = calloc(1, bufsize);
556 if (!data) {
557 fprintf(stderr, "\n%s:could not allocate %d bytes\n",__FUNCTION__,bufsize);
558 pthread_exit(NULL);
559 }
560
561 mbtk_audio_set_status(dev_hdl, AUDIO_RUNNING);
562// if(bufsize > len )
563// {
564// bufsize = len;
565// }
566
567 while (pcxt->state != AUDIO_STOP)
568 {
569
570 memcpy(data,p+read_size, bufsize );
571 read_size += bufsize;
572
573 if(read_size > len)
574 {
575 // printf(">[%d]\n", read_size);
576 break;
577 }
578
579 while(AUDIO_PAUSE == pcxt->state)
580 {
581 usleep(80000);
582 }
583
584 if ((0 == first_set || AUDIO_RESUME == pcxt->state))
585 {
586 first_set = 1;
587 mbtk_audio_set_status(dev_hdl, AUDIO_RUNNING);
588 }
589
590 ret = pcxt->stream_out->write(pcxt->stream_out, data, bufsize);
591 if (ret < 0) {
592 printf("%s: error writing (child).\n", __FUNCTION__);
593 break;
594 } else if (ret < (signed int)pcxt->pcm_packet_size) {
595 printf("%s: wrote less than buffer size, rc=%d.\n", __FUNCTION__, ret);
596 break;
597 }
598
599 if(read_size == len)
600 {
601 // printf("=[%d]", read_size);
602 break;
603 }
604
605 }
606
607 mbtk_audio_set_status(dev_hdl, AUDIO_OPEN);
608 free(data);
609 return 0;
610
611}
612
613
614int mbtk_audio_play_file(void *dev_hdl, int file_fd, int offset)
615{
616 unsigned bufsize = 0;
617 char *data = NULL;
618 int first_set = 0;
619 int file_data_sz = 0;
620 int res = 0;
621 int ret;
622
623 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)dev_hdl;
624
625 if (NULL == dev_hdl || NULL == internal_hdl)
626 return -1;
627
628 if(AUDIO_RUNNING == pcxt->state)
629 return -2;
630
631 file_data_sz = mbtk_wav_pcm16Le_check(file_fd);
632
633 bufsize = pcxt->pcm_packet_size;
634 data = calloc(1, bufsize);
635 if (!data) {
636 fprintf(stderr, "\n%s:could not allocate %d bytes\n",__FUNCTION__,bufsize);
637 pthread_exit(NULL);
638 }
639 if(offset)
640 {
641 lseek(file_fd, offset, SEEK_SET);
642 }
643
644 mbtk_audio_set_status(dev_hdl, AUDIO_RUNNING);
645 int all_size = 0;
646
647 while (pcxt->state != AUDIO_STOP)
648 {
649 res = read(file_fd, data, bufsize);
650 // printf("%s:read : %d bytes\n", __FUNCTION__, res);
651 if(res == 0 || res < 0)
652 {
653 // printf("[%d]", res);
654 break;
655 }
656
657 all_size += res;
658 if (file_data_sz < all_size || file_data_sz == all_size) {
659 printf("aplay size :%d - %d\n", file_data_sz, all_size);
660 break;
661 }
662
663 while(AUDIO_PAUSE == pcxt->state)
664 {
665 usleep(80000);
666 }
667
668 if ((0 == first_set || AUDIO_RESUME == pcxt->state))
669 {
670 first_set = 1;
671 mbtk_audio_set_status(dev_hdl, AUDIO_RUNNING);
672 }
673
674 ret = pcxt->stream_out->write(pcxt->stream_out, data, res);
675 if (ret < 0) {
676 printf("%s: error writing (child).\n", __FUNCTION__);
677 break;
678 } else if (ret < (signed int)pcxt->pcm_packet_size) {
679 printf("%s: wrote less than buffer size, rc=%d.\n", __FUNCTION__, ret);
680 break;
681 }
682 }
683
684 mbtk_audio_set_status(dev_hdl, AUDIO_OPEN);
685 free(data);
686
687 return 0;
688}
689
690int mbtk_audio_record(void *dev_hdl, mbtk_audio_record_cb_func cb_func, void *cb_data)
691{
692 struct mopen_audio_t *pcxt = (struct mopen_audio_t *)dev_hdl;
693 int res = -1;
694 struct record_cb_s *_usrData = NULL;
695
696 if (NULL == pcxt || NULL == internal_hdl || NULL == cb_func)
697 return -1;
698
699 if(AUDIO_RUNNING == pcxt->state)
700 return -2;
701
702 _usrData = malloc(sizeof(struct record_cb_s));
703 _usrData->_cb = cb_func;
704 _usrData->cb_data = cb_data;
705 pcxt->usrData = (void *)_usrData;
706 res = pthread_create(&pcxt->pid, NULL, mbtk_record_pthread, dev_hdl);
707 if (res != 0)
708 {
709 if(pcxt->usrData)
710 {
711 free(pcxt->usrData);
712 pcxt->usrData = NULL;
713 }
714 fprintf(stderr, "\n%s: Failed to create pthread\n", __FUNCTION__);
715 }
716 // 防止重复录音
717 usleep(500);
718
719 return res;
720}
721
722int mbtk_audio_close(void *dev_hdl)
723{
724 printf("mbtk_audio_close()\n");
725 int value = 0;
726 struct mopen_audio_t *_hdl = (struct mopen_audio_t *)dev_hdl;
727
728 if (NULL == _hdl || NULL == internal_hdl )
729 {
730 printf("mbtk_audio_close() fail dev_hdl is NULL\n");
731 return -1;
732 }
733
734 mbtk_audio_set_status(_hdl, AUDIO_STOP);
735 if(0 == _hdl->device) {
736 while (_hdl->pid != 0) {
737 usleep(10000);
738 }
739
740 vcm_playback_drain(0);//wait for drain the AP audiostub queue.
741 usleep(80000);//delay 80ms until DSP play out its buffered data.
742 _hdl->stream_out->common.standby(&_hdl->stream_out->common);
743 _hdl->audio_ahw_dev_ubus->close_output_stream(_hdl->audio_ahw_dev_ubus, _hdl->stream_out);
744 } else {
745
746 while (_hdl->pid != 0) {
747 sleep(1);
748 }
749 _hdl->stream_in->common.standby(&_hdl->stream_in->common);
750 _hdl->audio_ahw_dev_ubus->close_input_stream(_hdl->audio_ahw_dev_ubus, _hdl->stream_in);
751 VCMDeinit();//close the fd of audiostub_ctl when exit the thread.
752 }
753
754 audio_hal_uninstall();
755 pthread_mutex_destroy(&_hdl->_cond_mutex);
756 pthread_mutex_destroy(&_hdl->_stream_mutex);
757 free(_hdl);
758 _hdl = NULL;
759 internal_hdl = NULL;
760
761 return 0;
762}
763
764int mbtk_audio_pause(void* dev_hdl)
765{
766 // struct pcm *_pcm = ((struct mopen_audio_t *)dev_hdl)->_pcm;
767
768 if (NULL == dev_hdl || NULL == internal_hdl)
769 return -1;
770
771 if (((struct mopen_audio_t *)dev_hdl)->state != AUDIO_RUNNING)
772 {
773 return -1;
774 }
775
776 // if (ioctl(_pcm->fd, SNDRV_PCM_IOCTL_PAUSE, 1))
777 // {
778 // printf("\n%s: cannot pause channel: errno =%d\n",__FUNCTION__,-errno);
779 // return -errno;
780 // }
781 mbtk_audio_set_status(dev_hdl, AUDIO_PAUSE);
782 return 0;
783}
784
785int mbtk_audio_resume(void* dev_hdl)
786{
787 if (NULL == dev_hdl || NULL == internal_hdl)
788 return -1;
789
790 if (((struct mopen_audio_t *)dev_hdl)->state != AUDIO_PAUSE)
791 {
792 return -1;
793 }
794
795 // if (ioctl(_pcm->fd, SNDRV_PCM_IOCTL_PAUSE, 0))
796 // {
797 // printf("\n%s: cannot Resume channel: errno =%d\n", __FUNCTION__, -errno);
798 // return -errno;
799 // }
800 mbtk_audio_set_status(dev_hdl, AUDIO_RESUME);
801 return 0;
802}
803
804int mbtk_audio_stop(void* dev_hdl)
805{
806 struct mopen_audio_t *_hdl = (struct mopen_audio_t *)dev_hdl;
807
808 if (NULL == dev_hdl || NULL == internal_hdl)
809 return -1;
810
811 // if (ioctl(_hdl->_pcm->fd, SNDRV_PCM_IOCTL_DROP))
812 // {
813 // printf("\n%s: cannot Resume channel: errno =%d\n",__FUNCTION__,-errno);
814 // return -errno;
815 // }
816
817 mbtk_audio_set_status(dev_hdl, AUDIO_STOP);
818 _hdl->pid = 0;
819
820 return 0;
821}
822
823mbtk_audio_state_enum mbtk_audio_state_get(void *hdl)
824{
825 return ((struct mopen_audio_t *)hdl)->state;
826}