mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-21 22:17:53 +00:00
Remove unused audio code
This commit is contained in:
parent
53f3920b90
commit
749080cbfb
238
asterisk_app.c
238
asterisk_app.c
@ -1,238 +0,0 @@
|
||||
/*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Connect with Serval Distributed Numbering Architecture for Mesh Calling
|
||||
*
|
||||
* Paul Gardner-Stephen (paul@servalproject.org)
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision: Serval $")
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/features.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/cli.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/say.h"
|
||||
#include "asterisk/localtime.h"
|
||||
#include "asterisk/cdr.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
#include "serval.c"
|
||||
|
||||
#undef inet_ntoa
|
||||
#define inet_ntoa ast_inet_ntoa
|
||||
|
||||
static char *sdnalookup_descrip =
|
||||
" SDNALookup(): Resolves a telephone number into SIP address via Serval Distributed Numbering Architecture\n";
|
||||
|
||||
static char *sdnalookup_app = "SDNALookup";
|
||||
static char *sdnalookup_synopsis = "Resolve DID into SIP address via Serval DNA";
|
||||
|
||||
static char *handle_cli_sdnalookup(int fd, int argc, char *argv[])
|
||||
{
|
||||
char *did=NULL;
|
||||
char *sid=NULL;
|
||||
unsigned char buffer[65535];
|
||||
int len=0;
|
||||
int instance=0;
|
||||
|
||||
if (argc != 4) {
|
||||
ast_cli(fd, "You did not provide an argument to serval dna lookup\n\n");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
did=argv[3];
|
||||
|
||||
ast_cli(fd,"Serval DNA Lookup: NOT IMPLEMENTED\n\n",len);
|
||||
return RESULT_FAILURE;
|
||||
|
||||
buffer[len]=0;
|
||||
ast_cli(fd,"%s resolves to %s (len=%d)\n",did,buffer,len);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char *handle_cli_sdnapeers(int fd, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc != 3) {
|
||||
ast_cli(fd, "serval dna peers does not argue about arguments.\n\n");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
getPeerList();
|
||||
ast_cli(fd,"%d peers reachable:\n",peer_count);
|
||||
for(i=0;i<peer_count;i++)
|
||||
{
|
||||
unsigned char *c=(unsigned char *)&peers[i];
|
||||
ast_cli(fd," %d.%d.%d.%d\n",c[0],c[1],c[2],c[3]);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static char *handle_cli_sdnagate(int fd, int argc, char *argv[])
|
||||
{
|
||||
unsigned char buffer[65535];
|
||||
int len=0;
|
||||
int instance=0;
|
||||
|
||||
if (gatewayspec) free(gatewayspec);
|
||||
gatewayspec=NULL;
|
||||
if (argc == 3 ) {
|
||||
ast_cli(fd,"Serval DNA Gateway Function OFF.\n\n",len);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
if (argc != 4) {
|
||||
ast_cli(fd, "You did not provide an argument to serval dna gateway\n\n");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
gatewayspec=strdup(argv[3]);
|
||||
|
||||
ast_cli(fd,"Serval DNA Gateway Function ON (trunk spec is %s).\n\n",gatewayspec);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char *handle_cli_sdnadebug(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 3) {
|
||||
ast_cli(fd, "You did not provide an argument to serval debug\n\n");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
debug=atoi(argv[2]);
|
||||
|
||||
ast_cli(fd,"Serval debug level set to %d\n",debug);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static char sdnalookup_usage[]=
|
||||
"Usage: serval dna lookup <did>\n"
|
||||
" Attempt to resolve a DID into a SIP address via Serval DNA.\n"
|
||||
"Examples:\n"
|
||||
" serval dna lookup 0427679796\n";
|
||||
|
||||
static char sdnapeers_usage[]=
|
||||
"Usage: serval dna peers\n"
|
||||
" Ask DNA to list the peers currently reachable on the mesh.\n"
|
||||
"Examples:\n"
|
||||
" serval dna peers\n";
|
||||
|
||||
static char sdnadebug_usage[]=
|
||||
"Usage: serval debug <debug level>\n"
|
||||
" Set Serval debug level (0-3 are useful values).\n"
|
||||
"Examples:\n"
|
||||
" serval debug 3\n";
|
||||
|
||||
static char sdnagate_usage[]=
|
||||
"Usage: serval dna gateway [gateway uri]\n"
|
||||
" Offer Serval DNA gateway services to allow other BatPhones to use our SIP trunk.\n"
|
||||
"Examples:\n"
|
||||
" serval dna gateway 4000@10.130.1.101\n";
|
||||
|
||||
|
||||
static struct ast_cli_entry cli_sdnalookup[] = {
|
||||
{ { "serval","dna","lookup" }, handle_cli_sdnalookup,
|
||||
"Resolve a telephone number via Serval DNA", sdnalookup_usage },
|
||||
{ { "serval","dna","peers" }, handle_cli_sdnapeers,
|
||||
"Ask DNA to list peers reachable on the mesh", sdnapeers_usage },
|
||||
{ { "serval","debug" }, handle_cli_sdnadebug,
|
||||
"Set Serval debug level", sdnadebug_usage },
|
||||
{ { "serval","dna","gateway" }, handle_cli_sdnagate,
|
||||
"Enable DNA Gateway ", sdnagate_usage },
|
||||
};
|
||||
|
||||
static int sdnalookup_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *did=data;
|
||||
char *sid=NULL;
|
||||
unsigned char buffer[65535];
|
||||
int len=0;
|
||||
int instance=0;
|
||||
|
||||
char status[256] = "INVALIDARGS";
|
||||
|
||||
/* Clear Serval DNA set variables */
|
||||
pbx_builtin_setvar_helper(chan, "SDNADID", "");
|
||||
pbx_builtin_setvar_helper(chan, "SDNASID", "");
|
||||
pbx_builtin_setvar_helper(chan, "SDNALOCATION", "");
|
||||
pbx_builtin_setvar_helper(chan, "SDNASIG", "");
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "SDNALookup requires an argument (number)\n");
|
||||
pbx_builtin_setvar_helper(chan, "SDNASTATUS", status);
|
||||
if (debug) fprintf(stderr,"SDNASTATUS=%s (a)\n",status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX - Simple version for now. Should really use a derivation of the core code from the function below to:
|
||||
(a) provide more meaningful errors;
|
||||
(b) retrieve the SID for the DID for further use
|
||||
(c) fetch the voicesig as well if requested
|
||||
*/
|
||||
// NOT IMPLEMENTED
|
||||
pbx_builtin_setvar_helper(chan,"SNASTATUS","FAILED");
|
||||
if (debug) fprintf(stderr,"SDNASTATUS=FAILED\n");
|
||||
return -1;
|
||||
|
||||
/* It worked, so set appropriate variables and return happily */
|
||||
pbx_builtin_setvar_helper(chan,"SNADID",did);
|
||||
if (debug) fprintf(stderr,"SNADID=%s\n",did);
|
||||
if (sid) {
|
||||
pbx_builtin_setvar_helper(chan,"SNASID",sid);
|
||||
if (debug) fprintf(stderr,"SNASID=%s\n",sid);
|
||||
}
|
||||
if (len) {
|
||||
buffer[len]=0;
|
||||
pbx_builtin_setvar_helper(chan,"SDNALOCATION",(char*)buffer);
|
||||
if (debug) fprintf(stderr,"SNALOCATION=%s\n",buffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
ast_cli_unregister_multiple(cli_sdnalookup, ARRAY_LEN(cli_sdnalookup));
|
||||
res = ast_unregister_application(sdnalookup_app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
batman_peerfile=NULL;
|
||||
ast_cli_register_multiple(cli_sdnalookup, ARRAY_LEN(cli_sdnalookup));
|
||||
return ast_register_application(sdnalookup_app, sdnalookup_exec, sdnalookup_synopsis, sdnalookup_descrip);
|
||||
}
|
||||
|
||||
#define AST_MODULE "app_serval"
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Serval Mesh Telephony Adapter and Serval DNA Resolver");
|
274
audio_alsa.c
274
audio_alsa.c
@ -1,274 +0,0 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
#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>
|
||||
#include <dlfcn.h>
|
||||
#include <alsa/asoundlib.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_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 *);
|
||||
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()
|
||||
{
|
||||
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_preferred);
|
||||
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);
|
||||
WHY("Loaded ALSA library");
|
||||
|
||||
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_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 */
|
||||
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_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 */
|
||||
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;
|
||||
snd_pcm_t *handle;
|
||||
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
|
551
audio_msm_g1.c
551
audio_msm_g1.c
@ -1,551 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
Contains code derived from playwav2.c, which has the following notice:
|
||||
|
||||
Copyright (C) 2008 The Android Open Source Project
|
||||
*/
|
||||
|
||||
/*
|
||||
We ask the driver to reduce it's buffer size, but it doesn't listen.
|
||||
This is very strange, as looking in pcm_out.c of kernel source it appears
|
||||
that it should work just fine.
|
||||
|
||||
What does work, however, is increasing the sample rate, so that the buffers
|
||||
empty sooner. So we use 32000Hz instead of 8000Hz so that the 2KB record buffer
|
||||
holds only 1/32nd of a second instead of 1/8th of a second.
|
||||
|
||||
We may need to introduce a low-pass filter to prevent aliasing, assuming that
|
||||
the microphone and ACD in these phones responds to requencies above 4KHz.
|
||||
|
||||
Added fun with this device is that we must read/write exactly one buffer full
|
||||
at a time.
|
||||
*/
|
||||
#define DESIRED_BUFFER_SIZE 256
|
||||
#define DESIRED_SAMPLE_RATE 32000
|
||||
#define RESAMPLE_FACTOR (DESIRED_SAMPLE_RATE/8000)
|
||||
int resamplingBufferSize=0;
|
||||
unsigned char *playMarshallBuffer=0;
|
||||
unsigned char *recordMarshallBuffer=0;
|
||||
|
||||
extern int playFd;
|
||||
extern int recordFd;
|
||||
extern int playBufferSize;
|
||||
extern int recordBufferSize;
|
||||
|
||||
#include "serval.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if HAVE_LINUX_IOCTL_H
|
||||
#include <linux/ioctl.h>
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#include <linux/msm_audio.h>
|
||||
#else
|
||||
/* ---------- linux/msm_audio.h -------- */
|
||||
|
||||
#define AUDIO_IOCTL_MAGIC 'a'
|
||||
|
||||
#define AUDIO_START _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned)
|
||||
#define AUDIO_STOP _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned)
|
||||
#define AUDIO_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned)
|
||||
#define AUDIO_GET_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned)
|
||||
#define AUDIO_SET_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned)
|
||||
#define AUDIO_GET_STATS _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned)
|
||||
#define AUDIO_ENABLE_AUDPP _IOW(AUDIO_IOCTL_MAGIC, 6, unsigned)
|
||||
#define AUDIO_SET_ADRC _IOW(AUDIO_IOCTL_MAGIC, 7, unsigned)
|
||||
#define AUDIO_SET_EQ _IOW(AUDIO_IOCTL_MAGIC, 8, unsigned)
|
||||
#define AUDIO_SET_RX_IIR _IOW(AUDIO_IOCTL_MAGIC, 9, unsigned)
|
||||
|
||||
#define EQ_MAX_BAND_NUM 12
|
||||
|
||||
#define ADRC_ENABLE 0x0001
|
||||
#define ADRC_DISABLE 0x0000
|
||||
#define EQ_ENABLE 0x0002
|
||||
#define EQ_DISABLE 0x0000
|
||||
#define IIR_ENABLE 0x0004
|
||||
#define IIR_DISABLE 0x0000
|
||||
|
||||
struct eq_filter_type
|
||||
{
|
||||
int16_t gain;
|
||||
uint16_t freq;
|
||||
uint16_t type;
|
||||
uint16_t qf;
|
||||
};
|
||||
|
||||
struct eqalizer
|
||||
{
|
||||
uint16_t bands;
|
||||
uint16_t params[132];
|
||||
};
|
||||
|
||||
struct rx_iir_filter
|
||||
{
|
||||
uint16_t num_bands;
|
||||
uint16_t iir_params[48];
|
||||
};
|
||||
|
||||
|
||||
struct msm_audio_config
|
||||
{
|
||||
uint32_t buffer_size;
|
||||
uint32_t buffer_count;
|
||||
uint32_t channel_count;
|
||||
uint32_t sample_rate;
|
||||
uint32_t codec_type;
|
||||
uint32_t unused[3];
|
||||
};
|
||||
|
||||
struct msm_audio_stats
|
||||
{
|
||||
uint32_t out_bytes;
|
||||
uint32_t unused[3];
|
||||
};
|
||||
|
||||
/* Audio routing */
|
||||
|
||||
#define SND_IOCTL_MAGIC 's'
|
||||
|
||||
#define SND_MUTE_UNMUTED 0
|
||||
#define SND_MUTE_MUTED 1
|
||||
|
||||
struct msm_snd_device_config
|
||||
{
|
||||
uint32_t device;
|
||||
uint32_t ear_mute;
|
||||
uint32_t mic_mute;
|
||||
};
|
||||
|
||||
#define SND_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_device_config *)
|
||||
|
||||
#define SND_METHOD_VOICE 0
|
||||
|
||||
#define SND_METHOD_VOICE_1 1
|
||||
|
||||
struct msm_snd_volume_config
|
||||
{
|
||||
uint32_t device;
|
||||
uint32_t method;
|
||||
uint32_t volume;
|
||||
};
|
||||
|
||||
#define SND_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_snd_volume_config *)
|
||||
|
||||
/* Returns the number of SND endpoints supported. */
|
||||
|
||||
#define SND_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *)
|
||||
|
||||
struct msm_snd_endpoint
|
||||
{
|
||||
int id; /* input and output */
|
||||
char name[64]; /* output only */
|
||||
};
|
||||
|
||||
/* Takes an index between 0 and one less than the number returned by
|
||||
* SND_GET_NUM_ENDPOINTS, and returns the SND index and name of a
|
||||
* SND endpoint. On input, the .id field contains the number of the
|
||||
* endpoint, and on exit it contains the SND index, while .name contains
|
||||
* the description of the endpoint.
|
||||
*/
|
||||
|
||||
#define SND_GET_ENDPOINT _IOWR(SND_IOCTL_MAGIC, 5, struct msm_snd_endpoint *)
|
||||
|
||||
#endif
|
||||
|
||||
static int
|
||||
do_route_audio_rpc (uint32_t device, int ear_mute, int mic_mute)
|
||||
{
|
||||
if (device == -1UL)
|
||||
return 0;
|
||||
|
||||
int fd;
|
||||
|
||||
printf ("rpc_snd_set_device(%d, %d, %d)\n", device, ear_mute, mic_mute);
|
||||
|
||||
fd = open ("/dev/msm_snd", O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror ("Can not open snd device");
|
||||
return -1;
|
||||
}
|
||||
// RPC call to switch audio path
|
||||
/* rpc_snd_set_device(
|
||||
* device, # Hardware device enum to use
|
||||
* ear_mute, # Set mute for outgoing voice audio
|
||||
* # this should only be unmuted when in-call
|
||||
* mic_mute, # Set mute for incoming voice audio
|
||||
* # this should only be unmuted when in-call or
|
||||
* # recording.
|
||||
* )
|
||||
*/
|
||||
struct msm_snd_device_config args;
|
||||
args.device = device;
|
||||
args.ear_mute = ear_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED;
|
||||
args.mic_mute = mic_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED;
|
||||
|
||||
if (ioctl (fd, SND_SET_DEVICE, &args) < 0)
|
||||
{
|
||||
perror ("snd_set_device error.");
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
set_volume_rpc (uint32_t device, uint32_t method, uint32_t volume)
|
||||
{
|
||||
int fd;
|
||||
|
||||
printf ("rpc_snd_set_volume(%d, %d, %d)\n", device, method, volume);
|
||||
|
||||
if (device == -1UL)
|
||||
return 0;
|
||||
|
||||
fd = open ("/dev/msm_snd", O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror ("Can not open snd device");
|
||||
return -1;
|
||||
}
|
||||
/* rpc_snd_set_volume(
|
||||
* device, # Any hardware device enum, including
|
||||
* # SND_DEVICE_CURRENT
|
||||
* method, # must be SND_METHOD_VOICE to do anything useful
|
||||
* volume, # integer volume level, in range [0,5].
|
||||
* # note that 0 is audible (not quite muted)
|
||||
* )
|
||||
* rpc_snd_set_volume only works for in-call sound volume.
|
||||
*/
|
||||
struct msm_snd_volume_config args;
|
||||
args.device = device;
|
||||
args.method = method;
|
||||
args.volume = volume;
|
||||
|
||||
if (ioctl (fd, SND_SET_VOLUME, &args) < 0)
|
||||
{
|
||||
perror ("snd_set_volume error.");
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
close (fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prepare audio path, volume etc, and then open play and
|
||||
record file descriptors.
|
||||
*/
|
||||
int audio_msm_g1_start_play()
|
||||
{
|
||||
if (playFd>-1) return 0;
|
||||
|
||||
/* Get audio control device */
|
||||
int fd = open ("/dev/msm_snd", O_RDWR);
|
||||
if (fd<0) return -1;
|
||||
|
||||
/* Look through endpoints for the regular in-call endpoint */
|
||||
int endpoints=0;
|
||||
ioctl(fd,SND_GET_NUM_ENDPOINTS,&endpoints);
|
||||
int endpoint=-1;
|
||||
int i;
|
||||
for(i=0;i<endpoints;i++) {
|
||||
struct msm_snd_endpoint ep;
|
||||
ep.id=i;
|
||||
ep.name[0]=0;
|
||||
ioctl(fd,SND_GET_ENDPOINT,&ep);
|
||||
if (!strcasecmp(ep.name,"HANDSET"))
|
||||
/* should this be i, or ep.id ? */
|
||||
endpoint=i;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* Set the specified endpoint and unmute microphone and speaker */
|
||||
do_route_audio_rpc(endpoint,SND_MUTE_UNMUTED,SND_MUTE_UNMUTED);
|
||||
|
||||
/* Set the volume (somewhat arbitrarily for now) */
|
||||
int vol=5;
|
||||
int dev=0xd; /* no one seems to know what this magic value means */
|
||||
set_volume_rpc(dev,SND_METHOD_VOICE_1, vol);
|
||||
|
||||
playFd=open("/dev/msm_pcm_out",O_RDWR);
|
||||
struct msm_audio_config config;
|
||||
if (ioctl(playFd, AUDIO_GET_CONFIG,&config))
|
||||
{
|
||||
close(playFd);
|
||||
playFd=-1;
|
||||
return WHY("Could not read audio device configuration");
|
||||
}
|
||||
config.channel_count=1;
|
||||
config.sample_rate=DESIRED_SAMPLE_RATE;
|
||||
config.buffer_size=DESIRED_BUFFER_SIZE;
|
||||
if (ioctl(playFd, AUDIO_SET_CONFIG,&config))
|
||||
{
|
||||
close(playFd);
|
||||
playFd=-1;
|
||||
return WHY("Could not set audio device configuration");
|
||||
}
|
||||
|
||||
fcntl(playFd,F_SETFL,
|
||||
fcntl(playFd, F_GETFL, NULL)|O_NONBLOCK);
|
||||
|
||||
/*
|
||||
If playBufferSize equates to too long an interval,
|
||||
then try to reduce it in various ways.
|
||||
*/
|
||||
ioctl(playFd, AUDIO_GET_CONFIG,&config);
|
||||
playBufferSize=config.buffer_size;
|
||||
float bufferTime=playBufferSize/2*1.0/config.sample_rate;
|
||||
WHYF("PLAY buf=%.3fsecs.",bufferTime);
|
||||
|
||||
playMarshallBuffer=malloc(playBufferSize);
|
||||
|
||||
/* tell hardware to start playing */
|
||||
ioctl(playFd,AUDIO_START,0);
|
||||
|
||||
WHYF("G1/IDEOS style MSM audio device initialised and ready to play");
|
||||
WHYF("Play buffer size = %d bytes",playBufferSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_msm_g1_stop_play()
|
||||
{
|
||||
WHY("stopping audio play");
|
||||
if (playFd>-1) close(playFd);
|
||||
if (playMarshallBuffer) free(playMarshallBuffer);
|
||||
playFd=-1; playMarshallBuffer=NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_msm_g1_start_record()
|
||||
{
|
||||
if (recordFd>-1) return 0;
|
||||
|
||||
recordFd=open("/dev/msm_pcm_in",O_RDWR);
|
||||
struct msm_audio_config config;
|
||||
if (ioctl(recordFd, AUDIO_GET_CONFIG,&config))
|
||||
{
|
||||
close(recordFd);
|
||||
recordFd=-1;
|
||||
return WHY("Could not read audio device configuration");
|
||||
}
|
||||
config.channel_count=1;
|
||||
config.sample_rate=DESIRED_SAMPLE_RATE;
|
||||
config.buffer_size=DESIRED_BUFFER_SIZE;
|
||||
if (ioctl(recordFd, AUDIO_SET_CONFIG,&config))
|
||||
{
|
||||
close(recordFd);
|
||||
recordFd=-1;
|
||||
return WHY("Could not set audio device configuration");
|
||||
}
|
||||
|
||||
/*
|
||||
If recordBufferSize equates to too long an interval,
|
||||
then try to reduce it in various ways.
|
||||
*/
|
||||
ioctl(recordFd, AUDIO_GET_CONFIG,&config);
|
||||
recordBufferSize=config.buffer_size;
|
||||
float bufferTime=recordBufferSize/2*1.0/config.sample_rate;
|
||||
WHYF("REC buf=%.3fsecs.",bufferTime);
|
||||
|
||||
if (!recordMarshallBuffer)
|
||||
recordMarshallBuffer=malloc(recordBufferSize);
|
||||
|
||||
fcntl(recordFd,F_SETFL,
|
||||
fcntl(recordFd, F_GETFL, NULL)|O_NONBLOCK);
|
||||
|
||||
/* tell hardware to start playing */
|
||||
ioctl(recordFd,AUDIO_START,0);
|
||||
|
||||
WHY("G1/IDEOS style MSM audio device initialised and ready to record");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_msm_g1_stop_record()
|
||||
{
|
||||
WHY("stopping recording");
|
||||
if (recordFd>-1) close(recordFd);
|
||||
if (recordMarshallBuffer) free(recordMarshallBuffer);
|
||||
recordMarshallBuffer=NULL;
|
||||
recordFd=-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_msm_g1_stop()
|
||||
{
|
||||
audio_msm_g1_stop_play();
|
||||
audio_msm_g1_stop_record();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_msm_g1_start()
|
||||
{
|
||||
if (audio_msm_g1_start_play()) return -1;
|
||||
if (audio_msm_g1_start_record()) {
|
||||
audio_msm_g1_stop_play();
|
||||
return -1;
|
||||
}
|
||||
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=POLLIN;
|
||||
count++; slots--;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int recordMarshallBufferOffset=0;
|
||||
int audio_msm_g1_read(unsigned char *buffer,int maximum_count)
|
||||
{
|
||||
if (recordFd==-1) return 0;
|
||||
if (!recordMarshallBuffer) return 0;
|
||||
|
||||
int supplied=0;
|
||||
|
||||
/* read new samples if we don't have any lingering around */
|
||||
if (!recordMarshallBufferOffset) {
|
||||
fcntl(recordFd,F_SETFL,fcntl(recordFd, F_GETFL, NULL)|O_NONBLOCK);
|
||||
ioctl(recordFd,AUDIO_START,0);
|
||||
WHY("calling read()");
|
||||
int b=read(recordFd,&recordMarshallBuffer[0],recordBufferSize);
|
||||
if (b<1)
|
||||
WHYF("read failed: b=%d, err=%s",b,strerror(errno));
|
||||
if (errno==EBADF) recordFd=-1;
|
||||
WHYF("read %d raw (upsampled) bytes",b);
|
||||
recordMarshallBufferOffset=b;
|
||||
}
|
||||
|
||||
/* supply audio from marshalling buffer if it has anything.
|
||||
Don't forget to downsample first. */
|
||||
int marshall_offset=0;
|
||||
while(marshall_offset<recordMarshallBufferOffset
|
||||
&&supplied<maximum_count) {
|
||||
buffer[supplied+0]=recordMarshallBuffer[marshall_offset];
|
||||
buffer[supplied+1]=recordMarshallBuffer[marshall_offset+1];
|
||||
supplied+=2;
|
||||
marshall_offset+=2*RESAMPLE_FACTOR;
|
||||
}
|
||||
bcopy(&recordMarshallBuffer[marshall_offset],
|
||||
&recordMarshallBuffer[0],
|
||||
recordMarshallBufferOffset-marshall_offset);
|
||||
recordMarshallBufferOffset-=marshall_offset;
|
||||
|
||||
/* Else we read exactly one buffer full into the marshalling buffer */
|
||||
|
||||
WHYF("Read %d samples.",supplied/2);
|
||||
|
||||
return supplied;
|
||||
}
|
||||
|
||||
int playMarshallBufferOffset=0;
|
||||
int audio_msm_g1_write(unsigned char *data,int bytes)
|
||||
{
|
||||
if (playFd==-1) return 0;
|
||||
fcntl(playFd,F_SETFL,fcntl(playFd, F_GETFL, NULL)|O_NONBLOCK);
|
||||
|
||||
WHYF("Writing %d bytes of 8KHz audio",bytes);
|
||||
|
||||
int i,played=0;
|
||||
|
||||
while(played<bytes)
|
||||
{
|
||||
if (playMarshallBufferOffset==playBufferSize) {
|
||||
/* we have a buffer full of samples, so play it */
|
||||
struct msm_audio_stats stats;
|
||||
if (ioctl (playFd, AUDIO_GET_STATS, &stats) == 0)
|
||||
WHYF("stats.out_bytes = %10d", stats.out_bytes);
|
||||
|
||||
/* even if set non-blocking the following write can block
|
||||
if we don't call this ioctl first */
|
||||
ioctl(playFd,AUDIO_START,0);
|
||||
int w=write(playFd,&playMarshallBuffer[0],playBufferSize);
|
||||
if (w<1)
|
||||
{
|
||||
WHYF("Failed to write, returned %d (errno=%s)",
|
||||
w,strerror(errno));
|
||||
if (errno==EBADF) playFd=-1;
|
||||
} else {
|
||||
if (w<=playBufferSize) {
|
||||
/* short write, so update buffer status and inform caller */
|
||||
bcopy(&playMarshallBuffer[w],&playMarshallBuffer[0],
|
||||
playBufferSize-w);
|
||||
playMarshallBufferOffset-=w;
|
||||
WHYF("short write: %d of %d raw bytes written",
|
||||
w,playBufferSize);
|
||||
return w/RESAMPLE_FACTOR;
|
||||
}
|
||||
}
|
||||
playMarshallBufferOffset=0;
|
||||
}
|
||||
|
||||
/* upsample for playing back */
|
||||
for(i=0;i<RESAMPLE_FACTOR;i++) {
|
||||
playMarshallBuffer[playMarshallBufferOffset++]
|
||||
=data[played];
|
||||
playMarshallBuffer[playMarshallBufferOffset++]
|
||||
=data[played+1];
|
||||
}
|
||||
played+=2;
|
||||
}
|
||||
|
||||
WHYF("done writing %d audio bytes",played);
|
||||
return played;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
WHYF("Could not open /dev/msm_snd (err=%s)",strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
int endpoints=0;
|
||||
ioctl(fd,SND_GET_NUM_ENDPOINTS,&endpoints);
|
||||
close(fd);
|
||||
if (endpoints>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 {
|
||||
WHY("zero end points, so assuming not compatibile audio device");
|
||||
return NULL;
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
#define AUDIO_MSM_G1_ETC 1
|
||||
#define AUDIO_MSM_N1_ETC 2
|
||||
monitor_audio *audev=NULL;
|
||||
|
||||
int playFd=-1;
|
||||
int recordFd=-1;
|
||||
int playBufferSize=0;
|
||||
int recordBufferSize=0;
|
||||
|
||||
int detectAudioDevice()
|
||||
{
|
||||
#ifdef ANDROID
|
||||
if (!audev) audev=audio_msm_g1_detect();
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ALSA_ASOUNDLIB_H
|
||||
if (!audev) audev=audio_alsa_detect();
|
||||
#endif
|
||||
if (audev) {
|
||||
WHYF("Detected audio device '%s'",audev->name);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int getAudioPlayFd()
|
||||
{
|
||||
return playFd;
|
||||
}
|
||||
|
||||
int getAudioRecordFd()
|
||||
{
|
||||
return recordFd;
|
||||
}
|
||||
|
||||
/* read some audio, but not more than bufferSize-offset bytes.
|
||||
*/
|
||||
int getAudioBytes(unsigned char *buffer,
|
||||
int offset,
|
||||
int bufferSize)
|
||||
{
|
||||
if (audev&&audev->write) {
|
||||
return audev->write(&buffer[offset],bufferSize-offset);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stopAudio()
|
||||
{
|
||||
if (audev&&audev->stop) return audev->stop();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int startAudio()
|
||||
{
|
||||
if (audev&&audev->start) return audev->start();
|
||||
return -1;
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
SERVAL_SOURCES = $(SERVAL_BASE)audiodevices.c \
|
||||
$(SERVAL_BASE)audio_reflector.c \
|
||||
SERVAL_SOURCES = \
|
||||
$(SERVAL_BASE)cli.c \
|
||||
$(SERVAL_BASE)commandline.c \
|
||||
$(SERVAL_BASE)conf.c \
|
||||
|
Loading…
Reference in New Issue
Block a user