Implementation of German "Zeitansage", spoken by Elvira Bader
This commit is contained in:
parent
b1ea4e574f
commit
b2089bb529
|
@ -67,6 +67,7 @@ src/eurosignal/eurosignal
|
|||
src/tv/osmotv
|
||||
src/radio/osmoradio
|
||||
src/datenklo/datenklo
|
||||
src/zeitansage/zeitansage
|
||||
sim/cnetz_sim
|
||||
src/test/test_filter
|
||||
src/test/test_sendevolumenregler
|
||||
|
|
|
@ -54,7 +54,7 @@ AS_IF([test "x$with_soapy" == "xyes"],[AC_MSG_NOTICE( Compiling with SoapySDR su
|
|||
AS_IF([test "x$with_imagemagick" == "xyes"],[AC_MSG_NOTICE( Compiling with ImageMagick )],[AC_MSG_NOTICE( ImageMagick not supported. Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. )])
|
||||
AS_IF([test "x$with_fuse" == "xyes"],[AC_MSG_NOTICE( Compiling with FUSE )],[AC_MSG_NOTICE( FUSE not supported. There will be no analog modem support. Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. )])
|
||||
|
||||
AS_IF([test "x$with_alsa" != "xyes" -a "x$with_sdr" != "xyes"],[AC_MSG_FAILURE( Without sound nor SDR support this project does not make sense. Please support sound card for analog transceivers or better SDR!" )],[])
|
||||
AS_IF([test "x$with_alsa" != "xyes" -a "x$with_sdr" != "xyes"],[AC_MSG_NOTICE( Without sound nor SDR support this project does not make sense. Please support sound card for analog transceivers or better SDR!" )],[])
|
||||
|
||||
AC_OUTPUT(
|
||||
src/liboptions/Makefile
|
||||
|
@ -98,6 +98,7 @@ AC_OUTPUT(
|
|||
src/tv/Makefile
|
||||
src/radio/Makefile
|
||||
src/datenklo/Makefile
|
||||
src/zeitansage/Makefile
|
||||
src/test/Makefile
|
||||
src/Makefile
|
||||
sim/Makefile
|
||||
|
|
|
@ -50,7 +50,8 @@ SUBDIRS += \
|
|||
jolly \
|
||||
eurosignal \
|
||||
tv \
|
||||
radio
|
||||
radio \
|
||||
zeitansage
|
||||
|
||||
if HAVE_SDR
|
||||
if HAVE_FUSE
|
||||
|
|
|
@ -70,6 +70,7 @@ struct debug_cat {
|
|||
{ "uart", "\033[0;32m" },
|
||||
{ "device", "\033[0;33m" },
|
||||
{ "datenklo", "\033[1;34m" },
|
||||
{ "zeit", "\033[1;34m" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#define DUART 26
|
||||
#define DDEVICE 27
|
||||
#define DDATENKLO 28
|
||||
#define DZEIT 29
|
||||
|
||||
void get_win_size(int *w, int *h);
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) -fstack-check $(FUSE_CFLAGS)
|
||||
|
||||
bin_PROGRAMS = \
|
||||
zeitansage
|
||||
|
||||
zeitansage_SOURCES = \
|
||||
zeitansage.c \
|
||||
image.c \
|
||||
samples.c \
|
||||
main.c
|
||||
zeitansage_LDADD = \
|
||||
$(COMMON_LA) \
|
||||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
$(top_builddir)/src/libtimer/libtimer.a \
|
||||
$(top_builddir)/src/libsamplerate/libsamplerate.a \
|
||||
$(top_builddir)/src/libemphasis/libemphasis.a \
|
||||
$(top_builddir)/src/libfsk/libfsk.a \
|
||||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(ALSA_LIBS) \
|
||||
-lm
|
||||
|
||||
if HAVE_ALSA
|
||||
zeitansage_LDADD += \
|
||||
$(top_builddir)/src/libsound/libsound.a \
|
||||
$(ALSA_LIBS)
|
||||
endif
|
||||
|
||||
if HAVE_SDR
|
||||
zeitansage_LDADD += \
|
||||
$(top_builddir)/src/libsdr/libsdr.a \
|
||||
$(top_builddir)/src/libam/libam.a \
|
||||
$(top_builddir)/src/libfft/libfft.a \
|
||||
$(UHD_LIBS) \
|
||||
$(SOAPY_LIBS)
|
||||
endif
|
||||
|
||||
if HAVE_ALSA
|
||||
AM_CPPFLAGS += -DHAVE_ALSA
|
||||
endif
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../libmobile/image.h"
|
||||
|
||||
const char *image[] = {
|
||||
"",
|
||||
" @G___________________________",
|
||||
" / \\",
|
||||
" / ___________________ \\",
|
||||
" @w()@G|-------/ \\-------|",
|
||||
" @w() @G\\_____| @Y\\ @r| / @G|_____/",
|
||||
" @w() @G| @r\\ @Y\\ @r/ @G|",
|
||||
" @w() (@G| @Y\\ @G | @y\"@BBeim naechsten Ton ist es",
|
||||
" @w() () @G| @r-- @Y| @r-- @G| @B17 Urrr,",
|
||||
" @w() () @G| @Y| @G| @B55 Minuten",
|
||||
" @w()()() @G| @r/ \\ @G| @Bund 20 Sekunden.@y\"",
|
||||
" @G| @r/ | \\ @G|",
|
||||
" @G| |",
|
||||
" @G\\_________________/",
|
||||
"",
|
||||
" @W* Zeitansage: 1191 *",
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
|
||||
void print_image(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; image[i]; i++) {
|
||||
for (j = 0; j < (int)strlen(image[i]); j++) {
|
||||
if (image[i][j] == '@') {
|
||||
j++;
|
||||
switch(image[i][j]) {
|
||||
case 'k': /* black */
|
||||
printf("\033[0;30m");
|
||||
break;
|
||||
case 'r': /* red */
|
||||
printf("\033[0;31m");
|
||||
break;
|
||||
case 'g': /* green */
|
||||
printf("\033[0;32m");
|
||||
break;
|
||||
case 'y': /* yellow */
|
||||
printf("\033[0;33m");
|
||||
break;
|
||||
case 'b': /* blue */
|
||||
printf("\033[0;34m");
|
||||
break;
|
||||
case 'm': /* magenta */
|
||||
printf("\033[0;35m");
|
||||
break;
|
||||
case 'c': /* cyan */
|
||||
printf("\033[0;36m");
|
||||
break;
|
||||
case 'w': /* white */
|
||||
printf("\033[0;37m");
|
||||
break;
|
||||
case 'K': /* bright black */
|
||||
printf("\033[1;30m");
|
||||
break;
|
||||
case 'R': /* bright red */
|
||||
printf("\033[1;31m");
|
||||
break;
|
||||
case 'G': /* bright green */
|
||||
printf("\033[1;32m");
|
||||
break;
|
||||
case 'Y': /* bright yellow */
|
||||
printf("\033[1;33m");
|
||||
break;
|
||||
case 'B': /* bright blue */
|
||||
printf("\033[1;34m");
|
||||
break;
|
||||
case 'M': /* bright magenta */
|
||||
printf("\033[1;35m");
|
||||
break;
|
||||
case 'C': /* bright cyan */
|
||||
printf("\033[1;36m");
|
||||
break;
|
||||
case 'W': /* bright white */
|
||||
printf("\033[1;37m");
|
||||
break;
|
||||
}
|
||||
} else
|
||||
printf("%c", image[i][j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\033[0;39m");
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/* Zeitansage main
|
||||
*
|
||||
* (C) 2020 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmobile/main_mobile.h"
|
||||
#include "../liboptions/options.h"
|
||||
#include "zeitansage.h"
|
||||
#include "samples.h"
|
||||
|
||||
double audio_level_dBm = -16.0;
|
||||
int alerting = 0;
|
||||
|
||||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
main_mobile_print_help(arg0, "-c hw:0,0 ");
|
||||
/* - - */
|
||||
printf(" -G --gain\n");
|
||||
printf(" Gain of audio level relative to 1 mW on a 600 Ohm line. (default = %.0f)\n", audio_level_dBm);
|
||||
printf(" -A --alerting\n");
|
||||
printf(" Play as early audio while alerting. Don't send a connect.\n");
|
||||
main_mobile_print_hotkeys();
|
||||
}
|
||||
|
||||
static void add_options(void)
|
||||
{
|
||||
main_mobile_add_options();
|
||||
option_add('G', "gain", 1);
|
||||
option_add('A', "alerting", 0);
|
||||
}
|
||||
|
||||
static int handle_options(int short_option, int argi, char **argv)
|
||||
{
|
||||
switch (short_option) {
|
||||
case 'G':
|
||||
audio_level_dBm = atof(argv[argi]);
|
||||
break;
|
||||
case 'A':
|
||||
alerting = 1;
|
||||
send_patterns = 0;
|
||||
break;
|
||||
default:
|
||||
return main_mobile_handle_options(short_option, argi, argv);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc, argi;
|
||||
|
||||
/* init system specific tones */
|
||||
init_samples();
|
||||
|
||||
main_mobile_init();
|
||||
|
||||
/* handle options / config file */
|
||||
add_options();
|
||||
rc = options_config_file("~/.osmocom/analog/zeitansage.conf", handle_options);
|
||||
if (rc < 0)
|
||||
return 0;
|
||||
argi = options_command_line(argc, argv, handle_options);
|
||||
if (argi <= 0)
|
||||
return argi;
|
||||
|
||||
/* inits */
|
||||
fm_init(fast_math);
|
||||
zeit_init(audio_level_dBm, alerting);
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, "1191", 4);
|
||||
|
||||
//fail:
|
||||
/* exits */
|
||||
zeit_exit();
|
||||
fm_exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
|||
|
||||
void init_samples(void);
|
||||
|
|
@ -0,0 +1,406 @@
|
|||
/* Zeitansage processing
|
||||
*
|
||||
* (C) 2020 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "zeitansage.h"
|
||||
|
||||
#define db2level(db) pow(10, (double)(db) / 20.0)
|
||||
|
||||
/* list of calls */
|
||||
zeit_call_t *zeit_call_list = NULL;
|
||||
|
||||
double audio_gain;
|
||||
double early_audio;
|
||||
|
||||
#define BEEP_TIME 16000 /* adjust distance from beep in samples */
|
||||
|
||||
int16_t *bntie_spl;
|
||||
int bntie_size;
|
||||
int bntie_time; /* sample index when intro is over */
|
||||
int16_t *urrr_spl[24];
|
||||
int urrr_size[24];
|
||||
int urrr_time; /* sample index when hour is over */
|
||||
int16_t *minuten_spl[60];
|
||||
int minuten_size[60];
|
||||
int minuten_time; /* sample index when minute is over */
|
||||
int16_t *sekunden_spl[60];
|
||||
int sekunden_size[60];
|
||||
int sekunden_time; /* sample index when second is over */
|
||||
int16_t *tut_spl;
|
||||
int tut_size;
|
||||
int tut_time; /* sample index when beep is over */
|
||||
|
||||
static const char *call_state_name(enum zeit_call_state state)
|
||||
{
|
||||
static char invalid[16];
|
||||
|
||||
switch (state) {
|
||||
case ZEIT_CALL_NULL:
|
||||
return "(NULL)";
|
||||
case ZEIT_CALL_BEEP:
|
||||
return "BEEP";
|
||||
case ZEIT_CALL_INTRO:
|
||||
return "INTRO";
|
||||
case ZEIT_CALL_HOUR:
|
||||
return "HOUR";
|
||||
case ZEIT_CALL_MINUTE:
|
||||
return "MINUTE";
|
||||
case ZEIT_CALL_SECOND:
|
||||
return "SECOND";
|
||||
case ZEIT_CALL_PAUSE:
|
||||
return "PAUSE";
|
||||
}
|
||||
|
||||
sprintf(invalid, "invalid(%d)", state);
|
||||
return invalid;
|
||||
}
|
||||
|
||||
static void zeit_display_status(void)
|
||||
{
|
||||
zeit_call_t *call;
|
||||
|
||||
display_status_start();
|
||||
for (call = zeit_call_list; call; call = call->next)
|
||||
display_status_subscriber(call->caller_id, call_state_name(call->state));
|
||||
display_status_end();
|
||||
}
|
||||
|
||||
|
||||
static void call_new_state(zeit_call_t *call, enum zeit_call_state new_state)
|
||||
{
|
||||
if (call->state == new_state)
|
||||
return;
|
||||
PDEBUG(DZEIT, DEBUG_DEBUG, "State change: %s -> %s\n", call_state_name(call->state), call_state_name(new_state));
|
||||
call->state = new_state;
|
||||
zeit_display_status();
|
||||
}
|
||||
|
||||
/* global init */
|
||||
int zeit_init(double audio_level_dBm, int alerting)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* the recordings are speech level, so we apply gain as is */
|
||||
audio_gain = db2level(audio_level_dBm);
|
||||
|
||||
early_audio = alerting;
|
||||
|
||||
/* get maximum length for each speech segment */
|
||||
tut_time = BEEP_TIME;
|
||||
bntie_time = bntie_size + tut_time;
|
||||
urrr_time = 0;
|
||||
for (i = 0; i < 24; i++) {
|
||||
if (urrr_size[i] > urrr_time)
|
||||
urrr_time = urrr_size[i];
|
||||
}
|
||||
urrr_time += bntie_time;
|
||||
minuten_time = 0;
|
||||
for (i = 0; i < 60; i++) {
|
||||
if (minuten_size[i] > minuten_time)
|
||||
minuten_time = minuten_size[i];
|
||||
}
|
||||
minuten_time += urrr_time;
|
||||
sekunden_time = 0;
|
||||
for (i = 0; i < 60; i += 10) {
|
||||
if (sekunden_size[i] > sekunden_time)
|
||||
sekunden_time = sekunden_size[i];
|
||||
}
|
||||
sekunden_time += minuten_time;
|
||||
|
||||
PDEBUG(DZEIT, DEBUG_DEBUG, "Total time to play anouncement, starting with beep: %.2f seconds\n", (double)sekunden_time / 8000.0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* global exit */
|
||||
void zeit_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* calculate what time to speak */
|
||||
static void zeit_calc_time(zeit_call_t *call, time_t time_sec)
|
||||
{
|
||||
struct tm *tm;
|
||||
|
||||
/* we speak 10 seconds in advance */
|
||||
time_sec += 10;
|
||||
|
||||
tm = localtime(&time_sec);
|
||||
call->h = tm->tm_hour;
|
||||
call->m = tm->tm_min;
|
||||
call->s = tm->tm_sec;
|
||||
|
||||
PDEBUG(DZEIT, DEBUG_INFO, "The time at the next beep is: %d:%02d:%02d\n", call->h, call->m, call->s);
|
||||
}
|
||||
|
||||
static void call_timeout(struct timer *timer);
|
||||
|
||||
/* Create call instance */
|
||||
static zeit_call_t *zeit_call_create(uint32_t callref, const char *id)
|
||||
{
|
||||
zeit_call_t *call, **callp;
|
||||
double now, time_offset;
|
||||
time_t time_sec;
|
||||
|
||||
PDEBUG(DZEIT, DEBUG_INFO, "Creating call instance to play time for caller '%s'.\n", id);
|
||||
|
||||
/* create */
|
||||
call = calloc(1, sizeof(*call));
|
||||
if (!call) {
|
||||
PDEBUG(DZEIT, DEBUG_ERROR, "No mem!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* init */
|
||||
call->callref = callref;
|
||||
strncpy(call->caller_id, id, sizeof(call->caller_id) - 1);
|
||||
timer_init(&call->timer, call_timeout, call);
|
||||
now = get_time();
|
||||
time_offset = fmod(now, 10.0);
|
||||
time_sec = (int)floor(now / 10.0) * 10;
|
||||
call->spl_time = (int)(time_offset * 8000.0);
|
||||
zeit_calc_time(call, time_sec);
|
||||
timer_start(&call->timer, 10.0 - time_offset);
|
||||
|
||||
/* link */
|
||||
callp = &zeit_call_list;
|
||||
while ((*callp))
|
||||
callp = &(*callp)->next;
|
||||
(*callp) = call;
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
/* Destroy call instance */
|
||||
static void zeit_call_destroy(zeit_call_t *call)
|
||||
{
|
||||
zeit_call_t **callp;
|
||||
|
||||
/* unlink */
|
||||
callp = &zeit_call_list;
|
||||
while ((*callp) != call)
|
||||
callp = &(*callp)->next;
|
||||
(*callp) = call->next;
|
||||
|
||||
/* cleanup */
|
||||
timer_exit(&call->timer);
|
||||
|
||||
/* destroy */
|
||||
free(call);
|
||||
|
||||
/* update display */
|
||||
zeit_display_status();
|
||||
}
|
||||
|
||||
/* play samples for one call */
|
||||
static void call_play(zeit_call_t *call)
|
||||
{
|
||||
int i = 0;
|
||||
int16_t chunk[160];
|
||||
sample_t spl[160];
|
||||
int16_t *play_spl; /* current sample */
|
||||
int play_size; /* current size of sample*/
|
||||
int play_index; /* current sample index */
|
||||
int play_max; /* total length to plax */
|
||||
int spl_time; /* sample offset from start of 10 minutes */
|
||||
|
||||
spl_time = call->spl_time;
|
||||
|
||||
next_sample:
|
||||
/* select sample from current sample time stamp */
|
||||
if (spl_time < tut_time) {
|
||||
play_index = spl_time;
|
||||
play_max = tut_time;
|
||||
play_size = tut_size;
|
||||
play_spl = tut_spl;
|
||||
call_new_state(call, ZEIT_CALL_BEEP);
|
||||
} else
|
||||
if (spl_time < bntie_time) {
|
||||
play_index = spl_time - tut_time;
|
||||
play_max = bntie_time - tut_time;
|
||||
play_size = bntie_size;
|
||||
play_spl = bntie_spl;
|
||||
call_new_state(call, ZEIT_CALL_INTRO);
|
||||
} else
|
||||
if (spl_time < urrr_time) {
|
||||
play_index = spl_time - bntie_time;
|
||||
play_max = urrr_time - bntie_time;
|
||||
play_size = urrr_size[call->h];
|
||||
play_spl = urrr_spl[call->h];
|
||||
call_new_state(call, ZEIT_CALL_HOUR);
|
||||
} else
|
||||
if (spl_time < minuten_time) {
|
||||
play_index = spl_time - urrr_time;
|
||||
play_max = minuten_time - urrr_time;
|
||||
play_size = minuten_size[call->m];
|
||||
play_spl = minuten_spl[call->m];
|
||||
call_new_state(call, ZEIT_CALL_MINUTE);
|
||||
} else
|
||||
if (spl_time < sekunden_time) {
|
||||
play_index = spl_time - minuten_time;
|
||||
play_max = sekunden_time - minuten_time;
|
||||
play_size = sekunden_size[call->s];
|
||||
play_spl = sekunden_spl[call->s];
|
||||
call_new_state(call, ZEIT_CALL_SECOND);
|
||||
} else {
|
||||
play_index = 0;
|
||||
play_max = 0;
|
||||
play_size = 0;
|
||||
play_spl = NULL;
|
||||
call_new_state(call, ZEIT_CALL_PAUSE);
|
||||
}
|
||||
|
||||
while (i < 160) {
|
||||
if (!play_size) {
|
||||
chunk[i++] = 0.0;
|
||||
continue;
|
||||
}
|
||||
/* go to next sample */
|
||||
if (play_index == play_max)
|
||||
goto next_sample;
|
||||
/* announcement or silence, if finished or not set */
|
||||
if (play_index < play_size)
|
||||
chunk[i++] = play_spl[play_index];
|
||||
else
|
||||
chunk[i++] = 0.0;
|
||||
play_index++;
|
||||
spl_time++;
|
||||
}
|
||||
|
||||
call->spl_time = spl_time;
|
||||
|
||||
/* convert to samples, apply gain and send toward fixed network */
|
||||
int16_to_samples(spl, chunk, 160);
|
||||
for (i = 0; i < 160; i++)
|
||||
spl[i] *= audio_gain;
|
||||
call_up_audio(call->callref, spl, 160);
|
||||
}
|
||||
|
||||
/* loop through all calls and play the announcement */
|
||||
void call_down_clock(void)
|
||||
{
|
||||
zeit_call_t *call;
|
||||
|
||||
for (call = zeit_call_list; call; call = call->next) {
|
||||
/* no callref */
|
||||
if (!call->callref)
|
||||
continue;
|
||||
/* beep or announcement */
|
||||
call_play(call);
|
||||
}
|
||||
}
|
||||
|
||||
/* Timeout handling */
|
||||
static void call_timeout(struct timer *timer)
|
||||
{
|
||||
zeit_call_t *call = (zeit_call_t *)timer->priv;
|
||||
double now, time_offset;
|
||||
time_t time_sec;
|
||||
|
||||
PDEBUG(DZEIT, DEBUG_INFO, "Beep!\n");
|
||||
|
||||
now = get_time();
|
||||
|
||||
time_offset = fmod(now, 10.0);
|
||||
time_sec = (int)floor(now / 10.0) * 10;
|
||||
/* if somehow the timer fires (a tiny bit) before the 10 seconds start */
|
||||
if (time_offset > 5.0) {
|
||||
time_offset -= 10.0;
|
||||
time_sec += 10;
|
||||
}
|
||||
call->spl_time = 0;
|
||||
zeit_calc_time(call, time_sec);
|
||||
timer_start(&call->timer, 10.0 - time_offset);
|
||||
}
|
||||
|
||||
/* Call control starts call towards clock */
|
||||
int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, enum number_type __attribute__((unused)) caller_type, const char *dialing)
|
||||
{
|
||||
zeit_call_t __attribute__((unused)) *call;
|
||||
|
||||
/* create call process to page station or send out-of-order message */
|
||||
call = zeit_call_create(callref, caller_id);
|
||||
if (early_audio) {
|
||||
call_up_alerting(callref);
|
||||
call_up_early(callref);
|
||||
} else
|
||||
call_up_answer(callref, dialing);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void call_down_answer(int __attribute__((unused)) callref)
|
||||
{
|
||||
}
|
||||
|
||||
static void _release(int callref, int __attribute__((unused)) cause)
|
||||
{
|
||||
zeit_call_t *call;
|
||||
|
||||
PDEBUG(DZEIT, DEBUG_INFO, "Call has been disconnected by network.\n");
|
||||
|
||||
for (call = zeit_call_list; call; call = call->next) {
|
||||
if (call->callref == callref)
|
||||
break;
|
||||
}
|
||||
if (!call) {
|
||||
PDEBUG(DZEIT, DEBUG_NOTICE, "Outgoing disconnect, but no callref!\n");
|
||||
call_up_release(callref, CAUSE_INVALCALLREF);
|
||||
return;
|
||||
}
|
||||
|
||||
zeit_call_destroy(call);
|
||||
}
|
||||
|
||||
/* Call control sends disconnect.
|
||||
* A queued ID will be kept until transmitted by mobile station.
|
||||
*/
|
||||
void call_down_disconnect(int callref, int cause)
|
||||
{
|
||||
_release(callref, cause);
|
||||
|
||||
call_up_release(callref, cause);
|
||||
}
|
||||
|
||||
/* Call control releases call toward mobile station. */
|
||||
void call_down_release(int callref, int cause)
|
||||
{
|
||||
_release(callref, cause);
|
||||
}
|
||||
|
||||
/* Receive audio from call instance. */
|
||||
void call_down_audio(int __attribute__((unused)) callref, sample_t __attribute__((unused)) *samples, int __attribute__((unused)) count)
|
||||
{
|
||||
}
|
||||
|
||||
void dump_info(void) {}
|
||||
|
||||
void sender_receive(sender_t __attribute__((unused)) *sender, sample_t __attribute__((unused)) *samples, int __attribute__((unused)) length, double __attribute__((unused)) rf_level_db) {}
|
||||
void sender_send(sender_t __attribute__((unused)) *sender, sample_t __attribute__((unused)) *samples, uint8_t __attribute__((unused)) *power, int __attribute__((unused)) length) {}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include "../libfm/fm.h"
|
||||
#include "../libmobile/sender.h"
|
||||
#include "../libtimer/timer.h"
|
||||
|
||||
/* current state of incoming call */
|
||||
enum zeit_call_state {
|
||||
ZEIT_CALL_NULL = 0,
|
||||
ZEIT_CALL_BEEP, /* play beep at the beginnung of each 10 seconds period */
|
||||
ZEIT_CALL_INTRO, /* play intro sample */
|
||||
ZEIT_CALL_HOUR, /* play hour sample */
|
||||
ZEIT_CALL_MINUTE, /* play minute sample */
|
||||
ZEIT_CALL_SECOND, /* play second sample */
|
||||
ZEIT_CALL_PAUSE, /* pause until next 10 seconds period */
|
||||
};
|
||||
|
||||
/* instance of incoming call */
|
||||
typedef struct zeit_call {
|
||||
struct zeit_call *next;
|
||||
int callref; /* call reference */
|
||||
struct timer timer;
|
||||
enum zeit_call_state state; /* current state */
|
||||
char caller_id[32]; /* caller id to be displayed */
|
||||
int spl_time; /* sample offset within 10 seconds */
|
||||
int h, m, s; /* what hour, minute, second to play */
|
||||
} zeit_call_t;
|
||||
|
||||
int zeit_init(double audio_level_dBm, int alerting);
|
||||
void zeit_exit(void);
|
||||
|
Loading…
Reference in New Issue