1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
15 #include <sys/types.h>
24 //#define MIXER_DEBUG /* debug mixer buffer overflow and underrun */
26 class Port *port_first = NULL;
28 unsigned long port_serial = 1; /* must be 1, because 0== no port */
31 /* free epointlist relation
33 void Port::free_epointlist(struct epoint_list *epointlist)
35 struct epoint_list *temp, **tempp;
38 tempp = &p_epointlist;
41 if (temp == epointlist)
49 PERROR("SOFTWARE ERROR: epointlist not in port's list.\n");
56 PDEBUG(DEBUG_EPOINT, "PORT(%d) removed epoint from port\n", p_serial);
57 memset(temp, 0, sizeof(struct epoint_list));
63 void Port::free_epointid(unsigned long epoint_id)
65 struct epoint_list *temp, **tempp;
68 tempp = &p_epointlist;
71 if (temp->epoint_id == epoint_id)
79 PERROR("epoint_id not in port's list, exitting.\n");
86 PDEBUG(DEBUG_EPOINT, "PORT(%d) removed epoint from port\n", p_serial);
87 memset(temp, 0, sizeof(struct epoint_list));
93 /* create new epointlist relation
95 struct epoint_list *Port::epointlist_new(unsigned long epoint_id)
97 struct epoint_list *epointlist, **epointlistpointer;
99 /* epointlist structure */
100 epointlist = (struct epoint_list *)calloc(1, sizeof(struct epoint_list));
103 PERROR("no mem for allocating epoint_list\n");
107 PDEBUG(DEBUG_EPOINT, "PORT(%d) allocating epoint_list.\n", p_serial);
108 memset(epointlist, 0, sizeof(struct epoint_list));
110 /* add epoint_list to chain */
111 epointlist->next = NULL;
112 epointlistpointer = &p_epointlist;
113 while(*epointlistpointer)
114 epointlistpointer = &((*epointlistpointer)->next);
115 *epointlistpointer = epointlist;
118 epointlist->epoint_id = epoint_id;
119 epointlist->active = 1;
128 Port::Port(int type, char *portname, struct port_settings *settings)
130 class Port *temp, **tempp;
132 PDEBUG(DEBUG_PORT, "new port of type %d, name '%s'\n", type, portname);
134 /* initialize object */
136 memcpy(&p_settings, settings, sizeof(struct port_settings));
139 memset(&p_settings, 0, sizeof(p_settings));
140 SCPY(p_settings.tones_dir, options.tones_dir);
142 SCPY(p_name, portname);
143 SCPY(p_tone_dir, p_settings.tones_dir); // just to be sure
147 p_serial = port_serial++;
148 p_debug_nothingtosend = 0;
150 p_tone_fetched = NULL;
151 p_tone_name[0] = '\0';
153 // p_knock_fetched = NULL;
154 p_state = PORT_STATE_IDLE;
156 memset(&p_callerinfo, 0, sizeof(p_callerinfo));
157 memset(&p_dialinginfo, 0, sizeof(p_dialinginfo));
158 memset(&p_connectinfo, 0, sizeof(p_connectinfo));
159 memset(&p_redirinfo, 0, sizeof(p_redirinfo));
160 memset(&p_capainfo, 0, sizeof(p_capainfo));
161 memset(p_mixer_buffer, 0, sizeof(p_mixer_buffer));
162 memset(p_record_buffer, 0, sizeof(p_record_buffer));
163 memset(p_stereo_buffer, 0, sizeof(p_stereo_buffer));
171 p_record_filename[0] = '\0';
173 /* append port to chain */
192 struct mixer_relation *relation, *rtemp;
193 class Port *temp, **tempp;
194 struct message *message;
201 PDEBUG(DEBUG_PORT, "removing port of type %d, name '%s'\n", p_type, p_name);
203 /* free mixer relation chain */
204 relation = p_mixer_rel;
208 relation = relation->next;
209 memset(rtemp, 0, sizeof(struct mixer_relation));
213 p_mixer_rel = NULL; /* beeing paranoid */
215 /* disconnect port from endpoint */
218 /* send disconnect */
219 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
220 message->param.disconnectinfo.cause = 16;
221 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
222 message_put(message);
223 /* remove endpoint */
224 free_epointlist(p_epointlist);
227 /* remove port from chain */
239 PERROR("PORT(%s) port not in port's list.\n", p_name);
245 /* close open tones file */
252 p_tone_fetched = NULL;
257 /* set new endpoint state
259 void Port::new_state(int state)
261 PDEBUG(DEBUG_PORT, "PORT(%s) new state %s --> %s\n", p_name, state_name[p_state], state_name[state]);
267 * find the port with port_id
269 class Port *find_port_id(unsigned long port_id)
271 class Port *port = port_first;
275 //printf("comparing: '%s' with '%s'\n", name, port->name);
276 if (port->p_serial == port_id)
288 void Port::set_echotest(int echotest)
290 p_echotest = echotest;
295 * set the file in the tone directory with the given name
297 void Port::set_tone(char *dir, char *name)
305 /* no counter, no eof, normal speed */
309 p_tone_codec = CODEC_LAW;
317 p_tone_fetched = NULL;
323 SPRINT(p_tone_name, "%s", name);
324 p_tone_dir[0] = '\0';
327 SCPY(p_tone_dir, dir);
328 SCPY(p_tone_name, name);
332 p_tone_name[0]= '\0';
337 if (!!strncmp(name,"cause_",6))
340 /* now we check if the cause exists, otherwhise we use error tone. */
341 if ((p_tone_fetched=open_tone_fetched(p_tone_dir, p_tone_name, &p_tone_codec, 0, 0)))
343 p_tone_fetched = NULL;
346 SPRINT(filename, "%s_loop", p_tone_name);
347 if ((p_tone_fetched=open_tone_fetched(p_tone_dir, filename, &p_tone_codec, 0, 0)))
349 p_tone_fetched = NULL;
352 SPRINT(filename, "%s/%s/%s", INSTALL_DATA, p_tone_dir, p_tone_name);
353 if ((fh=open_tone(filename, &p_tone_codec, 0, 0)) >= 0)
358 SPRINT(filename, "%s/%s/%s_loop", INSTALL_DATA, p_tone_dir, p_tone_name);
359 if ((fh=open_tone(filename, &p_tone_codec, 0, 0)) >= 0)
365 if (!strcmp(name,"cause_00") || !strcmp(name,"cause_10"))
367 PDEBUG(DEBUG_PORT, "PORT(%s) Given Cause 0x%s has no tone, using release tone\n", p_name, name+6);
368 SPRINT(p_tone_name,"release");
370 if (!strcmp(name,"cause_11"))
372 PDEBUG(DEBUG_PORT, "PORT(%s) Given Cause 0x%s has no tone, using busy tone\n", p_name, name+6);
373 SPRINT(p_tone_name,"busy");
376 PDEBUG(DEBUG_PORT, "PORT(%s) Given Cause 0x%s has no tone, using error tone\n", p_name, name+6);
377 SPRINT(p_tone_name,"error");
383 * set the file in the tone directory for vbox playback
384 * also set the play_eof-flag
386 void Port::set_vbox_tone(char *dir, char *name)
392 p_tone_codec = CODEC_LAW;
401 p_tone_fetched = NULL;
403 SPRINT(p_tone_dir, dir);
404 SPRINT(p_tone_name, name);
406 /* now we check if the cause exists, otherwhise we use error tone. */
409 if ((p_tone_fetched=open_tone_fetched(p_tone_dir, p_tone_name, &p_tone_codec, &p_tone_size, &p_tone_left)))
411 PDEBUG(DEBUG_PORT, "PORT(%s) opening fetched tone: %s\n", p_name, p_tone_name);
414 SPRINT(filename, "%s/%s/%s", INSTALL_DATA, p_tone_dir, p_tone_name);
415 if ((p_tone_fh=open_tone(filename, &p_tone_codec, &p_tone_size, &p_tone_left)) >= 0)
418 PDEBUG(DEBUG_PORT, "PORT(%s) opening tone: %s\n", p_name, filename);
423 SPRINT(filename, "%s", p_tone_name);
424 if ((p_tone_fh=open_tone(filename, &p_tone_codec, &p_tone_size, &p_tone_left)) >= 0)
427 PDEBUG(DEBUG_PORT, "PORT(%s) opening tone: %s\n", p_name, filename);
435 * set the file in the given directory for vbox playback
436 * also set the eof-flag
437 * also set the counter-flag
439 void Port::set_vbox_play(char *name, int offset)
442 struct message *message;
444 /* use ser_box_tone() */
445 set_vbox_tone("", name);
455 /* send message with counter value */
456 if (p_tone_size>=0 && ACTIVE_EPOINT(p_epointlist))
458 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TONE_COUNTER);
459 message->param.counter.current = offset;
460 message->param.counter.max = size;
461 message_put(message);
468 * set the playback speed (for recording playback with different speeds)
470 void Port::set_vbox_speed(int speed)
472 /* enable vbox play mode */
473 p_tone_speed = speed;
477 * read from the given file as specified in port_set_tone and return sample data
478 * silence is appended if sample ends, but only the number of samples with tones are returned
480 int Port::read_audio(unsigned char *buffer, int length)
484 int nodata=0; /* to detect 0-length files and avoid endless reopen */
486 int tone_left_before; /* temp variable to determine the change in p_tone_left */
493 codec_in = p_tone_codec;
495 /* if there is no tone set, use silence */
496 if (p_tone_name[0] == 0)
499 memset(buffer, (options.law=='a')?0x2a:0xff, len); /* silence */
503 /* if the file pointer is not open, we open it */
504 if (p_tone_fh<0 && p_tone_fetched==NULL)
508 SPRINT(filename, "%s", p_tone_name);
509 /* if file does not exist */
510 if (!(p_tone_fetched=open_tone_fetched(p_tone_dir, filename, &p_tone_codec, &p_tone_size, &p_tone_left)))
512 SPRINT(filename, "%s/%s/%s", INSTALL_DATA, p_tone_dir, p_tone_name);
513 /* if file does not exist */
514 if ((p_tone_fh=open_tone(filename, &p_tone_codec, &p_tone_size, &p_tone_left)) < 0)
516 PDEBUG(DEBUG_PORT, "PORT(%s) no tone: %s\n", p_name, filename);
523 SPRINT(filename, "%s", p_tone_name);
524 /* if file does not exist */
525 if ((p_tone_fh=open_tone(filename, &p_tone_codec, &p_tone_size, &p_tone_left)) < 0)
527 PDEBUG(DEBUG_PORT, "PORT(%s) no tone: %s\n", p_name, filename);
532 PDEBUG(DEBUG_PORT, "PORT(%s) opening %stone: %s\n", p_name, p_tone_fetched?"fetched ":"", filename);
536 /* file descriptor is open read data */
537 tone_left_before = p_tone_left;
540 l = read_tone(p_tone_fh, buffer, p_tone_codec, len, p_tone_size, &p_tone_left, p_tone_speed);
541 if (l<0 || l>len) /* paranoia */
548 l = read_tone_fetched(&p_tone_fetched, buffer, len, p_tone_size, &p_tone_left, p_tone_speed);
549 if (l<0 || l>len) /* paranoia */
555 /* if counter is enabled, we check if we have a change */
556 if (p_tone_counter && p_tone_size>=0 && ACTIVE_EPOINT(p_epointlist))
558 /* if we jumed to the next second */
559 if (((p_tone_size-p_tone_left)/8000) != (p_tone_size-tone_left_before)/8000)
561 //printf("\nsize=%d left=%d\n\n",p_tone_size,p_tone_left);
562 struct message *message;
563 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TONE_COUNTER);
564 message->param.counter.current = (p_tone_size-p_tone_left)/8000;
565 message->param.counter.max = -1;
566 message_put(message);
579 p_tone_fetched = NULL;
584 /* if the file has 0-length */
587 PDEBUG(DEBUG_PORT, "PORT(%s) 0-length loop: %s\n", p_name, filename);
590 goto rest_is_silence;
593 /* if eof is reached, or if the normal file cannot be opened, continue with the loop file if possible */
595 if (p_tone_eof && ACTIVE_EPOINT(p_epointlist))
597 struct message *message;
598 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TONE_EOF);
599 message_put(message);
604 /* if file does not exist */
605 SPRINT(filename, "%s_loop", p_tone_name);
606 if (!(p_tone_fetched=open_tone_fetched(p_tone_dir, filename, &p_tone_codec, &p_tone_size, &p_tone_left)))
608 SPRINT(filename, "%s/%s/%s_loop", INSTALL_DATA, p_tone_dir, p_tone_name);
609 /* if file does not exist */
610 if ((p_tone_fh=open_tone(filename, &p_tone_codec, &p_tone_size, &p_tone_left)) < 0)
612 PDEBUG(DEBUG_PORT, "PORT(%s) no tone loop: %s\n",p_name, filename);
613 p_tone_dir[0] = '\0';
614 p_tone_name[0] = '\0';
615 // codec_in = CODEC_LAW;
616 goto rest_is_silence;
622 SPRINT(filename, "%s_loop", p_tone_name);
623 /* if file does not exist */
624 if ((p_tone_fh=open_tone(filename, &p_tone_codec, &p_tone_size, &p_tone_left)) < 0)
626 PDEBUG(DEBUG_PORT, "PORT(%s) no tone loop: %s\n",p_name, filename);
627 p_tone_dir[0] = '\0';
628 p_tone_name[0] = '\0';
629 // codec_in = CODEC_LAW;
630 goto rest_is_silence;
635 PDEBUG(DEBUG_PORT, "PORT(%s) opening %stone: %s\n", p_name, p_tone_fetched?"fetched ":"", filename);
637 /* now we have opened the loop */
646 * dummy for transmit function, since this must be inherited
648 void Port::transmit(unsigned char *buffer, int length, int tonelength)
654 * process transmission clock */
655 int Port::handler(void)
660 /* endpoint sends messages to the port
661 * this is called by the message_epoint inherited by child classes
662 * therefor a return=1 means: stop, no more processing
664 //extern struct message *dddebug;
665 int Port::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
667 /* check if we got audio data from one remote port */
670 case MESSAGE_TONE: /* play tone */
671 PDEBUG(DEBUG_PORT, "PORT(%s) isdn port with (caller id %s) setting tone '%s' dir '%s'\n", p_name, p_callerinfo.id, param->tone.name, param->tone.dir);
672 set_tone(param->tone.dir,param->tone.name);
675 case MESSAGE_DATA: /* tx-data from upper layer */
676 fromup(param->data.data, param->data.len);
679 case MESSAGE_VBOX_TONE: /* play tone of answering machine */
680 PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine tone '%s' '%s'\n", p_name, param->tone.dir, param->tone.name);
681 set_vbox_tone(param->tone.dir, param->tone.name);
684 case MESSAGE_VBOX_PLAY: /* play recording of answering machine */
685 PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine file to play '%s' (offset %d seconds)\n", p_name, param->play.file, param->play.offset);
686 set_vbox_play(param->play.file, param->play.offset);
689 case MESSAGE_VBOX_PLAY_SPEED: /* set speed of playback (recording of answering machine) */
690 PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine playback speed %d (times)\n", p_name, param->speed);
691 set_vbox_speed(param->speed);
700 /* wave header structure */
702 unsigned short stereo; /* 1 = mono, 2 = stereo */
703 unsigned short channels; /* number of channels */
704 unsigned long sample_rate; /* sample rate */
705 unsigned long data_rate; /* data rate */
706 unsigned short bytes_sample; /* bytes per sample (all channels) */
707 unsigned short bits_sample; /* bits per sample (one channel) */
712 * open record file (actually a wave file with empty header which will be
713 * written before close, because we do not know the size yet)
714 * type=1 record annoucement, type=0 record audio stream, type=2 record vbox
716 int Port::open_record(int type, int vbox, int skip, char *extension, int anon_ignore, char *vbox_email, int vbox_email_file)
718 /* RIFFxxxxWAVEfmt xxxx(fmt-size)dataxxxx... */
719 char dummyheader[8+4+8+sizeof(fmt)+8];
724 PERROR("Port(%d) not an extension\n", p_serial);
727 SCPY(p_record_extension, extension);
728 p_record_anon_ignore = anon_ignore;
729 SCPY(p_record_vbox_email, vbox_email);
730 p_record_vbox_email_file = vbox_email_file;
734 PERROR("Port(%d) already recording\n", p_serial);
739 SPRINT(filename, "%s/%s/%s/vbox", INSTALL_DATA, options.extensions_dir, p_record_extension);
741 SPRINT(filename, "%s/%s/%s/recordings", INSTALL_DATA, options.extensions_dir, p_record_extension);
742 if (mkdir(filename, 0755) < 0)
746 PERROR("Port(%d) cannot create directory '%s'\n", p_serial, filename);
752 UPRINT(strchr(filename,'\0'), "/announcement");
754 UPRINT(strchr(filename,'\0'), "/%04d-%02d-%02d_%02d%02d%02d", now_tm->tm_year+1900, now_tm->tm_mon+1, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec);
757 p_record_vbox_year = now_tm->tm_year;
758 p_record_vbox_mon = now_tm->tm_mon;
759 p_record_vbox_mday = now_tm->tm_mday;
760 p_record_vbox_hour = now_tm->tm_hour;
761 p_record_vbox_min = now_tm->tm_min;
764 /* check, if file exists (especially when an extension calls the same extension) */
766 if ((p_record = fopen(filename, "r")))
769 SCAT(filename, "_2nd");
772 p_record = fopen(filename, "w");
775 PERROR("Port(%d) cannot record because file cannot be opened '%s'\n", p_serial, filename);
780 p_record_type = type;
781 p_record_vbox = vbox;
782 p_record_skip = skip;
784 switch(p_record_type)
789 fwrite(dummyheader, sizeof(dummyheader), 1, p_record);
795 UCPY(p_record_filename, filename);
797 PDEBUG(DEBUG_PORT, "Port(%d) recording started with file name '%s'\n", p_serial, filename);
803 * close the recoding file, put header in front and rename
805 void Port::close_record(int beep)
807 static signed long beep_mono[] = {-10000, 10000, -10000, 10000, -10000, 10000, -10000, 10000, -10000, 10000, -10000, 10000, -10000, 10000, -10000, 10000};
808 static unsigned char beep_8bit[] = {48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208, 48, 208};
809 unsigned long size, wsize;
811 char filename[512], indexname[512];
814 char number[256], callerid[256];
816 struct caller_info callerinfo;
817 char *valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-!$%&/()=+*;~";
822 memcpy(&callerinfo, &p_callerinfo, sizeof(struct caller_info));
823 apply_callerid_restriction(p_record_anon_ignore, -1, callerinfo.id, &callerinfo.ntype, &callerinfo.present, &callerinfo.screen, callerinfo.voip, callerinfo.intern, callerinfo.name);
825 SCPY(number, p_dialinginfo.number);
826 SCPY(callerid, numberrize_callerinfo(callerinfo.id, callerinfo.ntype));
827 if (callerid[0] == '\0')
829 if (callerinfo.present == INFO_PRESENT_RESTRICTED)
830 UCPY(callerid,"anonymous");
832 UCPY(callerid,"unknown");
835 /* change verboten digits */
837 while((p=strchr(p,'*')))
840 while((p=strchr(p,'/')))
843 while((p=strchr(p,'*')))
846 while((p=strchr(p,'/')))
849 ii = strlen(callerid);
852 if (!strchr(valid_chars, callerid[i]))
860 if (!strchr(valid_chars, number[i]))
865 /* add beep to the end of recording */
867 switch(p_record_type)
873 fwrite(beep_mono, sizeof(beep_mono), 1, p_record);
874 i += sizeof(beep_mono);
875 p_record_length += sizeof(beep_mono);
882 fwrite(beep_8bit, sizeof(beep_8bit), 1, p_record);
883 i += sizeof(beep_8bit);
884 p_record_length += sizeof(beep_8bit);
892 fwrite(beep_law, sizeof(beep_law), 1, p_record);
893 i += sizeof(beep_law);
894 p_record_length += sizeof(beep_law);
899 PERROR("codec %d not supported for beep adding\n", p_record_type);
902 /* complete header */
903 switch(p_record_type)
909 fprintf(p_record, "cue %c%c%c%c%c%c%c%c", 4, 0, 0, 0, 0,0,0,0);
912 fprintf(p_record, "LIST%c%c%c%cadtl", 4, 0, 0, 0);
915 fseek(p_record, 0, SEEK_SET);
917 /* WAVEfmt xxxx(fmt-size)dataxxxx[data]cue xxxx0000LISTxxxxadtl*/
918 size = p_record_length;
919 wsize = 4+8+sizeof(fmt)+8+size+8+4+8+4;
922 fprintf(p_record, "RIFF%c%c%c%c", (unsigned char)(wsize&0xff), (unsigned char)((wsize>>8)&0xff), (unsigned char)((wsize>>16)&0xff), (unsigned char)(wsize>>24));
925 fprintf(p_record, "WAVE");
928 fprintf(p_record, "fmt %c%c%c%c", sizeof(fmt), 0, 0, 0);
929 switch(p_record_type)
934 fmt.sample_rate = 8000; /* samples/sec */
935 fmt.data_rate = 16000; /* full data rate */
936 fmt.bytes_sample = 2; /* all channels */
937 fmt.bits_sample = 16; /* one channel */
943 fmt.sample_rate = 8000; /* samples/sec */
944 fmt.data_rate = 32000; /* full data rate */
945 fmt.bytes_sample = 4; /* all channels */
946 fmt.bits_sample = 16; /* one channel */
952 fmt.sample_rate = 8000; /* samples/sec */
953 fmt.data_rate = 8000; /* full data rate */
954 fmt.bytes_sample = 1; /* all channels */
955 fmt.bits_sample = 8; /* one channel */
958 fwrite(&fmt, sizeof(fmt), 1, p_record);
961 fprintf(p_record, "data%c%c%c%c", (unsigned char)(size&0xff), (unsigned char)((size>>8)&0xff), (unsigned char)((size>>16)&0xff), (unsigned char)(size>>24));
964 if (p_record_vbox == 1)
965 SPRINT(filename, "%s.wav", p_record_filename);
967 SPRINT(filename, "%s_%s-%s.wav", p_record_filename, callerid, number);
972 if (p_record_vbox == 1)
973 SPRINT(filename, "%s.isdn", p_record_filename);
975 SPRINT(filename, "%s_%s-%s.isdn", p_record_filename, callerid, number);
983 if (rename(p_record_filename, filename) < 0)
985 PERROR("Port(%d) cannot rename from '%s' to '%s'\n", p_serial, p_record_filename, filename);
989 PDEBUG(DEBUG_PORT, "Port(%d) recording is written and renamed to '%s' and must have the following size:%lu raw:%lu samples:%lu\n", p_serial, filename, wsize+8, size, size>>1);
991 if (p_record_vbox == 2)
993 SPRINT(indexname, "%s/%s/%s/vbox/index", INSTALL_DATA, options.extensions_dir, p_record_extension);
994 if ((fp = fopen(indexname,"a")))
998 /* remove path from file name */
1000 while(strchr(p, '/'))
1001 p = strchr(p, '/')+1;
1002 fprintf(fp, "%s %d %d %d %d %d %s\n", p, p_record_vbox_year, p_record_vbox_mon, p_record_vbox_mday, p_record_vbox_hour, p_record_vbox_min, callerid);
1008 PERROR("Port(%d) cannot open index file '%s' to append.\n", p_serial, indexname);
1011 /* send email with sample*/
1012 if (p_record_vbox_email[0])
1014 send_mail(p_record_vbox_email_file?filename:(char *)"", callerid, callerinfo.intern, callerinfo.name, p_record_vbox_email, p_record_vbox_year, p_record_vbox_mon, p_record_vbox_mday, p_record_vbox_hour, p_record_vbox_min, p_record_extension);
1021 * recording function
1022 * Records all data from down and from up into one single stream.
1023 * Both streams may have gaps or jitter.
1024 * A Jitter buffer for both streams is used to compensate jitter.
1026 * If one stream (dir) received packets, they are stored to a
1027 * buffer to wait for the other stream (dir), so both streams can
1028 * be combined. If the buffer is full, it's read pointer is written
1029 * without mixing stream.
1030 * A flag is used to indicate what stream is currently in buffer.
1032 * NOTE: First stereo sample (odd) is from down, second is from up.
1034 alle buffer initialisieren
1035 record nur aufrufen, wenn recorded wird.
1036 restlicher buffer wegschreiben beim schliessen
1037 void Port::record(char *data, int length, int dir_fromup)
1039 unsigned char write_buffer[1024], *d;
1045 if (!p_record || !length)
1048 free = ((p_record_buffer_readp - p_record_buffer_writep - 1) & RECORD_BUFFER_MASK);
1050 /* the buffer stores the same data stream */
1051 if (dir_fromup == p_record_buffer_dir)
1055 /* first write what we can to the buffer */
1056 while(free && length)
1058 p_record_buffer[p_record_buffer_writep] = audio_law_to_s32(*data++);
1059 p_record_buffer_writep = (p_record_buffer_writep + 1) & RECORD_BUFFER_MASK;
1063 /* all written, so we return */
1066 /* still data left, buffer is full, so we need to write to file */
1067 switch(p_record_type)
1070 s = (signed short *)write_buffer;
1074 *s++ = p_record_buffer[p_record_buffer_readp];
1075 p_record_buffer_readp = (p_record_buffer_readp + 1) & RECORD_BUFFER_MASK;
1078 fwrite(write_buffer, 512, 1, p_record);
1082 s = (signed short *)write_buffer;
1083 if (p_record_buffer_dir)
1088 *s++ = 0; /* nothing from down */
1089 *s++ = p_record_buffer[p_record_buffer_readp];
1090 p_record_buffer_readp = (p_record_buffer_readp + 1) & RECORD_BUFFER_MASK;
1098 *s++ = p_record_buffer[p_record_buffer_readp];
1099 *s++ = 0; /* nothing from up */
1100 p_record_buffer_readp = (p_record_buffer_readp + 1) & RECORD_BUFFER_MASK;
1104 fwrite(write_buffer, 1024, 1, p_record);
1112 *d++ = (p_record_buffer[p_record_buffer_readp]+0x8000) >> 8;
1113 p_record_buffer_readp = (p_record_buffer_readp + 1) & RECORD_BUFFER_MASK;
1116 fwrite(write_buffer, 512, 1, p_record);
1124 *d++ = audio_s16_to_law[p_record_buffer[p_record_buffer_readp] & 0xffff];
1125 p_record_buffer_readp = (p_record_buffer_readp + 1) & RECORD_BUFFER_MASK;
1128 fwrite(write_buffer, 256, 1, p_record);
1131 /* because we still have data, we write again */
1132 free += sizeof(write_buffer);
1136 /* the buffer store the other stream */
1139 /* if buffer empty, change it */
1140 if (p_record_buffer_readp == p_record_buffer_writep)
1142 p_record_buffer_dir = dir_fromup;
1145 /* how much data can we mix ? */
1146 ii = (p_record_buffer_writep - p_record_buffer_readp) & RECORD_BUFFER_MASK;
1149 /* write data mixed with the buffer */
1150 switch(p_record_type)
1153 s = (signed short *)write_buffer;
1157 sample = p_record_buffer[p_record_buffer_readp]
1158 + audio_law_to_s32(*data++);
1159 p_record_buffer_readp = (p_record_buffer_readp + 1) & RECORD_BUFFER_MASK;
1167 fwrite(write_buffer, ii<<1, 1, p_record);
1171 s = (signed short *)write_buffer;
1172 if (p_record_buffer_dir)
1177 *s++ = audio_law_to_s32(*data++);
1178 *s++ = p_record_buffer[p_record_buffer_readp];
1179 p_record_buffer_readp = (p_record_buffer_readp + 1) & RECORD_BUFFER_MASK;
1187 *s++ = p_record_buffer[p_record_buffer_readp];
1188 *s++ = audio_law_to_s32(*data++);
1192 fwrite(write_buffer, ii<<2, 1, p_record);
1200 sample = p_record_buffer[p_record_buffer_readp]
1201 + audio_law_to_s32(*data++);
1202 p_record_buffer_readp = (p_record_buffer_readp + 1) & RECORD_BUFFER_MASK;
1207 *d++ = (sample+0x8000) >> 8;
1210 fwrite(write_buffer, ii, 1, p_record);
1218 sample = p_record_buffer[p_record_buffer_readp]
1219 + audio_law_to_s32(*data++);
1220 p_record_buffer_readp = (p_record_buffer_readp + 1) & RECORD_BUFFER_MASK;
1225 *d++ = audio_s16_to_law[sample & 0xffff];
1228 fwrite(write_buffer, ii, 1, p_record);
1232 /* data, but buffer empty */
1235 p_record_buffer_dir = dir_fromup;
1238 /* no data (maybe buffer) */
1245 * enque data from upper buffer
1247 iniialisieren der werte
1248 void Port::txfromup(unsigned char *data, int length)
1255 /* get free samples in buffer */
1256 free = ((p_fromup_buffer_readp - p_fromup_buffer_writep - 1) & FROMUP_BUFFER_MASK);
1259 PDEBUG(DEBUG_PORT, "Port(%d): fromup_buffer overflows, this shall not happen under normal conditions\n", p_serial);
1263 /* write data to buffer and return */
1266 p_fromup_buffer[p_fromup_buffer_writep] = *data++;
1267 p_fromup_buffer_writep = (p_fromup_buffer_writep + 1) & FROMUP_BUFFER_MASK;
1270 return; // must return, because length is 0