dtmfbox (AB/CB/CT VoIP/ISDN/Analog)

das komische ist ja, dass die dtmfbox bei 80% liegt und nicht madplay... andersrum würde ich es verstehen. aber madplay ist echt effektiv. und die dtmfbox rechnet ja auch nicht viel. es ist also wirklich so, dass sie vermutlich in irgendwelchen idle_loops sich aufhält und cpu verbrät. wenn andere tasks laufen würden, dann würde der scheduler der dtmfbox da was abzweigen ohne dass es stört, aber wenn nix läuft nimmt sie sich das halt, wenn man es mal so unformell ausdrückt.

EDIT: ok, dann passts ja. wollt ja nur drauf hinweisen, dass es so ist :)

EDIT2: Assertion `validapplid(applid)' failed kommt bei der beta3 beim beenden auch noch. Einen Segmentation fault gibt es manchmal wenn nichts von der pipe zu lesen ist. habe das aber noch nicht ganz getestet wo der genau auftritt. hat auf jeden fall was mitm waveplayer und der pipe zu tun. tritt aber auch nur auf, wenns mitm schreiben in die pipe nicht so ganz klappt.
Abundzu hängt sich die dtmfbox bei Ctrl-C auch einfach auf ohne vorher eine weitere meldung zu geben. Vllt. direkt im Sigterm handler eine endlosschleife oder ähnliches?
 
Zuletzt bearbeitet:
Habe das Binary auf dem Server nochmal ausgetauscht. Ob es was gebracht hat, kann ich allerdings nicht genau sagen. Bei meinen bisherigen Tests ging dtmfbox auf max. 25%. Es muss aber irgendwas mit dem Lesen und Schreiben auf dem Named Pipe zu tun haben.
 
Ich hofe nicht, dass ich euch da in eine Sackgasse gelotst habe :-(, aber denke doch, dass es zumindest kaum "schlechter" sein dürfte, als lesen von STDIN...

Jörg
 
MaxMuster schrieb:
Ich hofe nicht, dass ich euch da in eine Sackgasse gelotst habe

Würde ich nicht sagen. Named Pipe ist sehr komfortabel. Die Auslastung kann genausogut bei stdin auftreten. stdin fänd ich sogar schwerer umzusetzen.

Es ist ja auch noch nicht ganz fertig. Zumal bis gestern wusste ich nichtmal, dass es Named Pipes gibt ;)

Alles in allem schon recht brauchbar. Es fehlen noch die Feinschliffe (z.B. der Segfault, wenn in der Pipe nichts mehr zu lesen gibt, Resampler, etc.)...

Die CPU-Auslastung scheint sich jetzt auch zwischen 0-25% eingependelt zu haben. Müsstet ihr mal probieren, ob es bei euch genauso ist.
 
Der erste Test ging leider daneben (Box hat sich beim Starten einfach aufgehängt), vermutlich ist meine Eumex-Box mit dem ds-mod zusammen einfach "zu klein", oder es liegt an klassicher "Fehlbedienung" ;-).
Ich habe aber im Moment nicht richtig Zeit, da länger nachzuforschen. Kann leider also nichts produktives dazu beitragen.

Jörg
 
@bodega:
Das neue binary nimmt weniger CPU in Anspruch. Bei mir auch nur 20-25 % .

Ich hab madplay noch optimiert (also beim compilieren). Mit CFLAGS="-O3 -march=mips32" läuft es jetzt mit nur noch 8% CPU statt 16-20%.
Ich habe sogar bei libmad die option --enable-accuracy aktiviert, statt --enable-speed wie letztes mal. sowas auch. find auch (bzw. bilde es mir ein... placebo effect ;) ) es klingt jetzt etwas besser, wobei das eh mehr durch die 8khz beim Tel. eingeschränkt wird als durch die mp3 decoder Qualität.

Im neuen tar.gz ist ein install skript drin , der ist aber nicht sinnvoll, ausser für meine konfig. wichtig ist nur das neue binary (heisst jetzt madplaybin). madplay selber ist nur ein skript, der den lib path setzt und madplaybin startet (der muss auch an die individuellen konfigs angepasst werden, oder einfach gleich madplaybin verwenden. die libs sind auch neu, da ja v.a. libmad die decoder teile enthält.
 

Anhänge

  • mad-fbox.tgz
    192.5 KB · Aufrufe: 15
Telefon-Recorder

Ich würde gerne Telefongespräche mitschneiden können.
Geht das schon bzw. ist das geplant?
Und wie würde das realisiert?
Jörg
 
MaxMuster schrieb:
Der erste Test ging leider daneben (Box hat sich beim Starten einfach aufgehängt), vermutlich ist meine Eumex-Box mit dem ds-mod zusammen einfach "zu klein", oder es liegt an klassicher "Fehlbedienung"
Die Beta hatte ich für USB ausgelegt. Mit der Standalone oder dsmod könnte es besser funktionieren (wobei die erst beim Release erstellt werden). Die Binaries hab ich mittlerweile etwas kleiner bekommen:

@all:
dtmfbox hat nun 650kb und die busybox nur noch 137kb. Habe die ganzen Asserts weggelassen. eSpeak wird jetzt auch gestreamed, was echt schnell geht :).
Ansagen können optional von URL abgespielt und Aufnahmen auf FTP abgelegt werden - für die 7050 wahrscheinlich interessant, da nichts mehr auf der Box gespeichert werden muss (außer das Programm und die Konfig). Länge der Ansagen/Aufnahmen spielen also keine Rolle mehr.

Hab jetzt auch noch die Parameter "-playstream [hz] [fifo] / -recordstream [hz] [fifo]" miteingebaut.

Der Speicherverbrauch hat sich verbessert und CTRL+C sollte auch etwas zuverlässiger sein.
Am DDI-Präfix müsste ich nochmal ran (zumindest gibt es die Einstellung schonmal im WebIF ;))...

Ich werde die beta-4 heute abend posten.

@florixyz + @MaxMuster:
Das Streamen ist echt stark. Danke nochmal für eure Ideen!

EDIT:
v0.4.0-beta4
CTRL+C während eines Anrufs möglichst nicht machen ;)
Was auch noch fehlt wäre eine Überprüfung, ob der Stream auch wirklich abgespielt werden kann. Es könnte sonst die Applikation blocken. Bei espeak nicht so das Problem aber bei Ansage (URL) und Aufnahmen (FTP).
Immerhin besser als beta3, finde ich.

EDIT2:
eSpeak für FB7050 :
Online Text2Speech
 
Zuletzt bearbeitet:
ich hab jetzt ein stream mixer geschrieben, der vom stdin lesen kann und gleichzeitig auf einem fifo lauschen kann. die ausgabe erfolgt in eine datei oder auf ein fifo.
man kann jetzt mit "cat wavefile > fifofile" ansagen in den stream mischen. dazu wird die lautstärke des streams automatisch reduziert, sozusagen eine talk-over funktion.

das programm wird so benutzt (vorher natürlich die beiden fifos erzeugen!!):

erst den player der dtmfbox starten:
dtmfbox 0 -playthread /var/tmp/mp3fifo &

dann den stream und den mixer:
wget http://radiator.nci.de:8000/live -O - | ./mad/madplaybin -R 8000 -m -o raw:- - 2>/dev/null | ./mixer2 - /var/tmp/msgfifo /var/tmp/mp3fifo &

jetzt kann man mit "cat wavefile.wav > /var/tmp/msgfifo" was dazwischenmischen.
natürlich alles nur für pcm, 16-bit 8khz !!!!

sourcecode gibts demnächst auch.

das ganze soll mal dazu dienen AB ansagen, mit webradio zu hinterlegen ;)

@bodega: kann es sein, dass es der dtmfbox nicht bekommt wenn man sie mit ctrl-c (sigterm) beendet während der wave-player läuft (mit -playthread)? sie hängt sich dann bei mir immer auf ... und ich muss sie mit sigkill beenden
 

Anhänge

  • mixer.tar
    20 KB · Aufrufe: 7
ähhm...

bodega schrieb:
CTRL+C während eines Anrufs möglichst nicht machen

;). Ich arbeite dran. Wobei, probiere mal beta4 aus.
 
oops, sorry, hab deinen edit nicht rechtzeitig gesehen. war ja schon spät als ich gepostet hab ;)

ich werd mal heut abend die beta4 testen.
zum testen ob vom stream gelesen werden kann:
wie öffnest du denn den stream wenn man -playstram verwendet? man kann es mit open() machen, da die option O_NONBLOCK angeben und dann mit select() warten bis vom stream gelesen werden kann, dann noch überprüfen ob read eine zahl > 0 zurückgibt, dann sollte nix mehr blocken. schau dir den sourcecode des mixers an, sobald ich ihn gepostet hab (evtl. heut abend oder morgen)
 
Den Stream öffne ich mit fopen. Du hast natürlich recht, da open() mehr Möglichkeiten bietet, alleine durch das select().
Müsste nur nachschauen ob Windows das auch kann, schätze aber nicht (#ifdef :().
 
bodega schrieb:
Den Stream öffne ich mit fopen. Du hast natürlich recht, da open() mehr Möglichkeiten bietet, alleine durch das select().
Müsste nur nachschauen ob Windows das auch kann, schätze aber nicht (#ifdef :().

Kann Windows überhaupt named pipes genauso wie linux? (in der Art mkfifo datei...)

EDIT:
Hab jetzt den Sourcecode des Stream mixers und nochmal ein kompiliertes binary angehängt. Falls es jemand dafür verwendung hat... ;)
 

Anhänge

  • streammixer.tar
    30 KB · Aufrufe: 9
Zuletzt bearbeitet:
Hab mich mal etwas eingelesen - es soll angeblich auch unter Windows funktionieren. Z.B. über: \\ServerName\pipe\PipeName.

Müsste ich mal probieren...

florixyz schrieb:
Hab jetzt den Sourcecode des Stream mixers und nochmal ein kompiliertes binary angehängt. Falls es jemand dafür verwendung hat...

Auf jedenfall :) - Das Mixen mehrerer Waves/Pipes ist noch ein Knackpunkt. Ich kam bisher nur noch nicht dazu, es zu testen. Werde das heute abend nachholen.
 
Zuletzt bearbeitet:
ich habe grad die beta4 ausprobiert. ich muss sagen, ich bin begeistert!
die playstream funktion funktioniert, auch zusammen mit dem mixer tadellos. bei der beta3 hatte ich noch das problem, dass bei erneutem aufruf von playthread noch alte daten in der pipe waren (obwohl ich sie gelöscht und neu erstellt hatte). das ist jetzt bei playstream nicht mehr.

gäbe es eine möglichkeit -playstreamthread oder so ähnlich zu implementieren? bzw. wann beendet dtmfbox wenn mit -playstream gestartet? Ich starte es eh mit & im Hintergrund, und nach dem DISCONNECT ist es weg, aber sauberer und manchmal vllt. praktischer wäre es wenn der aufruf gleich zurückkehrt. evtl. hätten wir dann auch keine probleme wenn der player blockiert solange bis von der pipe gelesen werden kann.

leider ist die sache mit ctrl-c und dem aufhängen während dem play immer noch. es sieht so aus als ob er zwei von den 6 dtmfbox threads die unter ps zu sehen sind beendet, vier laufen weiter und hängen (oder auch nur einer davon...)
ich finde aber jetzt das stört nicht soo sehr. man kann ja vorher auflegen ;)

EDIT:
hmmmm... hab eine segfault entdeckt wenn ich folgendes skript laufen lasse, während ich intern abhebe ($D und $M enthalten pfade, die gibt es auch...) (das wave file wird ordnungsgemäß gespeichert):
Code:
$D/dtmfbox 0 -hook up ;
$D/dtmfbox 0 -record $M/$1 ;
read YN
$D/dtmfbox -stop record ;
$D/dtmfbox 0 -hook down
in der beta3 hat das funktioniert.

hier ist das log:
Code:
23:26:45.125 script_funcs.c Run script: "/var/stick/dist/abscript.sh" "CONFIRMED" "CAPI" "OUTGOING" "0" "-1" "<mymsn>" "00" "1" &
sh: /var/stick/dist/abscript.sh: not found
 23:26:45.195  capi_events.c (IND, CTRL 3, PLCI: 2563, NCCI: 68099) - CAPI_CONNECT_B3
 23:26:45.197  capi_events.c (IND, CTRL 3, PLCI: 2563, NCCI: 68099) - CAPI_CONNECT_B3_ACTIVE
 23:26:45.198   capi_funcs.c Enable DTMF for NCCI 68099
 23:26:45.200    capi_ctrl.c (CNF, CTRL 3, PLCI: 2563, NCCI: 68099) - CAPI_FACILITY
 23:26:45.234 script_funcs.c Queue no.: 1, (pending: 1)
 23:26:45.234 script_funcs.c [0] - recording /var/stick/dist/abmain.wav2...
 23:26:45.237   wav_writer.c File writer '/var/stick/dist/abmain.wav2' created: samp.rate=8000, bufsize=4KB
 23:26:47.355 script_funcs.c Queue no.: 2, (pending: 1)
 23:26:47.434 script_funcs.c Queue no.: 3, (pending: 1)
 23:26:47.436 script_funcs.c [0] - hook down!
 23:26:47.438  capi_events.c (IND, CTRL 3, PLCI: 2563) - CAPI_INFO (0x001e) - PROGRESS INDICATOR (0x02)
 23:26:47.439  capi_events.c (IND, CTRL 3, PLCI: 2563) - CAPI_INFO (0xc000) - UNKNOWN INFO
 23:26:47.439  capi_events.c (IND, CTRL 3, PLCI: 2563, NCCI: 68099) - CAPI_DISCONNECT_B3
 23:26:47.441 script_funcs.c Run script: "/var/stick/dist/abscript.sh" "DISCONNECT" "CAPI" "OUTGOING" "0" "-1" "<mymsn>" "00" "1" &
sh: /var/stick/dist/abscript.sh: not found
Segmentation fault
er findet das skript abscript.sh nicht, das ist aber ok, mit script geht es auch nicht, liegt also nicht daran. wollte nur testen obs auch wirklich nicht am script liegt, deswegen hab ichs umbenannt.

EDIT2:
MIt der beta4 geht -play <datei> auch nicht mehr. bei mir hat er einfach nix abgespielt. gleiche befehle, beta3, da gehts. muss also irgendwas mit den neuen änderungen zu tun haben. playstream allerdings geht wie gesagt prima

EDIT3:
mit -playstream -recordstream gibt es in der beta4 keinerlei probleme. kann auch in raw datein speichern und davon lesen.
 
Zuletzt bearbeitet:
Und ich kompiliere keine Asserts mit - das hätte ich nicht tun sollen. :-o

Bei '-stop record' müsstest du eigentlich auch die Connection-ID mitübergeben (es soll ja die Aufnahme der jew. Verbindung beendet werden). Ob es damit zu tun haben könnte, werde ich testen...

Habe mich wohl zu sehr auf -playstream/-recordstream konzentiert, wobei bei mir -play und -record auch funktioniert haben. Ich gehe stark davon aus, dass der Resampler hier das Problem verursacht.

-playstreamthread werde ich miteinbauen (aber auf open()-Basis). Ein Timeout für's Blocken wäre sicherlich auch sinnvoll.
 
ctrl-c und aufhängen

ich bin dem problem ein bisschen auf den grund gegangen via printf debugging... fazit: er bleibt im CAPI20_WaitforMessage hängen, und genauer gesagt dort im select() aufruf, der trotz timeout niemals zurückkehrt!
Habe bereits eine lock variable eingeführt, die gesetzt wird während der eine thread in waitformessage ist. solange diese variable gesetzt ist kann der andere thread nicht CAPI20_RELEASE aufrufen.
hab auch mal nach select() never returns gegoogelt und es sieht so aus, als ob irgendein dritter thread noch auf den capi device file descriptor zugreift während capi20_waitformessage aktiv ist. ne idee wo im code das sein könnte?

EDIT:
hab gesehen, dass aus dem grund des blockens CAPI20_RELEASE im SignalHandler extra aufgerufen wird. Leider hilft das nicht immer.
Wozu ist aber dieser code im signalHandler gut: ??
Code:
        while(closing != 2)
        {

            #ifdef DTMFBOX_WIN32
                // Same as DoEvents()
                GetMessage(message, 0, 0, 0);
                TranslateMessage(message);
                DispatchMessage(message);        
            #else
                pj_thread_sleep(100);
            #endif
        }
        exit(0);

wenn ich davor ein return einfüge, dann beendet die dtmfbox IMMER ordnungsgemäß. Auch während dem abspielen von streams.
(
Info: Wenn der Hauptthread in dem auch capi_listen() läuft, SIGTERM bekommt, dann wird er unterbrochen (und das heisst auch select() wird angehalten, deswegen blockt capi20_waitformessage). wenn der sighandler jetzt nicht sich beendet, dann wird der prozess niemals fortgesetzt und damit block select() unendlich lange... und damit die ganze dtmfbox, da closing==2 niemals erreicht wird, da capi_listen niemals beendet wird.... ;)
)

Das einzige Problem dann: die gestarteten scripte laufen weiter. EDIT: lässt sich aber mit einem wrapper script folgender Art lösen:
Code:
./dtmfbox -cfg cfg ;
sleep 1;
kill `pidof dtmfbox`;
kill `pidof <scriptfile>`;

( edit: text entfernt .. hab gesehen system("... &") wird aufgerufen, d.h. die shell startet denn einen neuen prozess. ist ok so, ausser dass man keine pid hat, die man nach ctrl-c beenden kann. )

EDIT:
@bodega:
zu gloablen variablen:
du definierst sie in "config.h" mit "int <varname>;"
d.h. in jeden eigenen object wird eine eigene lokale instanz erzeugt (theoretisch), dadurch kann es passieren, dass in einem thread die globale variable nur lokal ist (??).
besser so:
Code:
// --------------------------------------------------------------------------------------------
// Global structs & variables
// --------------------------------------------------------------------------------------------
#ifdef __DTMFBOX_C
#define __EXTERN
#else
#define __EXTERN extern
#endif
__EXTERN struct APP_SETTINGS   oSettings;                                // application-settings
__EXTERN struct CONNECTION     oCON;                                     // current connection (temporary)
__EXTERN struct CONNECTION     oCONS[CAPI_SLOTS];                        // all connections

// global variables
__EXTERN char current_exe[512];                                          // This binary (from startargs)
__EXTERN char workdir[512];                                              // Working directory
__EXTERN char logfile[512];                                              // Parameter: Logfile (-log)
__EXTERN char configfile[512];                                           // Parameter: Config file (-cfg)
__EXTERN int closing;                                                    // When 1, it stops the listen-loop and exits application
__EXTERN int daemonized;                                                 // Parameter: Daemon mode (-daemon)
__EXTERN int foreground;                                                 // Parameter: Start in foreground (-start)

__EXTERN pj_thread_t *SignalThread;                                      // SignalThread for process communication
und in "dtmfbox.c" dann als erste Zeile:
Code:
#define __DTMFBOX_C
 
Zuletzt bearbeitet:
florixyz schrieb:
Wozu ist aber dieser code im signalHandler gut: ??

Die while-Schleife hatte ich mal eingebaut, damit voip_listen() noch ein bisschen laufen kann (um Meldungen abzuholen). Ich bin mir nicht sicher, ob das mal zum Workaround gedient hatte, da die Registrierung beim VoIP-Provider nicht immer aufgehoben wurde. Wenn das auf der FB Probleme macht, sollte man es rausnehmen. Ich müsste nur nochmal einen Blick auf die Registrierungssache werfen.

Zu den Globals:
Das würde bedeuten, die Variablen werden in dtmfbox.c reserviert und in anderen Dateien, per extern, global, zur Verfügung gestellt (??). Finde ich auch besser :)

EDIT:
ich hab das mal mit mehreren play-ports probiert und es klappt erstmal gut. Eigentlich kein großer Aufwand gewesen.
Bei '-stop play' wird dann immer der letzte play_port geschlossen (der Einfachkeit halber).

EDIT2:
Ich habe die while-Schleife am Ende rausgenommen und die 'extern' Definition übernommen. Thx florixyz.
Der Parameter '-playstreamthread' ist auch eingebaut. Man kann nun bis zu 10 Dateien oder Streams parallel abspielen.
Ist im Trunk zu finden...
 
Zuletzt bearbeitet:
florixyz schrieb:
zu gloablen variablen:
du definierst sie in "config.h" mit "int <varname>;"
d.h. in jeden eigenen object wird eine eigene lokale instanz erzeugt (theoretisch), dadurch kann es passieren, dass in einem thread die globale variable nur lokal ist (??).
C-Compier unter Unix (so auch gcc) legen üblicher Weise nicht initialisierte globale Variablen im erzeutgen .o Modul als Common-Blöcke an, für die dann erst der Linker den Speicherplatz allokiert (und zwar nur einmal im ganzen Programm, wenn mehrere Module je einen Common-Block mit gleichem Namen enthalten). Daher funktioniert es, wenn zwei Module jeweils z.B. "int xxx;" global defineren - es wird letztendlich trotzdem nur eine Variable xxx im Programm erzeugt, und alle Module benutzen dann diese Variable gemeinsam. Ein Modul mit "int x = 5;" und ein zweiter Modul und "int x = 10;" lassen sich hingegen nicht miteinander linken, weil initialisierte Variablen nicht als Common-Blöcke, sondern im Datensegment angelegt werden (-> Linker schimpft dann über mehrfache Definition des selben Symbols). Wenn nur ein einziger Modul im Programm die Variable initialisiert, dann geht es auch.

Aber obwohl diese Semantik in Unix offenbar seit Jahrzehnten so üblich ist, ist es glaub' ich nicht ANSI-C konform, sich darauf zu verlassen, dass sich der Compiler so verhalten wird. Vor unentdeckten Fehlfunktionen des Programms wegen mehrfacher Instanzierung globaler Variablen braucht man sich aber nicht zu fürchten. Das Schlimmste, was passieren kann, wäre ein Fehler beim Übersetzen mit einem anderen Compiler (-> der Linker schimpft dann über mehrfache Definition des selben Symbols in mehreren Modulen). Und das merkt man dann schon ;)
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.