Загрузка данных


#include <stddef.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>

#include <portaudio.h>

#include <audio_dev.h>
#include <audio_utils.h>

#define PA_THREAD_PRIORITY 9

enum pa_state {
	PA_STREAM_RUNNING,
	PA_STREAM_STOPPED,
	PA_STREAM_CLOSED
};

struct pa_strm {
	uint8_t alloc;
	uint8_t devid;
	uint8_t number_of_chan;
	uint32_t sample_format;
	int rate;

	pthread_cond_t pa_cond;
	pthread_mutex_t pa_mutex;
	pthread_t pa_thread;
	pthread_attr_t      threadAttr;
	enum pa_state state;

	PaStreamCallback *callback;
	void *user_data;

	int active;
};

#define MODOPS_PA_STREAM_COUNT 2
static struct pa_strm pa_strm_pool[MODOPS_PA_STREAM_COUNT] = {0};

//Mutex && condwait
static int pa_mutex_init(struct pa_strm *pa)
{
    pthread_mutexattr_t attr;
    int rc;

    if(pa == NULL)
        return -1;
    rc = pthread_mutexattr_init(&attr);
    if (rc != 0) {
        printf("%s Error pthread_mutexattr_init rc=%d\n",__FUNCTION__,rc);
        return rc;
    }
    rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
    if (rc != 0) {
        printf("%s Error pthread_mutexattr_settype rc=%d\n",__FUNCTION__,rc);
        return rc;
    }

    rc = pthread_mutex_init(&pa->pa_mutex, &attr);
    if (rc != 0) {
        printf("%s Error pthread_mutex_init rc=%d\n",__FUNCTION__,rc);
        return rc;
    }
    rc = pthread_mutexattr_destroy(&attr);
    if (rc != 0) {
        printf("%s Error pthread_mutexattr_destroy rc=%d\n",__FUNCTION__,rc);
        pthread_mutex_destroy(&pa->pa_mutex);
        return rc;
    }
    return 0;
}

static int pa_mutex_destroy(struct pa_strm *pa)
{
    return (pa) ? pthread_mutex_destroy(&pa->pa_mutex) : -1;
}

static void pa_cond_wait(struct pa_strm *pa_stream)
{
    if(pa_stream == NULL)
        return;
    pthread_mutex_lock(&pa_stream->pa_mutex);
    while (!pa_stream->active)
    {
        pthread_cond_wait(&pa_stream->pa_cond, &pa_stream->pa_mutex);
    }
    pthread_mutex_unlock(&pa_stream->pa_mutex);
}

static void pa_cond_signal(struct pa_strm *pa_stream)
{
    if(pa_stream == NULL)
        return;
    pthread_mutex_lock(&pa_stream->pa_mutex);
    pthread_cond_signal(&pa_stream->pa_cond);
    pthread_mutex_unlock(&pa_stream->pa_mutex);
}

static struct pa_strm *pa_str_alloc()
{
    struct pa_strm *pa_strm_ = NULL;
    for(uint8_t i=0; i < MODOPS_PA_STREAM_COUNT; i++)
    {
        if(pa_strm_pool[i].alloc == 0)
        {
            pa_strm_ = &pa_strm_pool[i];
            pa_strm_pool[i].alloc = 1;
            break;
        }
    }
    return pa_strm_;
}

static void pa_str_free(struct pa_strm *pa_strm_)
{
    if(!pa_strm_)
        return;
    for(uint8_t i=0; i < MODOPS_PA_STREAM_COUNT; i++)
    {
        if(pa_strm_pool[i].devid == pa_strm_->devid)
        {
            pa_strm_pool[i].alloc = 0;
            break;
        }
    }
}

static void pa_do_rate_conversion(struct pa_strm *pa_stream,
		struct audio_dev *audio_dev, uint8_t *buf, int inp_frames) {
	int cur_rate, out_rate;
	int audio_dev_rate = audio_dev->ad_ops->ad_ops_ioctl(audio_dev,
			ADIOCTL_GET_RATE, NULL);

	cur_rate = audio_dev->dir == AUDIO_DEV_OUTPUT
		? audio_dev_rate : pa_stream->rate;
	out_rate = audio_dev->dir == AUDIO_DEV_OUTPUT
		? pa_stream->rate : audio_dev_rate;
	if(cur_rate != out_rate)
		audio_convert_rate(cur_rate, out_rate, buf, inp_frames);
}

/* Sort out problems related to the number of channels */
static void pa_do_channel_conversion(struct pa_strm *pa_stream,
		struct audio_dev *audio_dev, uint8_t *buf, int inp_frames) {
	int cur_chan, out_chan;
	int num_of_chan = audio_dev->ad_ops->ad_ops_ioctl(audio_dev,
		audio_dev->dir == AUDIO_DEV_OUTPUT
		? ADIOCTL_OUT_SUPPORT
		: ADIOCTL_IN_SUPPORT,
		NULL);

	num_of_chan = num_of_chan & AD_STEREO_SUPPORT ? 2 : 1;

	cur_chan = audio_dev->dir == AUDIO_DEV_OUTPUT
		? pa_stream->number_of_chan : num_of_chan;
	out_chan = audio_dev->dir == AUDIO_DEV_OUTPUT
		? num_of_chan : pa_stream->number_of_chan;
        printf("stream=%p cur_chan=%d out_chan=%d\n",pa_stream,cur_chan,out_chan);
	if(cur_chan != out_chan)
		audio_convert_channels(cur_chan, out_chan, buf, inp_frames);
}