#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>

#include <alsa/asoundlib.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "hiredis/hiredis.h"
#include "cJSON.h"
//#include "Rk_wake_lock.h"

#define SAMPLE_RATE 48000
#define CHANNEL 2
#define REC_DEVICE_NAME "fake_record"
#define WRITE_DEVICE_NAME "fake_play"
#define JACK_DEVICE_NAME "fake_jack"
#define READ_FRAME  960    //(768)
#define PERIOD_SIZE (960)  //(SAMPLE_RATE/8)
#define PERIOD_counts (2) //double of delay 200ms
#define BUFFER_SIZE (PERIOD_SIZE * PERIOD_counts)
#define MUTE_TIME_THRESHOD (4)//seconds
#define MUTE_FRAME_THRESHOD (SAMPLE_RATE * MUTE_TIME_THRESHOD / READ_FRAME)//30 seconds
//#define ALSA_READ_FORMAT SND_PCM_FORMAT_S32_LE
#define ALSA_READ_FORMAT SND_PCM_FORMAT_S16_LE
#define ALSA_WRITE_FORMAT SND_PCM_FORMAT_S16_LE
#define paging_channel "volume-event-channel"
#define volume_channel "volume-value-channel"

/*
 * Select different alsa pathways based on device type.
 *  LINE_OUT: LR-Mix(fake_play)->EqDrcProcess(ladspa)->Speaker(real_playback)
 *  HEAD_SET: fake_jack -> Headset(real_playback)
 *  BLUETOOTH: device as bluetooth source.
 */
#define DEVICE_FLAG_LINE_OUT  0x01
#define DEVICE_FLAG_HEAD_SET  0x02
#define DEVICE_FLAG_BLUETOOTH 0x04

static char g_bt_mac_addr[17];
static int g_bt_is_connect;
static bool g_system_sleep = false;
static bool g_paging_state = false;
static bool sip_mute = true;
static bool sip_paging = false;
static bool DEBUG = false;
static bool reset = true;

struct timeval tv_begin, tv_end;
//gettimeofday(&tv_begin, NULL);

extern int set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t buffer_size,
                         snd_pcm_uframes_t period_size, char **msg);

