mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-02-21 01:42:18 +00:00
reworked shortcircuit audio code.
This commit is contained in:
parent
b15e5cfee7
commit
850d7b42d7
263
audio_alsa.c
Normal file
263
audio_alsa.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
Copyright (C) 2012 Paul Gardner-Stephen
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include "serval.h"
|
||||
|
||||
#ifndef ANDROID
|
||||
#define ALSA_LIB_PATH "/lib/libasound.so.2"
|
||||
#else
|
||||
// XXX Verify on a SGS2 ?
|
||||
#define ALSA_LIB_PATH "/system/lib/libasound.so.2"
|
||||
#endif
|
||||
|
||||
/*
|
||||
For Android systems we have the fun that this binary (not just the source code)
|
||||
needs to be able to run on systems that lack the alsa library.
|
||||
|
||||
This means it is time for some more dlopen() and dlsym() fun to get the
|
||||
necessary symbols we need.
|
||||
*/
|
||||
typedef struct alsa_functions {
|
||||
int (*snd_pcm_open)(snd_pcm_t **,char *,int,int);
|
||||
int (*snd_pcm_close)(snd_pcm_t *);
|
||||
int (*snd_pcm_hw_params_malloc)(snd_pcm_hw_params_t **);
|
||||
int (*snd_pcm_hw_params_any)(snd_pcm_t *,snd_pcm_hw_params_t *);
|
||||
int (*snd_pcm_hw_params_set_access)(snd_pcm_t *,snd_pcm_hw_params_t *,int);
|
||||
int (*snd_pcm_hw_params_set_format)(snd_pcm_t *,snd_pcm_hw_params_t *,int);
|
||||
int (*snd_pcm_hw_params_set_rate_near)(snd_pcm_t *,snd_pcm_hw_params_t *,int,int);
|
||||
int (*snd_pcm_hw_params_set_channels)(snd_pcm_t *,snd_pcm_hw_params_t *,int);
|
||||
int (*snd_pcm_hw_params)(snd_pcm_t *,snd_pcm_hw_params_t *);
|
||||
void (*snd_pcm_hw_params_free)(snd_pcm_hw_params_t *);
|
||||
int (*snd_pcm_prepare)(snd_pcm_t *);
|
||||
int (*snd_pcm_writei)(snd_pcm_t *,short *,int);
|
||||
int (*snd_pcm_readi)(snd_pcm_t *,short *,int);
|
||||
int (*snd_pcm_poll_descriptors)(snd_pcm_t *,struct pollfd *,unsigned int);
|
||||
} alsa_functions;
|
||||
|
||||
#define S(X) #X
|
||||
#define GETSYM(X) {a->X = dlsym(h,S(X)); if (!a->X) { dlclose(h); free(a); return -1; }}
|
||||
|
||||
alsa_functions *alsa = NULL;
|
||||
|
||||
int alsa_load()
|
||||
{
|
||||
void *h = dlopen(ALSA_LIB_PATH,RTLD_LAZY);
|
||||
if (!h) return -1;
|
||||
alsa_functions *a=calloc(sizeof(alsa_functions),1);
|
||||
GETSYM(snd_pcm_open);
|
||||
GETSYM(snd_pcm_hw_params_malloc);
|
||||
GETSYM(snd_pcm_hw_params_any);
|
||||
GETSYM(snd_pcm_hw_params_set_access);
|
||||
GETSYM(snd_pcm_hw_params_set_format);
|
||||
GETSYM(snd_pcm_hw_params_set_rate_near);
|
||||
GETSYM(snd_pcm_hw_params_set_channels);
|
||||
GETSYM(snd_pcm_hw_params);
|
||||
GETSYM(snd_pcm_hw_params_free);
|
||||
GETSYM(snd_pcm_writei);
|
||||
GETSYM(snd_pcm_readi);
|
||||
GETSYM(snd_pcm_close);
|
||||
GETSYM(snd_pcm_poll_descriptors);
|
||||
alsa=a;
|
||||
dlclose(h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int alsa_handles_initialised=0;
|
||||
snd_pcm_t *play_handle;
|
||||
snd_pcm_t *record_handle;
|
||||
snd_pcm_hw_params_t *play_params;
|
||||
snd_pcm_hw_params_t *record_params;
|
||||
|
||||
int audio_alsa_stop_play()
|
||||
{
|
||||
if (!alsa) return 0;
|
||||
alsa->snd_pcm_hw_params_free(play_params); play_params=NULL;
|
||||
alsa->snd_pcm_close(play_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_alsa_stop_record()
|
||||
{
|
||||
if (!alsa) return 0;
|
||||
alsa->snd_pcm_hw_params_free(record_params); record_params=NULL;
|
||||
alsa->snd_pcm_close(record_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_alsa_start_play()
|
||||
{
|
||||
int r;
|
||||
|
||||
/* if already playing, then return. */
|
||||
if (alsa_handles_initialised) return 0;
|
||||
|
||||
if (!alsa) return -1;
|
||||
record_handle=NULL; play_handle=NULL;
|
||||
record_params=NULL; play_params=NULL;
|
||||
|
||||
/* Open playback device */
|
||||
r = alsa->snd_pcm_open (&play_handle,"default",SND_PCM_STREAM_PLAYBACK,
|
||||
SND_PCM_NONBLOCK);
|
||||
if (r) { WHYF("ALSA pcm_open() failed"); goto error; }
|
||||
|
||||
/* Configure playback device for 8000Hz, 16 bit, mono */
|
||||
r=alsa->snd_pcm_hw_params_malloc(&play_params);
|
||||
if (r) { WHYF("ALSA hw_params_malloc() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_any(play_handle,play_params);
|
||||
if (r) { WHYF("ALSA hw_params_any() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_set_access(play_handle,play_params,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (r) { WHYF("ALSA hw_params_set_access() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_set_format(play_handle,play_params,
|
||||
SND_PCM_FORMAT_S16_LE);
|
||||
if (r) { WHYF("ALSA hw_params_set_format() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_set_rate_near(play_handle,play_params,8000,0);
|
||||
if (r) { WHYF("ALSA hw_params_set_rate_near() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_set_channels(play_handle,play_params,1);
|
||||
if (r) { WHYF("ALSA hw_params_set_channels() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params(play_handle,play_params);
|
||||
if (r) { WHYF("ALSA snd_pcm_hw_params() failed"); goto error; }
|
||||
alsa->snd_pcm_hw_params_free(play_params); play_params=NULL;
|
||||
|
||||
r=alsa->snd_pcm_prepare(play_handle);
|
||||
if (r) { WHYF("ALSA snd_pcm_prepare() failed"); goto error; }
|
||||
|
||||
WHY("Playback device configured");
|
||||
|
||||
error:
|
||||
/* close handles and generally cleanup after ourselves */
|
||||
audio_alsa_stop_play();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int audio_alsa_start_record()
|
||||
{
|
||||
/* Open recording device non-blocking */
|
||||
int r = alsa->snd_pcm_open (&record_handle,"default",SND_PCM_STREAM_CAPTURE,
|
||||
SND_PCM_NONBLOCK);
|
||||
if (r) { WHYF("ALSA pcm_open() failed"); goto error; }
|
||||
|
||||
/* Configure playback device for 8000Hz, 16 bit, mono */
|
||||
r=alsa->snd_pcm_hw_params_malloc(&record_params);
|
||||
if (r) { WHYF("ALSA hw_params_malloc() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_any(record_handle,record_params);
|
||||
if (r) { WHYF("ALSA hw_params_any() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_set_access(record_handle,record_params,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (r) { WHYF("ALSA hw_params_set_access() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_set_format(record_handle,record_params,
|
||||
SND_PCM_FORMAT_S16_LE);
|
||||
if (r) { WHYF("ALSA hw_params_set_format() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_set_rate_near(record_handle,record_params,8000,0);
|
||||
if (r) { WHYF("ALSA hw_params_set_rate_near() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params_set_channels(record_handle,record_params,1);
|
||||
if (r) { WHYF("ALSA hw_params_set_channels() failed"); goto error; }
|
||||
r=alsa->snd_pcm_hw_params(record_handle,record_params);
|
||||
if (r) { WHYF("ALSA snd_pcm_hw_params() failed"); goto error; }
|
||||
alsa->snd_pcm_hw_params_free(record_params); record_params=NULL;
|
||||
|
||||
r=alsa->snd_pcm_prepare(record_handle);
|
||||
if (r) { WHYF("ALSA snd_pcm_prepare() failed"); goto error; }
|
||||
|
||||
WHY("Record device configured");
|
||||
return 0;
|
||||
|
||||
error:
|
||||
/* close handles and generally cleanup after ourselves */
|
||||
audio_alsa_stop_record();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int audio_alsa_stop()
|
||||
{
|
||||
audio_alsa_stop_play();
|
||||
audio_alsa_stop_record();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_alsa_start()
|
||||
{
|
||||
if (audio_alsa_start_play()) return -1;
|
||||
if (audio_alsa_start_record()) {
|
||||
audio_alsa_stop();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_alsa_pollfds(struct pollfd *fds,int slots)
|
||||
{
|
||||
int used_play
|
||||
=alsa->snd_pcm_poll_descriptors(play_handle,fds,slots);
|
||||
int used_record
|
||||
=alsa->snd_pcm_poll_descriptors(record_handle,&fds[used_play],slots);
|
||||
return used_play+used_record;
|
||||
}
|
||||
|
||||
int audio_alsa_read(unsigned char *buffer,int maximum_bytes)
|
||||
{
|
||||
int frames_read=0;
|
||||
if ((frames_read=
|
||||
alsa->snd_pcm_readi(record_handle, (short *)buffer, maximum_bytes/2))<0)
|
||||
{
|
||||
alsa->snd_pcm_prepare(record_handle);
|
||||
frames_read
|
||||
=alsa->snd_pcm_readi(play_handle, (short *)buffer, maximum_bytes/2);
|
||||
}
|
||||
return frames_read*2;
|
||||
}
|
||||
|
||||
int audio_alsa_write(unsigned char *buffer,int bytes)
|
||||
{
|
||||
/* 16 bits per sample, so frames = bytes/2 */
|
||||
int frames_written=0;
|
||||
if ((frames_written=alsa->snd_pcm_writei(play_handle, (short *)buffer, bytes/2))<0)
|
||||
{
|
||||
alsa->snd_pcm_prepare(play_handle);
|
||||
return alsa->snd_pcm_writei(play_handle, (short *)buffer, bytes/2)*2;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
monitor_audio *audio_alsa_detect()
|
||||
{
|
||||
if (!alsa) alsa_load();
|
||||
if (!alsa) return NULL;
|
||||
|
||||
int r;
|
||||
snd_pcm_t *handle;
|
||||
if ((r = alsa->snd_pcm_open (&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)
|
||||
return NULL;
|
||||
alsa->snd_pcm_close(handle);
|
||||
|
||||
monitor_audio *au=calloc(sizeof(monitor_audio),1);
|
||||
strcpy(au->name,"ALSA compatible");
|
||||
au->start=audio_alsa_start;
|
||||
au->stop=audio_alsa_stop;
|
||||
au->poll_fds=audio_alsa_pollfds;
|
||||
au->read=audio_alsa_read;
|
||||
au->write=audio_alsa_write;
|
||||
return au;
|
||||
}
|
@ -31,6 +31,7 @@ extern int recordFd;
|
||||
extern int playBufferSize;
|
||||
extern int recordBufferSize;
|
||||
|
||||
#include "serval.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -239,21 +240,6 @@ set_volume_rpc (uint32_t device, uint32_t method, uint32_t volume)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* See if we can query end-points for this device.
|
||||
If so, assume we have detected it.
|
||||
*/
|
||||
char *audio_msm_g1_detect()
|
||||
{
|
||||
int fd = open ("/dev/msm_snd", O_RDWR);
|
||||
if (fd<0) return NULL;
|
||||
int endpoints=0;
|
||||
int rc =ioctl(fd,SND_GET_NUM_ENDPOINTS,&endpoints);
|
||||
close(fd);
|
||||
if (rc>0) return "G1/IDEOS style MSM audio";
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
/* Prepare audio path, volume etc, and then open play and
|
||||
record file descriptors.
|
||||
*/
|
||||
@ -265,7 +251,7 @@ int audio_msm_g1_start_play()
|
||||
|
||||
/* Look through endpoints for the regular in-call endpoint */
|
||||
int endpoints=0;
|
||||
int rc =ioctl(fd,SND_GET_NUM_ENDPOINTS,&endpoints);
|
||||
ioctl(fd,SND_GET_NUM_ENDPOINTS,&endpoints);
|
||||
int endpoint=-1;
|
||||
int i;
|
||||
for(i=0;i<endpoints;i++) {
|
||||
@ -394,3 +380,68 @@ int audio_msm_g1_start()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_msm_g1_poll_fds(struct pollfd *fds,int slots)
|
||||
{
|
||||
int count=0;
|
||||
if (playFd>-1&&slots>0) {
|
||||
fds[count].fd=playFd;
|
||||
fds[count].events=POLL_IN;
|
||||
count++; slots--;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int audio_msm_g1_read(unsigned char *buffer,int maximum_count)
|
||||
{
|
||||
/* Regardless of the maximum, we must read exactly buffer sized pieces
|
||||
on this audio device */
|
||||
if (maximum_count<recordBufferSize) {
|
||||
return WHY("Supplied buffer has no space for sample quanta");
|
||||
}
|
||||
int b=read(recordFd,&buffer[0],recordBufferSize);
|
||||
return b;
|
||||
}
|
||||
|
||||
int playBufferBytes=0;
|
||||
unsigned char playBuffer[65536];
|
||||
int audio_msm_g1_write(unsigned char *data,int bytes)
|
||||
{
|
||||
if (bytes+playBufferBytes>65536)
|
||||
{ WHY("Play marshalling buffer full");
|
||||
return 0; }
|
||||
bcopy(&data[0],&playBuffer[playBufferBytes],bytes);
|
||||
playBufferBytes+=bytes;
|
||||
int i;
|
||||
for(i=0;i<playBufferBytes;i+=playBufferSize)
|
||||
{
|
||||
if (write(playFd,&playBuffer[i],playBufferSize)<
|
||||
playBufferSize)
|
||||
break;
|
||||
}
|
||||
bcopy(&playBuffer[i],&playBuffer[0],playBufferBytes-i);
|
||||
playBufferBytes-=i;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* See if we can query end-points for this device.
|
||||
If so, assume we have detected it.
|
||||
*/
|
||||
monitor_audio *audio_msm_g1_detect()
|
||||
{
|
||||
int fd = open ("/dev/msm_snd", O_RDWR);
|
||||
if (fd<0) return NULL;
|
||||
int endpoints=0;
|
||||
int rc =ioctl(fd,SND_GET_NUM_ENDPOINTS,&endpoints);
|
||||
close(fd);
|
||||
if (rc>0) {
|
||||
monitor_audio *au=calloc(sizeof(monitor_audio),1);
|
||||
strcpy(au->name,"G1/IDEOS style MSM audio");
|
||||
au->start=audio_msm_g1_start;
|
||||
au->stop=audio_msm_g1_stop;
|
||||
au->poll_fds=audio_msm_g1_poll_fds;
|
||||
au->read=audio_msm_g1_read;
|
||||
au->write=audio_msm_g1_write;
|
||||
return au;
|
||||
} else return NULL;
|
||||
}
|
||||
|
@ -21,8 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#define AUDIO_MSM_G1_ETC 1
|
||||
#define AUDIO_MSM_N1_ETC 2
|
||||
int detectedAudioDevice=-1;
|
||||
char *detectedAudioDeviceName=NULL;
|
||||
monitor_audio *audev=NULL;
|
||||
|
||||
int playFd=-1;
|
||||
int recordFd=-1;
|
||||
@ -31,10 +30,10 @@ int recordBufferSize=0;
|
||||
|
||||
int detectAudioDevice()
|
||||
{
|
||||
detectedAudioDeviceName=audio_msm_g1_detect();
|
||||
if (detectedAudioDeviceName) {
|
||||
detectedAudioDevice=AUDIO_MSM_G1_ETC;
|
||||
WHYF("Detected audio device '%s'",detectedAudioDeviceName);
|
||||
if (!audev) audev=audio_msm_g1_detect();
|
||||
if (!audev) audev=audio_alsa_detect();
|
||||
if (audev) {
|
||||
WHYF("Detected audio device '%s'",audev->name);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
@ -56,88 +55,29 @@ int getAudioBytes(unsigned char *buffer,
|
||||
int offset,
|
||||
int bufferSize)
|
||||
{
|
||||
switch(detectedAudioDevice) {
|
||||
/* some devices require reading a whole buffer in one go */
|
||||
case AUDIO_MSM_G1_ETC:
|
||||
{
|
||||
if (bufferSize-offset<recordBufferSize) {
|
||||
return WHY("Supplied buffer has no space for new samples");
|
||||
}
|
||||
int b=read(recordFd,&buffer[offset],recordBufferSize);
|
||||
if (b>0) offset+=b;
|
||||
return offset;
|
||||
}
|
||||
break;
|
||||
/* while others allow reading an arbitrary amount */
|
||||
default:
|
||||
{
|
||||
int b=read(recordFd,&buffer[offset],bufferSize-offset);
|
||||
if (b>0) offset+=b;
|
||||
return offset;
|
||||
}
|
||||
break;
|
||||
if (audev&&audev->write) {
|
||||
return audev->write(&buffer[offset],bufferSize-offset);
|
||||
}
|
||||
return WHYF("Reading audio for device class #%d not implemented",
|
||||
detectedAudioDevice);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* as with recording, some of the devices have a fixed buffer size that
|
||||
we must completely fill.
|
||||
*/
|
||||
int playBufferBytes=0;
|
||||
unsigned char playBuffer[65536];
|
||||
int playAudio(unsigned char *data,int bytes)
|
||||
{
|
||||
switch(detectedAudioDevice) {
|
||||
/* some devices require reading a whole buffer in one go */
|
||||
case AUDIO_MSM_G1_ETC:
|
||||
if (bytes+playBufferBytes>65536)
|
||||
return WHY("Play marshalling buffer full");
|
||||
bcopy(&data[0],&playBuffer[playBufferBytes],bytes);
|
||||
playBufferBytes+=bytes;
|
||||
int i;
|
||||
for(i=0;i<playBufferBytes;i+=playBufferSize)
|
||||
{
|
||||
if (write(playFd,&playBuffer[i],playBufferSize)<
|
||||
playBufferSize)
|
||||
break;
|
||||
}
|
||||
bcopy(&playBuffer[i],&playBuffer[0],playBufferBytes-i);
|
||||
playBufferBytes-=i;
|
||||
break;
|
||||
/* the rest we can just write() to */
|
||||
default:
|
||||
if (write(playFd,data,bytes)<bytes)
|
||||
return WHY("short write() when playing audio");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return WHYF("Playing audio for device class #%d not implemented",
|
||||
detectedAudioDevice);
|
||||
if (audev&&audev->write) return audev->write(data,bytes);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stopAudio()
|
||||
{
|
||||
switch(detectedAudioDevice) {
|
||||
case AUDIO_MSM_G1_ETC:
|
||||
return audio_msm_g1_stop();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return WHYF("Stopping audio for device class #%d not implemented",
|
||||
detectedAudioDevice);
|
||||
if (audev&&audev->stop) return audev->stop();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int startAudio()
|
||||
{
|
||||
switch(detectedAudioDevice) {
|
||||
case AUDIO_MSM_G1_ETC:
|
||||
return audio_msm_g1_start();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return WHYF("Starting audio for device class #%d not implemented",
|
||||
detectedAudioDevice);
|
||||
if (audev&&audev->start) return audev->start();
|
||||
return -1;
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
|
||||
|
||||
if (pipeAudio) {
|
||||
detectAudioDevice();
|
||||
char *name=detectedAudioDeviceName;
|
||||
char *name=audev?audev->name:NULL;
|
||||
if (!name) {
|
||||
WHY("Could not detect any audio device. Will not pipe audio.");
|
||||
pipeAudio=0;
|
||||
|
26
serval.h
26
serval.h
@ -98,6 +98,7 @@ struct in_addr {
|
||||
#include <fcntl.h>
|
||||
//FIXME #include <getopt.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
#define DEFAULT_INSTANCE_PATH "/data/data/org.servalproject/var/serval-node"
|
||||
@ -1423,24 +1424,25 @@ int monitor_call_status(vomp_call_state *call);
|
||||
int monitor_send_audio(vomp_call_state *call,overlay_mdp_frame *audio);
|
||||
extern int monitor_socket_count;
|
||||
|
||||
#define AUDIO_MSM_G1_ETC 1
|
||||
#define AUDIO_MSM_N1_ETC 2
|
||||
extern int detectedAudioDevice;
|
||||
extern char *detectedAudioDeviceName;
|
||||
|
||||
typedef struct monitor_audio {
|
||||
char name[128];
|
||||
int (*start)();
|
||||
int (*stop)();
|
||||
int (*poll_fds)(struct pollfd *,int);
|
||||
int (*read)(unsigned char *,int);
|
||||
int (*write)(unsigned char *,int);
|
||||
} monitor_audio;
|
||||
extern monitor_audio *audev;
|
||||
|
||||
monitor_audio *audio_msm_g1_detect();
|
||||
monitor_audio *audio_alsa_detect();
|
||||
int detectAudioDevice();
|
||||
int getAudioPlayFd();
|
||||
int getAudioRecordFd();
|
||||
int getAudioFd();
|
||||
int getAudioBytes(unsigned char *buffer,
|
||||
int offset,
|
||||
int bufferSize);
|
||||
int playAudio(unsigned char *data,int bytes);
|
||||
int stopAudio();
|
||||
int startAudio();
|
||||
int encodeAndDispatchRecordedAudio(int fd,int callSessionToken,
|
||||
int recordCodec,
|
||||
unsigned char *sampleData,
|
||||
int sampleBytes);
|
||||
char *audio_msm_g1_detect();
|
||||
int audio_msm_g1_start();
|
||||
int audio_msm_g1_stop();
|
||||
|
Loading…
x
Reference in New Issue
Block a user