mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-20 05:37:57 +00:00
Remove bitrot related to voip testing
This commit is contained in:
parent
025726dcab
commit
1228df2b70
31
INSTALL.md
31
INSTALL.md
@ -170,37 +170,6 @@ Configure
|
|||||||
The [doc/Servald-Configuration](./doc/Servald-Configuration.md) document
|
The [doc/Servald-Configuration](./doc/Servald-Configuration.md) document
|
||||||
describes the configuration of Serval DNA in detail.
|
describes the configuration of Serval DNA in detail.
|
||||||
|
|
||||||
Voice call test
|
|
||||||
---------------
|
|
||||||
|
|
||||||
If the following packages are present then `./configure` will set the
|
|
||||||
`HAVE_VOIPTEST` macro and build **servald** with its `phone` command available
|
|
||||||
for performing voice call testing:
|
|
||||||
|
|
||||||
* [Port audio](http://www.portaudio.com)
|
|
||||||
* [Secret Rabbit Code](http://www.mega-nerd.com/SRC/) (a.k.a. Sample Rate
|
|
||||||
Convert) by Erik de Castro Lopo
|
|
||||||
* [SpanDSP](http://www.soft-switch.org/) by Steve Underwood
|
|
||||||
* [Codec2](http://www.rowetel.com/blog/?page_id=452) by Dave Rowe of Rowetel
|
|
||||||
|
|
||||||
The Codec2 source code can be fetched using [Subversion][]:
|
|
||||||
|
|
||||||
$ cd $HOME/src
|
|
||||||
$ svn checkout https://freetel.svn.sourceforge.net/svnroot/freetel/codec2 codec2
|
|
||||||
$
|
|
||||||
|
|
||||||
There are command-line options to control the `HAVE_VOIPTEST` macro:
|
|
||||||
|
|
||||||
* To force `HAVE_VOIPTEST` to be set, and fail if the necessary packages are
|
|
||||||
not present, use:
|
|
||||||
|
|
||||||
$ ./configure --enable-voiptest
|
|
||||||
|
|
||||||
* To force `HAVE_VOIPTEST` to be un-set (and not check for the presence of the
|
|
||||||
above packages), use:
|
|
||||||
|
|
||||||
$ ./configure --disable-voiptest
|
|
||||||
|
|
||||||
About the examples
|
About the examples
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
15
Makefile.in
15
Makefile.in
@ -16,17 +16,6 @@ SERVALD_SRCS = \
|
|||||||
$(SERVAL_CLIENT_SOURCES) \
|
$(SERVAL_CLIENT_SOURCES) \
|
||||||
$(SERVAL_DAEMON_SOURCES)
|
$(SERVAL_DAEMON_SOURCES)
|
||||||
|
|
||||||
HAVE_ALSA= @HAVE_ALSA@
|
|
||||||
ifeq (HAVE_ALSA,1)
|
|
||||||
SERVALD_SRCS+= audio_alsa.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
HAVE_VOIPTEST= @HAVE_VOIPTEST@
|
|
||||||
ifeq ($(HAVE_VOIPTEST), 1)
|
|
||||||
SERVALD_SRCS+= pa_phone.c
|
|
||||||
VOIPTEST_CFLAGS=-DHAVE_VOIPTEST=1
|
|
||||||
endif
|
|
||||||
|
|
||||||
MONITOR_CLIENT_SRCS = \
|
MONITOR_CLIENT_SRCS = \
|
||||||
$(SERVAL_CLIENT_SOURCES) \
|
$(SERVAL_CLIENT_SOURCES) \
|
||||||
monitor-client.c
|
monitor-client.c
|
||||||
@ -41,9 +30,9 @@ SERVAL_DAEMON_OBJS= $(SERVAL_DAEMON_SOURCES:.c=.o)
|
|||||||
MONITOR_CLIENT_OBJS= $(MONITOR_CLIENT_SRCS:.c=.o)
|
MONITOR_CLIENT_OBJS= $(MONITOR_CLIENT_SRCS:.c=.o)
|
||||||
MDP_CLIENT_OBJS= $(MDP_CLIENT_SRCS:.c=.o)
|
MDP_CLIENT_OBJS= $(MDP_CLIENT_SRCS:.c=.o)
|
||||||
|
|
||||||
LDFLAGS=@LDFLAGS@ @LIBS@ @PORTAUDIO_LIBS@ @SRC_LIBS@ @SPANDSP_LIBS@ @CODEC2_LIBS@ @PTHREAD_LIBS@
|
LDFLAGS=@LDFLAGS@ @LIBS@ @PTHREAD_LIBS@
|
||||||
|
|
||||||
CFLAGS= -Isqlite-amalgamation-3070900 @CPPFLAGS@ @CFLAGS@ @PORTAUDIO_CFLAGS@ @SRC_CFLAGS@ @SPANDSP_CFLAGS@ @PTHREAD_CFLAGS@ $(VOIPTEST_CFLAGS) -Inacl/include
|
CFLAGS= -Isqlite-amalgamation-3070900 @CPPFLAGS@ @CFLAGS@ @PTHREAD_CFLAGS@ -Inacl/include
|
||||||
CFLAGS+=-DSYSCONFDIR="\"$(sysconfdir)\"" -DLOCALSTATEDIR="\"$(localstatedir)\""
|
CFLAGS+=-DSYSCONFDIR="\"$(sysconfdir)\"" -DLOCALSTATEDIR="\"$(localstatedir)\""
|
||||||
CFLAGS+=-fPIC
|
CFLAGS+=-fPIC
|
||||||
CFLAGS+=-Wall -Wno-unused-value
|
CFLAGS+=-Wall -Wno-unused-value
|
||||||
|
@ -3135,9 +3135,5 @@ struct cli_schema command_line_options[]={
|
|||||||
"Listen for incoming connections"},
|
"Listen for incoming connections"},
|
||||||
{app_msp_connection,{"msp", "connect", "[--once]", "[--forward=<local_port>]", "<sid>", "<port>", NULL}, 0,
|
{app_msp_connection,{"msp", "connect", "[--once]", "[--forward=<local_port>]", "<sid>", "<port>", NULL}, 0,
|
||||||
"Connect to a remote party"},
|
"Connect to a remote party"},
|
||||||
#ifdef HAVE_VOIPTEST
|
|
||||||
{app_pa_phone,{"phone",NULL}, 0,
|
|
||||||
"Run phone test application"},
|
|
||||||
#endif
|
|
||||||
{NULL,{NULL},0,NULL}
|
{NULL,{NULL},0,NULL}
|
||||||
};
|
};
|
||||||
|
25
configure.in
25
configure.in
@ -38,26 +38,6 @@ dnl Specify default Rhizome store directory
|
|||||||
AC_ARG_VAR([RHIZOME_STORE_PATH], [default Rhizome store directory])
|
AC_ARG_VAR([RHIZOME_STORE_PATH], [default Rhizome store directory])
|
||||||
AS_IF([test "x$RHIZOME_STORE_PATH" != x], [AC_DEFINE_UNQUOTED([RHIZOME_STORE_PATH], ["$RHIZOME_STORE_PATH"], [default Rhizome store directory])])
|
AS_IF([test "x$RHIZOME_STORE_PATH" != x], [AC_DEFINE_UNQUOTED([RHIZOME_STORE_PATH], ["$RHIZOME_STORE_PATH"], [default Rhizome store directory])])
|
||||||
|
|
||||||
dnl VoIP test app
|
|
||||||
AC_ARG_ENABLE(voiptest,
|
|
||||||
AS_HELP_STRING([--enable-voiptest], [Require VoIP test program (default: only build if dependencies are present)])
|
|
||||||
AS_HELP_STRING([--disable-voiptest], [Disable VoIP test program (don't test for dependencies)])dnl'
|
|
||||||
)
|
|
||||||
|
|
||||||
have_voip=0
|
|
||||||
AS_IF([test "x$enable_voiptest" != "xno"], [
|
|
||||||
have_voip=1
|
|
||||||
PKG_CHECK_MODULES([PORTAUDIO], [portaudio-2.0],,[have_voip=0])
|
|
||||||
PKG_CHECK_MODULES([SRC], [samplerate],,[have_voip=0])
|
|
||||||
PKG_CHECK_MODULES([SPANDSP], [spandsp],,[have_voip=0])
|
|
||||||
AC_CHECK_HEADER([codec2.h],, [have_voip=0])
|
|
||||||
AC_CHECK_LIB([codec2], [codec2_create], [AC_SUBST([CODEC2_LIBS], -lcodec2)], [have_voip=0])
|
|
||||||
])
|
|
||||||
AS_IF([test "x$enable_voiptest" = "xyes" -a "x$have_voip" != "x1" ], [
|
|
||||||
AC_MSG_ERROR([Missing VoIP dependencies])
|
|
||||||
])
|
|
||||||
AC_SUBST([HAVE_VOIPTEST], $have_voip)
|
|
||||||
|
|
||||||
dnl Check for programs.
|
dnl Check for programs.
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
|
||||||
@ -141,11 +121,6 @@ AC_CHECK_HEADERS(
|
|||||||
#endif
|
#endif
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl Check for ALSA
|
|
||||||
AC_CHECK_HEADER([alsa/asoundlib.h], [have_alsa=1], [have_alsa=0])
|
|
||||||
AS_IF([test x"$have_alsa" = "x1"], [AC_DEFINE([HAVE_ALSA_ASOUNDLIB_H])])
|
|
||||||
AS_IF([test x"$have_alsa" = "x1"], [AC_SUBST(HAVE_ALSA,1)], [AC_SUBST(HAVE_ALSA,0)])
|
|
||||||
|
|
||||||
dnl Lazy way of checking for Linux
|
dnl Lazy way of checking for Linux
|
||||||
AS_IF([test "x$ac_cv_header_linux_if_h" = xyes], [AC_DEFINE([USE_ABSTRACT_NAMESPACE])])
|
AS_IF([test "x$ac_cv_header_linux_if_h" = xyes], [AC_DEFINE([USE_ABSTRACT_NAMESPACE])])
|
||||||
|
|
||||||
|
277
pa_phone.c
277
pa_phone.c
@ -1,277 +0,0 @@
|
|||||||
/*
|
|
||||||
Serval DNA Portaudio phone interface
|
|
||||||
Copyright (C) 2012 Serval Project Inc.
|
|
||||||
|
|
||||||
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 <codec2.h>
|
|
||||||
#include <spandsp.h>
|
|
||||||
#include "fifo.h"
|
|
||||||
#include <portaudio.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <samplerate.h>
|
|
||||||
#include "serval.h"
|
|
||||||
|
|
||||||
/* Defines */
|
|
||||||
#define IN_FRAMES 128
|
|
||||||
#define NUM_BUFS (8)
|
|
||||||
#define ECHO_LEN (128)
|
|
||||||
#define ADAPT_MODE (ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CNG)
|
|
||||||
|
|
||||||
#define CODEC2_BYTES_PER_FRAME ((CODEC2_BITS_PER_FRAME + 7) / 8)
|
|
||||||
|
|
||||||
/* Prototypes */
|
|
||||||
typedef struct {
|
|
||||||
PaStream *stream;
|
|
||||||
|
|
||||||
SRC_STATE *src;
|
|
||||||
|
|
||||||
pthread_mutex_t mtx; /* Mutex for frobbing queues */
|
|
||||||
|
|
||||||
/* Incoming samples after decompression
|
|
||||||
* Written with result of recvfrom + codec2_decode
|
|
||||||
* Read by sample rate converter
|
|
||||||
*/
|
|
||||||
struct fifo *incoming;
|
|
||||||
int incoverflow;
|
|
||||||
|
|
||||||
/* Samples after rate conversion
|
|
||||||
* Written by sample rate converter
|
|
||||||
* Read by PA callback
|
|
||||||
*/
|
|
||||||
struct fifo *incrate;
|
|
||||||
int underrun;
|
|
||||||
|
|
||||||
/* Outgoing samples
|
|
||||||
* Written by PA callback
|
|
||||||
* Read by codec2_encode + sendto
|
|
||||||
*/
|
|
||||||
struct fifo *outgoing;
|
|
||||||
|
|
||||||
int overrun;
|
|
||||||
|
|
||||||
echo_can_state_t *echocan; /* Echo canceller state */
|
|
||||||
void *codec2; /* Codec2 state */
|
|
||||||
|
|
||||||
} PaCtx;
|
|
||||||
|
|
||||||
static void freectx(PaCtx *ctx);
|
|
||||||
static int patestCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer,
|
|
||||||
const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags,
|
|
||||||
void *userData);
|
|
||||||
static PaCtx *pa_phone_setup(void);
|
|
||||||
|
|
||||||
/* Declarations */
|
|
||||||
|
|
||||||
int app_pa_phone(const struct cli_parsed *parsed, void *context)
|
|
||||||
{
|
|
||||||
PaCtx *ctx;
|
|
||||||
|
|
||||||
if ((ctx = pa_phone_setup()) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
freectx(ctx);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
|
||||||
** It may called at interrupt level on some machines so don't do anything
|
|
||||||
** that could mess up the system like calling malloc() or free().
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
patestCallback(const void *inputBuffer, void *outputBuffer,
|
|
||||||
unsigned long framesPerBuffer,
|
|
||||||
const PaStreamCallbackTimeInfo* timeInfo,
|
|
||||||
PaStreamCallbackFlags statusFlags,
|
|
||||||
void *userData) {
|
|
||||||
PaCtx *ctx;
|
|
||||||
int16_t *in, *out;
|
|
||||||
int avail, amt;
|
|
||||||
|
|
||||||
ctx = (PaCtx *)userData;
|
|
||||||
out = (int16_t *)outputBuffer;
|
|
||||||
in = (int16_t *)inputBuffer;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&ctx->mtx);
|
|
||||||
|
|
||||||
amt = framesPerBuffer * sizeof(out[0]);
|
|
||||||
|
|
||||||
/* Copy out samples to be played */
|
|
||||||
if ((avail = fifo_get(ctx->incrate, (uint8_t *)out, amt)) < amt) {
|
|
||||||
/* Zero out samples there are no data for */
|
|
||||||
bzero(out + (avail / sizeof(out[0])), amt - avail);
|
|
||||||
ctx->underrun += (amt - avail) / sizeof(out[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy in samples to be recorded */
|
|
||||||
if ((avail = fifo_put(ctx->outgoing, (uint8_t *)in, amt)) < amt) {
|
|
||||||
/* Zero out samples there are no data for */
|
|
||||||
bzero(in + (avail / sizeof(out[0])), amt - avail);
|
|
||||||
ctx->overrun += (amt - avail) / sizeof(out[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
/* Run the echo canceller */
|
|
||||||
for (int ofs = 0; ofs < framesPerBuffer; ofs++)
|
|
||||||
out[ofs] = echo_can_update(ctx->echocan, in[ofs], out[ofs]);
|
|
||||||
#endif
|
|
||||||
pthread_mutex_unlock(&ctx->mtx);
|
|
||||||
|
|
||||||
return paContinue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PaCtx *
|
|
||||||
pa_phone_setup(void) {
|
|
||||||
PaCtx *ctx;
|
|
||||||
int err, i, srcerr;
|
|
||||||
PaError err2;
|
|
||||||
|
|
||||||
err = paNoError;
|
|
||||||
err2 = 0;
|
|
||||||
|
|
||||||
if ((ctx = calloc(1, sizeof(PaCtx))) == NULL) {
|
|
||||||
WHY("Unable to allocate PA context");
|
|
||||||
err2 = 1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init mutex */
|
|
||||||
if (pthread_mutex_init(&ctx->mtx, NULL) != 0) {
|
|
||||||
WHYF("Unable to init mutex: %s\n", strerror(errno));
|
|
||||||
err2 = 1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate FIFOs */
|
|
||||||
i = IN_FRAMES * 10 * sizeof(int16_t);
|
|
||||||
printf("Allocating %d byte FIFOs\n", i);
|
|
||||||
|
|
||||||
if ((ctx->incoming = fifo_alloc(i)) == NULL) {
|
|
||||||
WHY("Unable to allocate incoming FIFO\n");
|
|
||||||
err2 = 1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ctx->incrate = fifo_alloc(i)) == NULL) {
|
|
||||||
WHY("Unable to allocate incoming SRC FIFO\n");
|
|
||||||
err2 = 1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ctx->outgoing = fifo_alloc(i)) == NULL) {
|
|
||||||
WHY("Unable to allocate outgoing FIFO\n");
|
|
||||||
err2 = 1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Init sample rate converter */
|
|
||||||
if ((ctx->src = src_new(SRC_SINC_BEST_QUALITY, 1, &srcerr)) == NULL) {
|
|
||||||
WHYF("Unable to init sample rate converter: %d\n", srcerr);
|
|
||||||
err2 = 1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init echo canceller */
|
|
||||||
if ((ctx->echocan = echo_can_init(ECHO_LEN, ADAPT_MODE)) == NULL) {
|
|
||||||
WHY("Unable to init echo canceller\n");
|
|
||||||
err2 = 1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init codec2 */
|
|
||||||
if ((ctx->codec2 = codec2_create()) == NULL) {
|
|
||||||
WHY("Unable to init codec2\n");
|
|
||||||
err2 = 1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize Port Audio library */
|
|
||||||
if ((err = Pa_Initialize()) != paNoError)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* Open an audio I/O stream. */
|
|
||||||
if ((err = Pa_OpenDefaultStream(&ctx->stream,
|
|
||||||
1, /* input channels */
|
|
||||||
1, /* output channels */
|
|
||||||
paInt16,
|
|
||||||
SAMPLE_RATE,
|
|
||||||
IN_FRAMES, /* frames per buffer */
|
|
||||||
patestCallback,
|
|
||||||
&ctx)) != paNoError)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* Start stream */
|
|
||||||
if ((err = Pa_StartStream(ctx->stream)) != paNoError)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* Close down stream, PA, etc */
|
|
||||||
/* XXX: hangs in pthread_join on Ubuntu 10.04 */
|
|
||||||
#ifndef linux
|
|
||||||
if ((err = Pa_StopStream(ctx->stream)) != paNoError)
|
|
||||||
goto error;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Do stuff */
|
|
||||||
|
|
||||||
if ((err = Pa_CloseStream(ctx->stream)) != paNoError)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
error:
|
|
||||||
Pa_Terminate();
|
|
||||||
|
|
||||||
/* Free things */
|
|
||||||
freectx(ctx);
|
|
||||||
|
|
||||||
if (err != paNoError)
|
|
||||||
WHYF("Port audio error: %s\n", Pa_GetErrorText(err));
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
freectx(PaCtx *ctx) {
|
|
||||||
/* Destroy mutex */
|
|
||||||
pthread_mutex_destroy(&ctx->mtx);
|
|
||||||
|
|
||||||
/* Free SRC resources */
|
|
||||||
if (ctx->src != NULL)
|
|
||||||
src_delete(ctx->src);
|
|
||||||
|
|
||||||
/* Free echo caneller */
|
|
||||||
if (ctx->echocan != NULL)
|
|
||||||
echo_can_free(ctx->echocan);
|
|
||||||
|
|
||||||
/* Free codec2 */
|
|
||||||
if (ctx->codec2 != NULL)
|
|
||||||
codec2_destroy(ctx->codec2);
|
|
||||||
|
|
||||||
/* Free FIFOs */
|
|
||||||
if (ctx->incoming != NULL)
|
|
||||||
fifo_free(ctx->incoming);
|
|
||||||
if (ctx->incrate != NULL)
|
|
||||||
fifo_free(ctx->incrate);
|
|
||||||
if (ctx->outgoing != NULL)
|
|
||||||
fifo_free(ctx->outgoing);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 2
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user