mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-29 15:43:56 +00:00
work on bypass-audio.
CALLSTATUS monitor message has gained a field, thus changing API for java side.
This commit is contained in:
parent
c29f210e91
commit
7b82ccbd7b
@ -71,7 +71,8 @@ LOCAL_SRC_FILES:= \
|
||||
serval-dna/codecs.c \
|
||||
serval-dna/audiodevices.c \
|
||||
serval-dna/audio_msm_g1.c \
|
||||
serval-dna/audio_alsa.c
|
||||
serval-dna/audio_alsa.c \
|
||||
serval-dna/audio_reflector.c
|
||||
|
||||
LOCAL_MODULE:= serval
|
||||
|
||||
|
@ -44,7 +44,8 @@ SRCS= batman.c \
|
||||
codecs.c \
|
||||
audiodevices.c \
|
||||
audio_msm_g1.c \
|
||||
audio_alsa.c
|
||||
audio_alsa.c \
|
||||
audio_reflector.c
|
||||
|
||||
HAVE_VOIPTEST= @HAVE_VOIPTEST@
|
||||
ifeq ($(HAVE_VOIPTEST), 1)
|
||||
|
55
audio_alsa.c
55
audio_alsa.c
@ -18,7 +18,13 @@
|
||||
|
||||
#include "serval.h"
|
||||
|
||||
#ifdef HAVE_ALSA_ASOUNDLIB_H
|
||||
#ifndef HAVE_ALSA_ASOUNDLIB_H
|
||||
/* XXX Android NDK lacks the header files needed to build this.
|
||||
Will deal with it later */
|
||||
monitor_audio *audio_alsa_detect() {
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -40,7 +46,7 @@
|
||||
necessary symbols we need.
|
||||
*/
|
||||
typedef struct alsa_functions {
|
||||
int (*snd_pcm_open)(snd_pcm_t **,char *,int,int);
|
||||
int (*snd_pcm_open_preferred)(snd_pcm_t **,int *,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 *);
|
||||
@ -63,10 +69,12 @@ alsa_functions *alsa = NULL;
|
||||
|
||||
int alsa_load()
|
||||
{
|
||||
WHY("Trying to load ALSA library");
|
||||
void *h = dlopen(ALSA_LIB_PATH,RTLD_LAZY);
|
||||
if (!h) h=dlopen("/usr/lib/i386-linux-gnu/libasound.so.2",RTLD_LAZY);
|
||||
if (!h) return -1;
|
||||
alsa_functions *a=calloc(sizeof(alsa_functions),1);
|
||||
GETSYM(snd_pcm_open);
|
||||
GETSYM(snd_pcm_open_preferred);
|
||||
GETSYM(snd_pcm_hw_params_malloc);
|
||||
GETSYM(snd_pcm_hw_params_any);
|
||||
GETSYM(snd_pcm_hw_params_set_access);
|
||||
@ -81,7 +89,8 @@ int alsa_load()
|
||||
GETSYM(snd_pcm_poll_descriptors);
|
||||
alsa=a;
|
||||
dlclose(h);
|
||||
|
||||
WHY("Loaded ALSA library");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -120,8 +129,8 @@ int audio_alsa_start_play()
|
||||
record_params=NULL; play_params=NULL;
|
||||
|
||||
/* Open playback device */
|
||||
r = alsa->snd_pcm_open (&play_handle,"default",SND_PCM_STREAM_PLAYBACK,
|
||||
SND_PCM_NONBLOCK);
|
||||
r = alsa->snd_pcm_open_preferred (&play_handle,NULL,NULL,
|
||||
SND_PCM_STREAM_PLAYBACK|SND_PCM_NONBLOCK);
|
||||
if (r) { WHYF("ALSA pcm_open() failed"); goto error; }
|
||||
|
||||
/* Configure playback device for 8000Hz, 16 bit, mono */
|
||||
@ -157,8 +166,8 @@ int audio_alsa_start_play()
|
||||
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);
|
||||
int r = alsa->snd_pcm_open_preferred(&record_handle,NULL,NULL,
|
||||
SND_PCM_STREAM_CAPTURE|SND_PCM_NONBLOCK);
|
||||
if (r) { WHYF("ALSA pcm_open() failed"); goto error; }
|
||||
|
||||
/* Configure playback device for 8000Hz, 16 bit, mono */
|
||||
@ -243,25 +252,23 @@ int audio_alsa_write(unsigned char *buffer,int bytes)
|
||||
else return 0;
|
||||
}
|
||||
|
||||
#endif // HAVE_ALSA_ASOUNDLIB_H
|
||||
|
||||
monitor_audio *audio_alsa_detect()
|
||||
{
|
||||
#ifdef HAVE_ALSA_ASOUNDLIB_H
|
||||
if (!alsa) alsa_load();
|
||||
if (!alsa) return NULL;
|
||||
snd_pcm_t *handle;
|
||||
if (alsa->snd_pcm_open (&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) != -1) {
|
||||
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;
|
||||
}
|
||||
#endif // HAVE_ALSA_ASOUNDLIB_H
|
||||
return NULL;
|
||||
if (alsa->snd_pcm_open_preferred(&handle,NULL,NULL,SND_PCM_STREAM_PLAYBACK) < 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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
57
audio_reflector.c
Normal file
57
audio_reflector.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
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 "serval.h"
|
||||
|
||||
int audio_reflector_null() { return 0; }
|
||||
int audio_reflector_pollfds(struct pollfd *fd,int slots) { return 0; }
|
||||
|
||||
unsigned char reflectBuffer[8192];
|
||||
int reflectBufferLen=0;
|
||||
|
||||
int audio_reflector_write(unsigned char *buffer,int len)
|
||||
{
|
||||
if (reflectBufferLen+len>=8192)
|
||||
len=8192-reflectBufferLen;
|
||||
bcopy(&buffer[0],&reflectBuffer[reflectBufferLen],len);
|
||||
reflectBufferLen+=len;
|
||||
return len;
|
||||
}
|
||||
|
||||
int audio_reflector_read(unsigned char *buffer,int maximum_count)
|
||||
{
|
||||
int count=reflectBufferLen;
|
||||
if (count>maximum_count) count=maximum_count;
|
||||
bcopy(&reflectBuffer[0],&buffer[0],count);
|
||||
bcopy(&reflectBuffer[count],&reflectBuffer[0],
|
||||
reflectBufferLen-count);
|
||||
reflectBufferLen-=count;
|
||||
return count;
|
||||
}
|
||||
|
||||
monitor_audio *audio_reflector_detect()
|
||||
{
|
||||
monitor_audio *au=calloc(sizeof(monitor_audio),1);
|
||||
strcpy(au->name,"Echo Reflector");
|
||||
au->start=audio_reflector_null;
|
||||
au->stop=audio_reflector_null;
|
||||
au->poll_fds=audio_reflector_pollfds;
|
||||
au->read=audio_reflector_read;
|
||||
au->write=audio_reflector_write;
|
||||
return au;
|
||||
}
|
@ -61,15 +61,6 @@ int getAudioBytes(unsigned char *buffer,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* as with recording, some of the devices have a fixed buffer size that
|
||||
we must completely fill.
|
||||
*/
|
||||
int playAudio(unsigned char *data,int bytes)
|
||||
{
|
||||
if (audev&&audev->write) return audev->write(data,bytes);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stopAudio()
|
||||
{
|
||||
if (audev&&audev->stop) return audev->stop();
|
||||
|
11
codecs.c
11
codecs.c
@ -40,3 +40,14 @@ int encodeAndDispatchRecordedAudio(int fd,int callSessionToken,
|
||||
write(fd,msg,len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bufferAudioForPlayback(int codec,long long start_time,long long end_time,
|
||||
unsigned char *data,int dataLen)
|
||||
{
|
||||
/* XXX We need to buffer and reorder out-of-order sample blocks and
|
||||
decode codecs etc here. */
|
||||
|
||||
/* send audio to device */
|
||||
int bytesWritten=audev->write(&data[0],dataLen);
|
||||
return 0;
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ int processChar(int c);
|
||||
|
||||
int autoAnswerP=1;
|
||||
int pipeAudio=1;
|
||||
int reflectAudio=0;
|
||||
int syntheticAudio=0;
|
||||
int showReceived=1;
|
||||
int interactiveP=1;
|
||||
@ -62,6 +63,11 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
|
||||
cli_arg(argc, argv, o, "sid", &sid, NULL, "");
|
||||
struct sockaddr_un addr;
|
||||
|
||||
if (!strcasecmp(sid,"reflect")) {
|
||||
pipeAudio=1; reflectAudio=1;
|
||||
sid="";
|
||||
}
|
||||
|
||||
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
perror("socket");
|
||||
exit(-1);
|
||||
@ -81,7 +87,10 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
|
||||
}
|
||||
|
||||
if (pipeAudio) {
|
||||
detectAudioDevice();
|
||||
if (reflectAudio)
|
||||
audev=audio_reflector_detect();
|
||||
else
|
||||
detectAudioDevice();
|
||||
char *name=audev?audev->name:NULL;
|
||||
if (!name) {
|
||||
WHY("Could not detect any audio device. Will not pipe audio.");
|
||||
@ -118,17 +127,13 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
|
||||
we need, so we need to keep any left over ones from the previous
|
||||
read. */
|
||||
int audioRecordBufferBytes=0;
|
||||
int audioRecordBufferSize=8000*2;
|
||||
unsigned char audioRecordBuffer[8000*2];
|
||||
|
||||
int base_fd_count=fdcount;
|
||||
while(1) {
|
||||
fdcount=base_fd_count;
|
||||
int audio_fd = getAudioRecordFd();
|
||||
if (audio_fd>-1) {
|
||||
fds[fdcount].fd=STDIN_FILENO;
|
||||
fds[fdcount].events=POLLIN;
|
||||
fdcount++;
|
||||
}
|
||||
fdcount+=audev->poll_fds(&fds[fdcount],128-fdcount);
|
||||
poll(fds,fdcount,1000);
|
||||
|
||||
fcntl(fd,F_SETFL,
|
||||
@ -136,9 +141,6 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
|
||||
if (interactiveP)
|
||||
fcntl(STDIN_FILENO,F_SETFL,
|
||||
fcntl(STDIN_FILENO, F_GETFL, NULL)|O_NONBLOCK);
|
||||
if (audio_fd>-1)
|
||||
fcntl(audio_fd,F_SETFL,
|
||||
fcntl(audio_fd, F_GETFL, NULL)|O_NONBLOCK);
|
||||
|
||||
int bytes;
|
||||
int i;
|
||||
@ -153,12 +155,14 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
|
||||
printf("< %s",line);
|
||||
write(fd,line,bytes);
|
||||
}
|
||||
if (audio_fd>-1) {
|
||||
/* attempt to read next audio buffer.
|
||||
Some audio devices that we are using require an entire buffer
|
||||
to be read at a time. */
|
||||
audioRecordBufferBytes
|
||||
=getAudioBytes(audioRecordBuffer,audioRecordBufferBytes,sizeof(audioRecordBuffer));
|
||||
}
|
||||
|
||||
if (audev&&audev->read)
|
||||
{
|
||||
int bytesRead=audev->read(&audioRecordBuffer[audioRecordBufferBytes],
|
||||
audioRecordBufferSize-audioRecordBufferBytes);
|
||||
if (bytesRead>0) audioRecordBufferBytes+=bytesRead;
|
||||
|
||||
/* 8KHz 16 bit samples = 16000 bytes per second.
|
||||
Thus one 1ms of audio = 16 bytes. */
|
||||
int audioRecordBufferOffset=0;
|
||||
@ -180,13 +184,11 @@ int app_monitor_cli(int argc, const char *const *argv, struct command_line_optio
|
||||
audioRecordBufferBytes-audioRecordBufferOffset);
|
||||
audioRecordBufferBytes-=audioRecordBufferOffset;
|
||||
}
|
||||
}
|
||||
|
||||
fcntl(fd,F_SETFL,
|
||||
fcntl(fd, F_GETFL, NULL)&~O_NONBLOCK);
|
||||
fcntl(STDIN_FILENO,F_SETFL,
|
||||
fcntl(STDIN_FILENO, F_GETFL, NULL)&~O_NONBLOCK);
|
||||
|
||||
|
||||
fcntl(fd,F_SETFL,
|
||||
fcntl(fd, F_GETFL, NULL)&~O_NONBLOCK);
|
||||
fcntl(STDIN_FILENO,F_SETFL,
|
||||
fcntl(STDIN_FILENO, F_GETFL, NULL)&~O_NONBLOCK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -220,8 +222,8 @@ int processLine(char *cmd,unsigned char *data,int dataLen)
|
||||
&l_id,&r_id,&l_state,&r_state,
|
||||
&codec,&start_time,&end_time)==7)
|
||||
{
|
||||
if (pipeAudio) {
|
||||
playAudio(data,dataLen);
|
||||
if (pipeAudio&&audev) {
|
||||
bufferAudioForPlayback(codec,start_time,end_time,data,dataLen);
|
||||
}
|
||||
}
|
||||
if (sscanf(cmd,"CALLSTATUS:%x:%x:%d:%d",
|
||||
@ -268,6 +270,7 @@ int processLine(char *cmd,unsigned char *data,int dataLen)
|
||||
state=STATE_CMD;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int processChar(int c)
|
||||
{
|
||||
switch(state) {
|
||||
|
15
monitor.c
15
monitor.c
@ -361,6 +361,7 @@ int monitor_process_command(int index,char *cmd)
|
||||
}
|
||||
|
||||
char msg[1024];
|
||||
int flag;
|
||||
|
||||
if (cmd[0]=='*') {
|
||||
/* command with content */
|
||||
@ -391,6 +392,17 @@ int monitor_process_command(int index,char *cmd)
|
||||
c->flags|=MONITOR_RHIZOME;
|
||||
else if (!strcasecmp(cmd,"ignore rhizome"))
|
||||
c->flags&=~MONITOR_RHIZOME;
|
||||
else if (sscanf(cmd,"FASTAUDIO:%x:%d",&callSessionToken,&flag)==2)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<vomp_call_count;i++)
|
||||
if (vomp_call_states[i].local.session==callSessionToken
|
||||
||callSessionToken==0) {
|
||||
vomp_call_states[i].fast_audio=flag;
|
||||
vomp_call_states[i].local.last_state=-1;
|
||||
monitor_call_status(&vomp_call_states[i]);
|
||||
}
|
||||
}
|
||||
else if (sscanf(cmd,"call %s %s %s",sid,localDid,remoteDid)==3) {
|
||||
if (sid[0]=='*') {
|
||||
/* For testing, pick a peer and call them */
|
||||
@ -515,9 +527,10 @@ int monitor_call_status(vomp_call_state *call)
|
||||
call->remote.last_state=call->remote.state;
|
||||
if (show) {
|
||||
if (0) WHYF("sending call status to monitor");
|
||||
snprintf(msg,1024,"\nCALLSTATUS:%06x:%06x:%d:%d:%s:%s:%s:%s\n",
|
||||
snprintf(msg,1024,"\nCALLSTATUS:%06x:%06x:%d:%d:%d:%s:%s:%s:%s\n",
|
||||
call->local.session,call->remote.session,
|
||||
call->local.state,call->remote.state,
|
||||
call->fast_audio,
|
||||
overlay_render_sid(call->local.sid),
|
||||
overlay_render_sid(call->remote.sid),
|
||||
call->local.did,call->remote.did);
|
||||
|
9
serval.h
9
serval.h
@ -1320,6 +1320,7 @@ typedef struct vomp_call_state {
|
||||
vomp_call_half local;
|
||||
vomp_call_half remote;
|
||||
int ringing;
|
||||
int fast_audio;
|
||||
unsigned long long create_time;
|
||||
unsigned long long last_activity;
|
||||
unsigned long long audio_clock;
|
||||
@ -1444,17 +1445,19 @@ extern monitor_audio *audev;
|
||||
|
||||
monitor_audio *audio_msm_g1_detect();
|
||||
monitor_audio *audio_alsa_detect();
|
||||
monitor_audio *audio_reflector_detect();
|
||||
int detectAudioDevice();
|
||||
int getAudioPlayFd();
|
||||
int getAudioRecordFd();
|
||||
int getAudioBytes(unsigned char *buffer,
|
||||
int offset,
|
||||
int bufferSize);
|
||||
int playAudio(unsigned char *data,int bytes);
|
||||
int startAudio();
|
||||
int stopAudio();
|
||||
int encodeAndDispatchRecordedAudio(int fd,int callSessionToken,
|
||||
int recordCodec,
|
||||
unsigned char *sampleData,
|
||||
int sampleBytes);
|
||||
int scrapeProcNetRoute();
|
||||
int bufferAudioForPlayback(int codec,long long start_time,long long end_time,
|
||||
unsigned char *data,int dataLen);
|
||||
int startAudio();
|
||||
int stopAudio();
|
||||
|
Loading…
x
Reference in New Issue
Block a user