| /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @file m_audio.c | 
 |   @brief audio API example | 
 | */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 |  | 
 | /*------------------------------------------------------------------------------------------------- | 
 |   Copyright (c) 2019 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. | 
 |   Quectel Wireless Solution Proprietary and Confidential. | 
 | -------------------------------------------------------------------------------------------------*/ | 
 |  | 
 | /*------------------------------------------------------------------------------------------------- | 
 |   EDIT HISTORY | 
 |   This section contains comments describing changes made to the file. | 
 |   Notice that changes are listed in reverse chronological order. | 
 |   $Header: $ | 
 |   when         who          what, where, why | 
 |   --------     ---          ---------------------------------------------------------- | 
 |   2021-11-03   dameng.lin      Create. | 
 | -------------------------------------------------------------------------------------------------*/ | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 | #include <unistd.h> | 
 | #include <errno.h> | 
 | #include <pthread.h> | 
 |  | 
 | #include "ql_v2/ql_type.h" | 
 | #include "ql_v2/ql_audio_pcm.h" | 
 | #include "ql_v2/ql_audio_cfg.h" | 
 | #include "ql_v2/ql_test_utils.h" | 
 |  | 
 | typedef void (*show_handler_f)(void); | 
 |  | 
 | typedef struct | 
 | { | 
 |     const char *name; | 
 |     show_handler_f handle; | 
 | }audio_show_t; | 
 |  | 
 | typedef struct | 
 | { | 
 |     int playback_dest; | 
 |     int block_flag; | 
 |     char file_name[128]; | 
 | }audio_playback_info_t; | 
 |  | 
 | static ql_audio_handle_t g_playback_handle = QL_AUDIO_INVALID_HANDLE; | 
 | static int g_playback_end = 0; | 
 |  | 
 |  | 
 | void item_ql_audio_init(void) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     printf("test ql_audio_init: "); | 
 |     ret = ql_audio_init(); | 
 |     if(QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to init audio service, ret = %d\n", ret); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("Success to init audio service\n"); | 
 |     } | 
 | } | 
 |  | 
 | static void audio_service_error_cb_func(int error) | 
 | { | 
 |     printf("===== Audio Service Abort ===== error = %d\n",error); | 
 | } | 
 |  | 
 | static void item_ql_audio_set_service_error_cb(void) | 
 | { | 
 |     int ret = QL_ERR_OK; | 
 |  | 
 |     printf("test ql_audio_set_service_error_cb: \n"); | 
 |     ret = ql_audio_set_service_error_cb(audio_service_error_cb_func); | 
 |     if(ret != QL_ERR_OK) | 
 |     { | 
 |         printf("Failed to ql_audio_set_service_error_cb, ret=%d\n", ret); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("Successful\n"); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_audio_set_loopback_enable_state(void) | 
 | { | 
 |     int ret = QL_ERR_OK; | 
 |     int loopback_enable_state = 0; | 
 |  | 
 |     printf("test ql_audio_set_loopback_enable_state: \n"); | 
 |     printf("please enter the loopback enable state(0-1): "); | 
 |     ret = t_get_int(&loopback_enable_state); | 
 |     if(ret != 0) | 
 |     { | 
 |         printf("Invalid input\n"); | 
 |         return; | 
 |     } | 
 |  | 
 |     ret = ql_audio_set_loopback_enable_state(loopback_enable_state); | 
 |     if (QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to set loopback enable state, ret = %d\n", ret); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("Success to set loopback enable state\n"); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_audio_get_loopback_enable_state(void) | 
 | { | 
 |     int ret = QL_ERR_OK; | 
 |     int32_t loopback_enable_state = 0; | 
 |  | 
 |     printf("test ql_audio_get_loopback_enable_state: \n"); | 
 |  | 
 |     ret = ql_audio_get_loopback_enable_state(&loopback_enable_state); | 
 |     if (QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to get loopback enable state, ret = %d\n", ret); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("Success to get loopback enable state, loopback_enable_state = %d\n", loopback_enable_state); | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | static void item_ql_audio_set_tx_voice_mic_gain(void) | 
 | { | 
 |     int ret = QL_ERR_OK; | 
 |     int tx_voice_mic_gain = 0; | 
 |  | 
 |     printf("test ql_audio_set_tx_voice_mic_gain: \n"); | 
 |     printf("please enter the tx voice mic gain(0-65535): "); | 
 |     ret = t_get_int(&tx_voice_mic_gain); | 
 |     if(ret != 0) | 
 |     { | 
 |         printf("Invalid input\n"); | 
 |         return; | 
 |     } | 
 |  | 
 |     ret = ql_audio_set_tx_voice_mic_gain(tx_voice_mic_gain); | 
 |     if (QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to set tx voice mic gain, ret = %d\n", ret); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("Success to set tx voice mic gain\n"); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_audio_get_tx_voice_mic_gain(void) | 
 | { | 
 |     int ret = QL_ERR_OK; | 
 |     int32_t tx_voice_mic_gain = 0; | 
 |  | 
 |     printf("test ql_audio_get_tx_voice_mic_gain: \n"); | 
 |  | 
 |     ret = ql_audio_get_tx_voice_mic_gain(&tx_voice_mic_gain); | 
 |     if (QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to get tx voice mic gain, ret = %d\n", ret); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("Success to get tx voice mic gain, tx_voice_mic_gain = %d\n", tx_voice_mic_gain); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_audio_set_codec_down_vol(void) | 
 | { | 
 |     int ret = QL_ERR_OK; | 
 |     int down_volume = 0; | 
 |  | 
 |     printf("test ql_audio_set_codec_down_vol: \n"); | 
 |     printf("please enter the codec down volume(0-100): "); | 
 |     ret = t_get_int(&down_volume); | 
 |     if(ret != 0) | 
 |     { | 
 |         printf("Invalid input\n"); | 
 |         return; | 
 |     } | 
 |  | 
 |     ret = ql_audio_set_codec_down_vol(down_volume); | 
 |     if (QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to set codec down volume, ret = %d\n", ret); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("Success to set codec down volume\n"); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_audio_get_codec_down_vol(void) | 
 | { | 
 |     int ret = QL_ERR_OK; | 
 |     int32_t down_volume = 0; | 
 |  | 
 |     printf("test ql_audio_get_codec_down_vol: \n"); | 
 |  | 
 |     ret = ql_audio_get_codec_down_vol(&down_volume); | 
 |     if (QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to get codec down volume, ret = %d\n", ret); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("Success to codec down volume, down_volume = %d\n", down_volume); | 
 |     } | 
 | } | 
 |  | 
 | void item_ql_audio_deinit(void) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     printf("test ql_audio_deinit: "); | 
 |     ret = ql_audio_deinit(); | 
 |     if(QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to deinit audio service, ret = %d\n", ret); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("Success to deinit audio service\n"); | 
 |     } | 
 | } | 
 |  | 
 | static int default_playback_state(ql_audio_handle_t handle, void *params, QL_AUDIO_PLAYBACK_STATE_E state) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     switch(state) | 
 |     { | 
 |         case QL_AUDIO_PLAYBACK_STATE_OPEN: | 
 |         { | 
 |             printf("QL_AUDIO_PLAYBACK_STATE_OPEN\n"); | 
 |             break; | 
 |         } | 
 |         case QL_AUDIO_PLAYBACK_STATE_PREPARE: | 
 |         { | 
 |             printf("QL_AUDIO_PLAYBACK_STATE_PREPARE\n"); | 
 |             break; | 
 |         } | 
 |         case QL_AUDIO_PLAYBACK_STATE_PLAYING: | 
 |         { | 
 |             printf("QL_AUDIO_PLAYBACK_STATE_PLAYING\n"); | 
 |             break; | 
 |         } | 
 |         case QL_AUDIO_PLAYBACK_STATE_FINISHED: | 
 |         { | 
 |             printf("QL_AUDIO_PLAYBACK_STATE_FINISHED\n"); | 
 |             g_playback_end = 1; | 
 |             break; | 
 |         } | 
 |         case QL_AUDIO_PLAYBACK_STATE_PAUSE: | 
 |         { | 
 |             printf("QL_AUDIO_PLAYBACK_STATE_PAUSE\n"); | 
 |             break; | 
 |         } | 
 |         case QL_AUDIO_PLAYBACK_STATE_ERROR: | 
 |         { | 
 |             printf("QL_AUDIO_PLAYBACK_STATE_ERROR\n"); | 
 |             g_playback_end = 1; | 
 |             break; | 
 |         } | 
 |         default: | 
 |         { | 
 |             printf("INVALID PALYBACK STATE\n"); | 
 |             ret = -1; | 
 |             break; | 
 |         } | 
 |     } | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | static void *ql_audio_play_file_thread(void *args) | 
 | { | 
 |     int ret = QL_ERR_OK; | 
 |     uint32_t be_dai_mask = 0; | 
 |     ql_audio_handle_t handle = QL_AUDIO_INVALID_HANDLE; | 
 |  | 
 |     audio_playback_info_t *playback_info = (audio_playback_info_t *)args; | 
 |     if (NULL == playback_info) | 
 |     { | 
 |         printf("invalid params\n"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     switch(playback_info->playback_dest) | 
 |     { | 
 |         case 0: | 
 |         { | 
 |             be_dai_mask = QL_AUDIO_BE_DAI_MASK_PLAYBACK_PRI_PCM; | 
 |             break; | 
 |         } | 
 |         case 1: | 
 |         { | 
 |             be_dai_mask = QL_AUDIO_BE_DAI_MASK_PLAYBACK_VOICE_TX; | 
 |             break; | 
 |         } | 
 |         case 2: | 
 |         { | 
 |             be_dai_mask = QL_AUDIO_BE_DAI_MASK_PLAYBACK_PRI_PCM | QL_AUDIO_BE_DAI_MASK_PLAYBACK_VOICE_TX; | 
 |             break; | 
 |         } | 
 |         default: | 
 |         { | 
 |             printf("invalid playback destination\n"); | 
 |             free(playback_info); | 
 |             playback_info = NULL; | 
 |             return NULL; | 
 |         } | 
 |     } | 
 |  | 
 |     handle = ql_audio_playback_open(QL_AUDIO_FE_PCM_DEV_MULTIMEDIA1, be_dai_mask); | 
 |     if (QL_AUDIO_INVALID_HANDLE >= handle) | 
 |     { | 
 |         printf("Failed to open playback\n"); | 
 |         free(playback_info); | 
 |         playback_info = NULL; | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     g_playback_handle = handle; | 
 |  | 
 |     printf("playback handle = %d",g_playback_handle); | 
 |     ql_audio_playback_set_block_flag(g_playback_handle, playback_info->block_flag); | 
 |  | 
 |     ret = ql_audio_playback_file_prepare(g_playback_handle, | 
 |                                          playback_info->file_name, | 
 |                                          NULL, | 
 |                                          default_playback_state, | 
 |                                          NULL); | 
 |     if (QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to prepare playback file\n"); | 
 |         free(playback_info); | 
 |         playback_info = NULL; | 
 |         ql_audio_playback_close(g_playback_handle); | 
 |         return NULL; | 
 |     } | 
 |     printf("playback handle = %d",g_playback_handle); | 
 |  | 
 | 	ret = ql_audio_playback_play(g_playback_handle); | 
 |     if (QL_ERR_OK != ret) | 
 |     { | 
 |         printf("Failed to play file\n"); | 
 |         free(playback_info); | 
 |         playback_info = NULL; | 
 |         ql_audio_playback_close(g_playback_handle); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     while(0 == g_playback_end) | 
 |     { | 
 |         usleep(100 * 1000); | 
 |     } | 
 |  | 
 |     printf("End playing file\n"); | 
 |     ql_audio_playback_close(g_playback_handle); | 
 |     g_playback_handle = QL_AUDIO_INVALID_HANDLE; | 
 |     g_playback_end = 0; | 
 |  | 
 |     free(playback_info); | 
 |     playback_info = NULL; | 
 |  | 
 |     return NULL; | 
 | } | 
 |  | 
 | static void item_ql_audio_playback_play_file(void) | 
 | { | 
 |     int ret = 0; | 
 |     pthread_t thread_id; | 
 |     pthread_attr_t thread_attr; | 
 |     audio_playback_info_t *playback_info = NULL; | 
 |  | 
 |     printf("test ql_audio_playback_play_file: \n"); | 
 |  | 
 |     playback_info = (audio_playback_info_t *)malloc(sizeof(audio_playback_info_t)); | 
 |     if (NULL == playback_info) | 
 |     { | 
 |         printf("Failed to malloc memory\n"); | 
 |         return; | 
 |     } | 
 |     memset(playback_info, 0, sizeof(audio_playback_info_t)); | 
 |  | 
 |     printf("please enter the file name: "); | 
 |     ret = t_get_string(playback_info->file_name,sizeof(playback_info->file_name)); | 
 |     if(ret != 0) | 
 |     { | 
 |         printf("Invalid input\n"); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter the playback destination(0-To pcm interface / 1-To voice / 2-To pcm interface and voice): "); | 
 |     ret = t_get_int(&(playback_info->playback_dest)); | 
 |     if(ret != 0) | 
 |     { | 
 |         printf("Invalid input\n"); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter the block flag(0-nonblock / 1-block): "); | 
 |     ret = t_get_int(&(playback_info->block_flag)); | 
 |     if(ret != 0) | 
 |     { | 
 |         printf("Invalid input\n"); | 
 |         return; | 
 |     } | 
 |  | 
 |     pthread_attr_init(&thread_attr); | 
 |     pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); | 
 |  | 
 |     ret = pthread_create(&thread_id, &thread_attr, ql_audio_play_file_thread, (void *)playback_info); | 
 |     if (0 > ret) | 
 |     { | 
 |         printf("Failed to create play file thread, ret = %d, err = %s\n", ret, strerror(errno)); | 
 |     } | 
 |  | 
 |     pthread_attr_destroy(&thread_attr); | 
 | } | 
 |  | 
 |  | 
 | static audio_show_t audio_show[] = | 
 | { | 
 |     { "ql_audio_init",                          item_ql_audio_init                         }, | 
 |     { "ql_audio_set_service_error_cb",          item_ql_audio_set_service_error_cb         }, | 
 |     { "ql_audio_set_loopback_enable_state",     item_ql_audio_set_loopback_enable_state    }, | 
 |     { "ql_audio_get_loopback_enable_state",     item_ql_audio_get_loopback_enable_state    }, | 
 |     { "ql_audio_set_tx_voice_mic_gain",         item_ql_audio_set_tx_voice_mic_gain        }, | 
 |     { "ql_audio_get_tx_voice_mic_gain",         item_ql_audio_get_tx_voice_mic_gain        }, | 
 |     { "ql_audio_set_codec_down_vol",            item_ql_audio_set_codec_down_vol           }, | 
 |     { "ql_audio_get_codec_down_vol",            item_ql_audio_get_codec_down_vol           }, | 
 |     { "ql_audio_playback_play_file",            item_ql_audio_playback_play_file           }, | 
 |     { "ql_audio_deinit",                        item_ql_audio_deinit                       } | 
 | 	 | 
 | }; | 
 |  | 
 | int audio_get_int(int *val) | 
 | { | 
 |     int dat; | 
 |     char *ptr_end = NULL; | 
 |     char buf[256] = {0}; | 
 |  | 
 |     if (NULL == val) | 
 |     {    | 
 |         return -1; | 
 |     } | 
 |  | 
 |     if (fgets(buf, sizeof(buf), stdin) == NULL) | 
 |     { | 
 |         return -1; | 
 |     } | 
 |  | 
 |     if('\0' == buf[0]) | 
 |     { | 
 |         return -1; | 
 |     } | 
 |  | 
 |     if('\n' == buf[0]) | 
 |     { | 
 |         return 1; | 
 |     } | 
 |  | 
 |     dat = strtol(buf, &ptr_end, 10);  | 
 |     if((NULL != ptr_end) && ('\n' != ptr_end[0])) | 
 |     { | 
 |         return -1; | 
 |     } | 
 |  | 
 |     *val = dat; | 
 |     return 0; | 
 | } | 
 |  | 
 | static void dump_audio_show(void) | 
 | { | 
 |     int i = 0; | 
 |  | 
 |     for(i = 0; i < sizeof(audio_show)/sizeof(audio_show[0]); i++) | 
 |     { | 
 |         printf("%d\t%s\n", i, audio_show[i].name); | 
 |     } | 
 |     printf("-1\texit\n"); | 
 | } | 
 |  | 
 |  | 
 | int main(int argc, char **argv) | 
 | { | 
 |     int ret = 0; | 
 |     int index = 0; | 
 |  | 
 |     dump_audio_show(); | 
 |  | 
 |     while (1) | 
 |     { | 
 |         printf("\n"); | 
 |         printf("Please enter your choice: "); | 
 |         ret = audio_get_int(&index); | 
 |         printf("\n"); | 
 |         if(ret < 0) | 
 |         { | 
 |             printf("Invalid input\n"); | 
 |             continue; | 
 |         } | 
 |         else if(ret == 1) | 
 |         { | 
 |             dump_audio_show(); | 
 |             continue; | 
 |         } | 
 |  | 
 |         if (index == -1) | 
 |         { | 
 |             break; | 
 |         } | 
 |  | 
 |         if ((index < 0) || (index >= sizeof(audio_show)/sizeof(audio_show[0]))) | 
 |         { | 
 |             printf("Not support index: %d\n", index); | 
 |             continue; | 
 |         } | 
 |  | 
 |         if (NULL != audio_show[index].handle) | 
 |         { | 
 |             audio_show[index].handle(); | 
 |         } | 
 |     } | 
 |  | 
 |     return 0; | 
 | } | 
 |  | 
 |  | 
 |  |