/*
ztalkd 0.3 vm-version -- full rate ztalkd, using /dev/audio
modified by fein & Albion = feinmann@cs.mcgill.ca & spedge@csd4.csd.uvm.edu

A LOT OF source clean up by fein
Thu Mar 31 02:07:55 EST 1994
All the implicit declarations and unused vars removed.
And commentation error is fixed.

---------------------------------------------------------------------------
sd = Scott Doty, scott@cs.santarosa.edu
Mon Mar 28 03:33:47 PST 1994
Extremely alpha -- use at your own risk -- don't blame me
or these guys:
*/

/* Copyright (C) 1993 Free Software Association of Germany

   The following is only valid, if you use this outside the Federal
   Republic of Germany.

   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, 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.

   If you don't have a a copy of the GNU General Public License
   write to the Free Software Foundation, Inc., 675 Mass Ave, 
   Cambridge, MA 02139, USA.

   (C)opyright 1993,1994 FREE SOFTWARE ASSOCIATION OF GERMANY

   ----------------------------------------------------------------

   Fuer die Nutzung dieses Quell-Codes innerhalb der Bundesrepublik
   Deutschland gilt:

   Dieses Programm ist freie Software und kann unter den Bedingungen
   der Deutschen Free Software Lizenz weitergeben und/oder modifiziert
   werden.

   Wir haben dieses Programm in der Hoffnung entwickelt, dass es
   sich als nuetzlich erweist. Wir uebernehmen jedoch *KEINERLEI*
   Garantien auf die Funktion oder Verwendbarkeit dieses Programms.
   Der Anwender nutzt dieses Programm * AUF EIGENES RISIKO *

   Diesem Programm sollte eine Kopie der Deutschen Free Software Lizenz
   (DFSL) beigefuegt sein. Falls nicht, kann eine Kopie von uns angefordert
   werden: Free Software Association of Germany, Heimatring 19,
   60596 Frankfurt (info@elara.fsag..de), Telefon: ++49 - 69 - 6312083

   (C)opyright 1993,1994 FREE SOFTWARE ASSOCIATION OF GERMANY */

/***
 *** March 28, 1994:  Added "Answering machine" to the ztalkd Daemon.
 ***                  It is more like Voice-Mail. When you are set
 ***                  away, (toggle it from client), time stamped
 ***                  logging files will be generated in /tmp/vmail
 ***                  - Albion - (spedge@csd4.csd.uwm.edu)
 ***                   - fein -  (feinmann@cs.mcgill.ca)
 *** March 30, 1994:  Cleaned up the codes here and there.
 ***                   - fein -  (feinmann@.cs.mcgil.ca)
 ***/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include "ztalk.h"
#include "gsm.h"
#include "s2ul.h"

#ifdef WANT_ANSWER
#include <time.h>
#endif /* WANT_ANSWER */

#ifndef lint
static	char copyright[] =
"@(#) Copyright (c) 1994 Scott Doty, Mods by fein & Albion: release under conditions of the GPL.\n"
"Portions Copyright (c) 1993, 1994 Free Software Association of Germany.\n";
#endif

#ifndef lint
static char sccsid[] = "@(#) ztalkd  Version 0.3-vm"
			" Wed Mar 30 15:51:23 EST 1994\n";
#endif 

#define MAR 7 
#define MARA 5 
#define CNT 1 
#define CCNT 2 

extern void beep(int);
extern void boop(int);
int slow_read(int hd, char *s, int sz);
int decompress_buffer(  METHOD method,
                        unsigned char * buf_receive,
                        int size_receive,
                        unsigned char ** buf_play,
                        int * size_play
                        );

static	unsigned char * buf_receive;