void alsa_fake_device_record_open(snd_pcm_t** capture_handle,int channels,uint32_t rate)
{
    snd_pcm_hw_params_t *hw_params;
    snd_pcm_uframes_t periodSize = PERIOD_SIZE;
    snd_pcm_uframes_t bufferSize = BUFFER_SIZE;
    int dir = 0;
    int err;

    err = snd_pcm_open(capture_handle, REC_DEVICE_NAME, SND_PCM_STREAM_CAPTURE, 0);
    if (err)
    {
        printf( "Unable to open capture PCM device: \n");
        exit(1);
    }
    printf("snd_pcm_open\n");
    //err = snd_pcm_hw_params_alloca(&hw_params);

    err = snd_pcm_hw_params_malloc(&hw_params);
    if(err)
    {
        fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n",snd_strerror(err));
        exit(1);
    }
    printf("snd_pcm_hw_params_malloc\n");

    err = snd_pcm_hw_params_any(*capture_handle, hw_params);
    if(err)
    {
        fprintf(stderr, "cannot initialize hardware parameter structure (%s)\n",snd_strerror(err));
        exit(1);
    }
    printf("snd_pcm_hw_params_any!\n");

    err = snd_pcm_hw_params_set_access(*capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    // err = snd_pcm_hw_params_set_access(*capture_handle, hw_params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
    if (err)
    {
        printf("Error setting interleaved mode\n");
        exit(1);
    }
    printf("snd_pcm_hw_params_set_access!\n");

    err = snd_pcm_hw_params_set_format(*capture_handle, hw_params, ALSA_READ_FORMAT);
    if (err)
    {
        printf("Error setting format: %s\n", snd_strerror(err));
        exit(1);
    }
    printf("snd_pcm_hw_params_set_format\n");

    err = snd_pcm_hw_params_set_channels(*capture_handle, hw_params, channels);
    if (err)
    {
        printf("channels = %d\n",channels);
        printf( "Error setting channels: %s\n", snd_strerror(err));
        exit(1);
    }
    printf("channels = %d\n",channels);

    err = snd_pcm_hw_params_set_buffer_size_near(*capture_handle, hw_params, &bufferSize);
    if (err)
    {
        printf("Error setting buffer size (%ld): %s\n", bufferSize, snd_strerror(err));
        exit(1);
    }
    printf("bufferSize = %ld\n",bufferSize);

    err = snd_pcm_hw_params_set_period_size_near(*capture_handle, hw_params, &periodSize, 0);
    if (err)
    {
        printf("Error setting period time (%ld): %s\n", periodSize, snd_strerror(err));
        exit(1);
    }
    printf("periodSize = %ld\n",periodSize);

    err = snd_pcm_hw_params_set_rate_near(*capture_handle, hw_params, &rate, 0/*&dir*/);
    if (err)
    {
        printf("Error setting sampling rate (%d): %s\n", rate, snd_strerror(err));
        //goto error;
        exit(1);
    }
    printf("Rate = %d\n", rate);

    /* Write the parameters to the driver */
    err = snd_pcm_hw_params(*capture_handle, hw_params);
    if (err < 0)
    {
        printf( "Unable to set HW parameters: %s\n", snd_strerror(err));
        //goto error;
        exit(1);
    }

    err = snd_pcm_prepare(*capture_handle);

    printf("Open record device done \n");
    //set_sw_params(*capture_handle,bufferSize,periodSize,NULL);
    if(hw_params)
        snd_pcm_hw_params_free(hw_params);
}

void alsa_fake_device_write_open(snd_pcm_t** write_handle, int channels,
                                 uint32_t write_sampleRate, int device_flag)
{
    snd_pcm_hw_params_t *write_params;
    snd_pcm_uframes_t write_periodSize = PERIOD_SIZE;
    snd_pcm_uframes_t write_bufferSize = BUFFER_SIZE;
    int write_err;
    int write_dir;
    int i = 10;

retry:

    write_err = snd_pcm_open(write_handle, WRITE_DEVICE_NAME,
                                 SND_PCM_STREAM_PLAYBACK, 0);
    // }

    if (write_err) {
        usleep(100*1000);
        i --;
        if(i > 0)
            goto retry;
        printf( "Unable to open playback PCM device: \n");
        exit(1);
    }
    //printf( "interleaved mode\n");

    // snd_pcm_hw_params_alloca(&write_params);
    snd_pcm_hw_params_malloc(&write_params);
    //printf("snd_pcm_hw_params_alloca\n");

    snd_pcm_hw_params_any(*write_handle, write_params);

    write_err = snd_pcm_hw_params_set_access(*write_handle, write_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    //write_err = snd_pcm_hw_params_set_access(*write_handle,  write_params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
    if (write_err)
    {
        printf("Error setting interleaved mode\n");
        exit(1);
    }
    //printf( "interleaved mode\n");

    write_err = snd_pcm_hw_params_set_format(*write_handle, write_params, ALSA_WRITE_FORMAT);
    if (write_err)
    {
        printf("Error setting format: %s\n", snd_strerror(write_err));
        exit(1);
    }
    //printf( "format successed\n");

    write_err = snd_pcm_hw_params_set_channels(*write_handle, write_params, channels);
    if (write_err)
    {
        printf( "Error setting channels: %s\n", snd_strerror(write_err));
        exit(1);
    }
    //printf("channels = %d\n",channels);

    write_err = snd_pcm_hw_params_set_rate_near(*write_handle, write_params, &write_sampleRate, 0/*&write_dir*/);
    if (write_err)
    {
        printf("Error setting sampling rate (%d): %s\n", write_sampleRate, snd_strerror(write_err));
        exit(1);
    }
    //printf("setting sampling rate (%d)\n", write_sampleRate);

    write_err = snd_pcm_hw_params_set_buffer_size_near(*write_handle, write_params, &write_bufferSize);
    if (write_err)
    {
        printf("Error setting buffer size (%ld): %s\n", write_bufferSize, snd_strerror(write_err));
        exit(1);
    }
    //printf("write_bufferSize = %ld\n",write_bufferSize);

    write_err = snd_pcm_hw_params_set_period_size_near(*write_handle, write_params, &write_periodSize, 0);
    if (write_err)
    {
        printf("Error setting period time (%ld): %s\n", write_periodSize, snd_strerror(write_err));
        exit(1);
    }
    //printf("write_periodSize = %ld\n",write_periodSize);

#if 0
    snd_pcm_uframes_t write_final_buffer;
    write_err = snd_pcm_hw_params_get_buffer_size(write_params, &write_final_buffer);
    printf(" final buffer size %ld \n" , write_final_buffer);

    snd_pcm_uframes_t write_final_period;
    write_err = snd_pcm_hw_params_get_period_size(write_params, &write_final_period, &write_dir);
    printf(" final period size %ld \n" , write_final_period);
#endif

    /* Write the parameters to the driver */
    write_err = snd_pcm_hw_params(*write_handle, write_params);
    if (write_err < 0)
    {
        printf( "Unable to set HW parameters: %s\n", snd_strerror(write_err));
        exit(1);
    }

    write_err = snd_pcm_prepare(*write_handle);

    if(DEBUG) printf("open write device is successful\n");
    set_sw_params(*write_handle, write_bufferSize, write_periodSize, NULL);
    if(write_params)
        snd_pcm_hw_params_free(write_params);
}

int set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t buffer_size,
                  snd_pcm_uframes_t period_size, char **msg) {

    snd_pcm_sw_params_t *params;
    char buf[256];
    int err;

    //snd_pcm_sw_params_alloca(&params);
    snd_pcm_sw_params_malloc(&params);
    if ((err = snd_pcm_sw_params_current(pcm, params)) != 0) {
        snprintf(buf, sizeof(buf), "Get current params: %s", snd_strerror(err));
        //goto fail;
        exit(1);
    }

    /* start the transfer when the buffer is full (or almost full) */
    snd_pcm_uframes_t threshold = (buffer_size / period_size) * period_size;
    if ((err = snd_pcm_sw_params_set_start_threshold(pcm, params, threshold)) != 0) {
        snprintf(buf, sizeof(buf), "Set start threshold: %s: %lu", snd_strerror(err), threshold);
        exit(1);
    }

    /* allow the transfer when at least period_size samples can be processed */
    if ((err = snd_pcm_sw_params_set_avail_min(pcm, params, period_size)) != 0) {
        snprintf(buf, sizeof(buf), "Set avail min: %s: %lu", snd_strerror(err), period_size);
        exit(1);
    }

    if ((err = snd_pcm_sw_params(pcm, params)) != 0) {
        snprintf(buf, sizeof(buf), "%s", snd_strerror(err));
        exit(1);
    }
    if(params)
        snd_pcm_sw_params_free(params);

    return 0;
}

// int is_mute_frame(short *in,unsigned int size)
// {
//     int i;
//     int mute_count = 0;

//     if (!size) {
//         printf("frame size is zero!!!\n");
//         return 0;
//     }
//     for (i = 0; i < size;i ++) {
//         if(in[i] != 0)
//         return 0;
//     }

//     return 1;
// }

/* Determine whether to enter the energy saving mode according to
 * the value of the environment variable "EQ_LOW_POWERMODE"
 */
// bool low_power_mode_check()
// {
//     char *value = NULL;

//     /* env: "EQ_LOW_POWERMODE=TRUE" or "EQ_LOW_POWERMODE=true" ? */
//     value = getenv("EQ_LOW_POWERMODE");
//     if (value && (!strcmp("TRUE", value) || !strcmp("true", value)))
//         return true;

//     return false;
// }

/* Check device changing. */
// int get_device_flag()
// {
//     int fd = 0, ret = 0;
//     char buff[512] = {0};
//     int device_flag = DEVICE_FLAG_LINE_OUT;
//     const char *path = "/sys/devices/platform/ff560000.acodec/rk3308-acodec-dev/dac_output";
//     FILE *pp = NULL; /* pipeline */
//     char *bt_mac_addr = NULL;

//     if (g_bt_is_connect)
//         return DEVICE_FLAG_BLUETOOTH;

//     fd = open(path, O_RDONLY);
//     if (fd < 0) {
//         printf("Open %s failed!\n", path);
//         return device_flag;
//     }

//     ret = read(fd, buff, sizeof(buff));
//     if (ret <= 0) {
//         printf("Read %s failed!\n", path);
//         close(fd);
//         return device_flag;
//     }

//     if (strstr(buff, "hp out"))
//         device_flag = DEVICE_FLAG_HEAD_SET;

//     close(fd);

//     return device_flag;
// }

/* Get device name frome device_flag */
// const char *get_device_name(int device_flag)
// {
//     const char *device_name = NULL;

//     switch (device_flag) {
//         case DEVICE_FLAG_BLUETOOTH:
//             device_name = "BLUETOOTH";
//             break;
//         case DEVICE_FLAG_HEAD_SET:
//             device_name = JACK_DEVICE_NAME;
//             break;
//         case DEVICE_FLAG_LINE_OUT:
//             device_name = WRITE_DEVICE_NAME;
//             break;
//         default:
//             break;
//     }

//     return device_name;
// }

// void *a2dp_status_listen(void *arg)
// {
//     int ret = 0;
//     char buff[100] = {0};
//     struct sockaddr_un clientAddr;
//     struct sockaddr_un serverAddr;
//     int sockfd;
//     socklen_t addr_len;
//     char *start = NULL;
//     snd_pcm_t* audio_bt_handle;
//     char bluealsa_device[256] = {0};
//     int retry_cnt = 5;

//     sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
//     if (sockfd < 0) {
//         printf("Create socket failed!\n");
//         return NULL;
//     }

//     serverAddr.sun_family = AF_UNIX;
//     strcpy(serverAddr.sun_path, "/tmp/a2dp_master_status");

//     system("rm -rf /tmp/a2dp_master_status");
//     ret = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
//     if (ret < 0) {
//         printf("Bind Local addr failed!\n");
//         return NULL;
//     }

//     while(1) {
//         memset(buff, 0, sizeof(buff));
//         ret = recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *)&clientAddr, &addr_len);
//         if (ret <= 0)
//             break;
//         printf("###### FUCN:%s. Received a malformed message(%s)\n", __func__, buff);

//         if (strstr(buff, "status:connect")) {
//             start = strstr(buff, "address:");
//             if (start == NULL) {
//                 printf("FUCN:%s. Received a malformed message(%s)\n", __func__, buff);
//                 continue;
//             }
//             start += strlen("address:");
//             if (!g_bt_is_connect) {
// 		sleep(2);
//                 memcpy(g_bt_mac_addr, start, sizeof(g_bt_mac_addr));
//                 sprintf(bluealsa_device, "%s%s", "bluealsa:HCI=hci0,PROFILE=a2dp,DEV=",
//                         g_bt_mac_addr);
//                 retry_cnt = 5;
//                 while (retry_cnt--) {
//                     ret = snd_pcm_open(&audio_bt_handle, bluealsa_device,
//                                        SND_PCM_STREAM_PLAYBACK, 0);
//                     if (ret == 0) {
//                         snd_pcm_close(audio_bt_handle);
//                         g_bt_is_connect = 1;
//                     }
//                     usleep(600000); //600ms * 5 = 3s.
//                 }
//             }
//         } else if (strstr(buff, "status:disconnect")) {
//             g_bt_is_connect = 0;
//         } else if (strstr(buff, "status:suspend")) {
//             g_system_sleep = true;
//         } else if (strstr(buff, "status:resume")) {
//             g_system_sleep = false;
//         } else {
//             printf("FUCN:%s. Received a malformed message(%s)\n", __func__, buff);
//         }
//     }

//     close(sockfd);
//     return NULL;
// }


//Paging状态监控
void ProcessReply( redisReply * pReply )
{
    cJSON *pJson;
    redisReply * pSubReply = NULL;

    if ( pReply != NULL && pReply->elements == 3 )
    {
        pSubReply = pReply->element[2];
        // if(DEBUG)
        //     printf( "Msg [%s]\n", pSubReply->str );
        if(DEBUG) printf( "Msg [%s]\n", pSubReply->str );
        pJson =  cJSON_Parse(pSubReply->str);
        if ( pJson ) {
            if(strcmp(cJSON_GetObjectItem(pJson, "name")->valuestring, "SIP") == 0 &&
                strcmp(cJSON_GetObjectItem(pJson, "action")->valuestring, "on") == 0)
            {
                //通话
                //usleep(100*1000);
                sip_paging = true;
                if(reset)
                    g_paging_state = true;
            }
            else if(strcmp(cJSON_GetObjectItem(pJson, "name")->valuestring, "SIP") == 0 &&
                strcmp(cJSON_GetObjectItem(pJson, "action")->valuestring, "off") == 0)
            {
                //通话
                //usleep(100*1000);
                sip_paging = false;
                g_paging_state = false;
            }
        }
    }
}

void *paging_status_listen(void *arg)
{
    redisContext * pContext = redisConnect( "127.0.0.1", 6379 );

    if ( NULL == pContext || pContext->err == 1 )
    {
        printf( "%s\n", pContext->errstr );
        exit( -1 );
    }
    void* replyPtr = redisCommand( pContext, "SUBSCRIBE %s", paging_channel );
    redisReply* pReply = static_cast<redisReply*>(replyPtr);
    freeReplyObject( pReply );
    while ( redisGetReply( pContext, (void **)&pReply ) == REDIS_OK )
    {
        ProcessReply( pReply );
        freeReplyObject( pReply );
    }

    redisFree( pContext );
    return NULL;
}

//解析音量设置数据
void ProcessVolumeReply( redisReply * pReply )
{
    cJSON *pJson;
    redisReply * pSubReply = NULL;

    if ( pReply != NULL && pReply->elements == 3 )
    {
        pSubReply = pReply->element[2];
        if(DEBUG) printf( "Msg [%s]\n", pSubReply->str );
        pJson =  cJSON_Parse(pSubReply->str);
        if ( pJson ) {
            if(cJSON_GetArraySize(pJson) > 11 && cJSON_GetObjectItem(pJson, "sip_volume")->valueint != 0 && cJSON_GetObjectItem(pJson, "onvif_volume")->valueint != 0 &&
                cJSON_GetObjectItem(pJson, "broadcast_volume")->valueint != -1 && cJSON_GetObjectItem(pJson, "multicast_1_volume")->valueint != 0)
            {

                reset = true;
                return;
            }
            if(cJSON_GetObjectItem(pJson, "sip_volume"))
            {
                if(cJSON_GetObjectItem(pJson, "sip_volume")->valueint == 0)
                {
                    sip_mute == true;
                    g_paging_state = false;
                }
                else
                {
                    sip_mute == false;
                    if(sip_paging)
                        g_paging_state = true;
                }
                reset = false;
            }
            cJSON_Delete(pJson);
        }else{
            printf( "parse failed!\n");
        }
    }
}


/*
* 订阅音量信息.
*/
void *get_volume_info(void * arg)
{
    redisContext * pContext = redisConnect( "127.0.0.1", 6379 );

    if ( NULL == pContext || pContext->err == 1 )
    {
        printf( "%s\n", pContext->errstr );
        exit( -1 );
    }

    void* replyPtr = redisCommand( pContext, "SUBSCRIBE %s", volume_channel );
    redisReply* pReply = static_cast<redisReply*>(replyPtr);
    freeReplyObject( pReply );
    while ( redisGetReply( pContext, (void **)&pReply ) == REDIS_OK )
    {
        ProcessVolumeReply( pReply );
        freeReplyObject( pReply );
    }

    redisFree( pContext );
    return NULL;
}

int main(int argc, char *argv[])
{
    snd_pcm_t *capture_handle;
    snd_pcm_t *write_handle;
    int err;
    short buffer[READ_FRAME * 2];
    unsigned int sampleRate;
    unsigned int channels;
    //int mute_frame_thd;
    //int mute_frame;
    /* LINE_OUT is the default output device */
    int device_flag, new_flag;
    pthread_t paging_status_listen_thread;
    pthread_t volume_value_listen_thread;
    //struct rk_wake_lock* wake_lock;
    //bool low_power_mode = low_power_mode_check();
    char *silence_data = (char *)calloc(READ_FRAME * 2 * 2, 1);//2ch 16bit
    int mute_times;

    if(argc == 2 && strcmp(argv[1], "debug") == 0)
        DEBUG = true;

    //wake_lock = RK_wake_lock_new("eq_drc_process");

    /* Create a thread to listen for Paging connection status. */
    //pthread_create(&paging_status_listen_thread, NULL, paging_status_listen, NULL);


    /* Create a thread to listen for Volume connection status. */
    //pthread_create(&volume_value_listen_thread, NULL, get_volume_info, NULL);

repeat:
    capture_handle = NULL;
    write_handle = NULL;
    err = 0;
    memset(buffer, 0, sizeof(buffer));
    sampleRate = SAMPLE_RATE;
    channels = CHANNEL;
    //mute_frame_thd = (int)MUTE_FRAME_THRESHOD;
    //mute_frame = 0;
    /* LINE_OUT is the default output device */
    device_flag = DEVICE_FLAG_LINE_OUT;
    new_flag = DEVICE_FLAG_LINE_OUT;

    printf("\n==========EQ/DRC process release version 1.23===============\n");
    alsa_fake_device_record_open(&capture_handle, channels, sampleRate);
    alsa_fake_device_write_open(&write_handle, channels, sampleRate, device_flag);
    //RK_acquire_wake_lock(wake_lock);

    while (1) {
        err = snd_pcm_readi(capture_handle, buffer , READ_FRAME);
        if (err != READ_FRAME)
            printf("====read frame error = %d===\n",err);

        if (err < 0) {
            if (err == -EPIPE)
                printf( "Overrun occurred: %d\n", err);

            err = snd_pcm_recover(capture_handle, err, 0);
            // Still an error, need to exit.
            if (err < 0) {
                printf( "Error occured while recording: %s\n", snd_strerror(err));
                usleep(200 * 1000);
                if (capture_handle)
                    snd_pcm_close(capture_handle);
                if (write_handle)
                    snd_pcm_close(write_handle);
                goto repeat;
            }
        }

       

        // if(g_paging_state) {
        //     /* Reassign to avoid overflow */
        //     if (write_handle) {
        //         system("echo 1 > /sys/class/gpio/gpio5/value");
	    //         snd_pcm_drop(write_handle);
        //         snd_pcm_close(write_handle);
        //         //RK_release_wake_lock(wake_lock);
        //         if(DEBUG) printf("close write handle for you!!!\n ");
        //         write_handle = NULL;
        //     }
        //     continue;
        // }

        // while (write_handle == NULL) {
        //     alsa_fake_device_write_open(&write_handle, channels, sampleRate, device_flag);
        //     if (write_handle == NULL) {
        //         printf("Route change failed! Using default audio path.\n");
        //         device_flag = DEVICE_FLAG_LINE_OUT;
        //     }
		//     int i, num = PERIOD_counts / 2;
        //     for (i = 0; i < num; i++) {
        //         err = snd_pcm_writei(write_handle, silence_data, READ_FRAME);
        //         if(err != READ_FRAME)
        //             printf("====write frame error = %d, not %d\n",err, READ_FRAME);
        //     }
        //     if(!reset) system("/etc/scripts/pa_mute.sh 0 &");
        // }

        err = snd_pcm_writei(write_handle, buffer, READ_FRAME);
        if (-EPIPE == err) {
			snd_pcm_prepare(write_handle);

			err = snd_pcm_writei(write_handle, buffer, READ_FRAME);
			if (err < 0) {
				printf("alsa: write error: %s\n",
					snd_strerror((int) err));
			}
		}
		else if (err < 0) {
            printf("alsa: write error: %s\n",
                snd_strerror((int) err));
		}
		else if (err != READ_FRAME) {
			printf("alsa: write: wrote %d of %d samples\n",
				(int) err, READ_FRAME);
		}
        // if(err != READ_FRAME)
        //     printf("====write frame error = %d===\n",err);

        // if (err < 0) {
        //     if (err == -EPIPE)
        //         printf("Underrun occurred from write: %d\n", err);

        //     err = snd_pcm_recover(write_handle, err, 0);
        //     if (err < 0) {
        //         printf( "Error occured while writing: %s\n", snd_strerror(err));
        //         usleep(200 * 1000);

        //         if (write_handle) {
        //             snd_pcm_close(write_handle);
        //             write_handle = NULL;
        //         }

        //         // if (device_flag == DEVICE_FLAG_BLUETOOTH)
        //         //     g_bt_is_connect = 0;
        //     }
        // }
    }

error:
    if (capture_handle)
        snd_pcm_close(capture_handle);
    if (write_handle)
        snd_pcm_close(write_handle);

    // pthread_cancel(paging_status_listen_thread);
    // pthread_join(paging_status_listen_thread, NULL);
    // pthread_cancel(volume_value_listen_thread);
    // pthread_join(volume_value_listen_thread, NULL);

    return 0;
}