void main(int argc, char **argv) {
    int a,sz,b,c,audio,samps_read, stat_compressor, size_play;
    unsigned char buf[512];
    unsigned char * buf_play;
    METHOD method = 0;

#ifdef WANT_ANSWER
    char file_name[50];
    struct tm *rtime;
    time_t lt;
    FILE *fp;
    int file;
    char envir[50];
#endif

    envir[0] = '\0';
    signal(SIGHUP, SIG_DFL); /* Exit on SIGHUP -fein- */

#ifdef WANT_ANSWER
    if((fp=fopen("/tmp/.ztalk_away","r"))!=NULL) {
	fclose(fp);
        strcpy(envir,"/tmp/vmail/");
        lt=time(NULL);
        rtime=localtime(&lt);
        strftime(file_name,50,"%B.%d-%I:%M:%S%p",rtime);
        strcat(envir,file_name);
    }

    if(envir[0] != '\0' ) { /* Null Check */
        printf("001 cb server ready [ Away, Voice Mail Logged ]\r\n");
	fflush(stdout);
      }
    else {
        printf("001 cb server ready [ Voice Mail Logging off ]\r\n");
        fflush(stdout);
      }
#else
    printf("001 cb server ready\r\n");
    fflush(stdout);
#endif /* WANT_ANSWER */

    while (1)
	{
	b = 0;
	for (a = 0; a < 100; a++) {
    	    if (read(0,&c,1) != 1) exit(1);
	    if (c == 10) break;
	    buf[b++] = c;
	  }
	buf[b] = 0;
	if( isdigit( buf[0] ) ) {
	    method = ME_FULL;
	    sz = atoi(buf);
	  }
	else {
    	    for(method=0;id_compression[method];method++) {
		if(id_compression[method] == buf[0]) break;
	      }
   	    if ( method >= ME_UNSUPPORTED ) exit(1);
	    sz = atoi(buf+1);
	  }
	if (sz == 0 || sz > SIZE_MB ) {
	    printf("002 Thanks. Have a nice day\r\n");
	    fflush(stdout);
	    exit(1);
	  }
	if (sz > SIZE_MB) {
	    printf("005 data lost\r\n");
	    fflush(stdout);
	    exit(1);
	  }
	buf_receive = (unsigned char *) malloc(sz);
	if (NULL == buf_receive) {
	    printf("005 data lost (couldn't malloc buffer)\r\n");
	    fflush(stdout);
	    exit(1);
	  }
	printf("003 Reading %d bytes\r\n",sz);
	fflush(stdout);
	samps_read = slow_read(0,buf_receive,sz);
	printf("Received %d bytes\r\n",samps_read);
	fflush(stdout);
	c = 0;

        stat_compressor = decompress_buffer(	method,
	        				buf_receive,
        					samps_read,
        					&buf_play,
        					&size_play);
	
	for (b = 1; b < 10; b++) {
#ifdef WANT_ANSWER
	    if(envir[0] != '\0' )  /* Null Check */
            { /* write into a file first if set_away -fein- */
                file = creat(envir, 0660); 
                file = open(envir, O_WRONLY);
       		write(file,buf_play,size_play);
                close(file);
	      }
#endif /* WANT_ANSWER */
	    audio = open("/dev/audio",O_WRONLY);
	    if (audio >= 0) {
		boop(audio);
		beep(audio);
		write(audio,buf_play,size_play);
                sleep(1); /* Don't inturrupt listening the ending part -fein- */
                beep(audio);
                boop(audio);
		close(audio);
		printf("004 ok\r\n");
		c = 1;
		break;
	      }
	    sleep(3);
	  }
	if (c == 0) printf("005 data lost\r\n");
	fflush(stdout);
	if (buf_play != buf_receive) free(buf_play);
	free(buf_receive);
      }
  }

int decompress_buffer(	METHOD method,
			unsigned char * buf_receive,
			int size_receive,
			unsigned char ** buf_play,
			int * size_play
			)
{
    int stat_retval = 0;
    int pos_receive = 0;
    int pos_play = 0;
    int i = 0;
    unsigned char * buf_ul;

    switch(method) {
	case ME_FULL:	{
			*buf_play = buf_receive;
			*size_play = size_receive;
			break;
			}
	case ME_GSM:	{
		gsm_signal g_samples[160];
		gsm gh = NULL;
		
		if(!(gh = gsm_create())) return (-2);
		*size_play = size_receive * 5;
		buf_ul = (unsigned char *) malloc(*size_play);
		if( NULL == buf_ul ) return(-2);
		while(pos_receive < size_receive) {
		    gsm_decode(	gh, (gsm_byte *) (buf_receive + pos_receive),
				g_samples);
		    for( i = 0; i < 160; i++)
		    buf_ul[pos_play+i] = (unsigned char) S2U( g_samples[i] );

		    pos_receive+=33;
		    pos_play+=160;

		  }
		*buf_play = buf_ul;
	        *size_play=pos_play;
        	break;
	      }

	default:	stat_retval=-1;
	}	  /* switch */
    return(stat_retval);
  }

int slow_read(int hd, char *s, int sz)
{
    int pos;
    int a;
    int tz;
    pos = 0;
    tz = sz;  

    do {
        a = read(hd,&s[pos],tz);
        if (a < 0)
	   return (-1);
        pos +=a;
        tz -= a;
#ifdef DEBUG
        printf("slow_read: have <%d> still want <%d>\n",pos,tz);
#endif
      } while(pos < sz);
    return (pos);
  }
