src/telephonyevents.c

00001 /*
00002   The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack.
00003   Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Lesser General Public
00007   License as published by the Free Software Foundation; either
00008   version 2.1 of the License, or (at your option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Lesser General Public License for more details.
00014 
00015   You should have received a copy of the GNU Lesser General Public
00016   License along with this library; if not, write to the Free Software
00017   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 */
00019 
00020 #include <ortp/telephonyevents.h>
00021 #include "utils.h"
00022 #include "rtpsession_priv.h"
00023 #include <ortp/ortp.h>
00024 
00025 PayloadType     payload_type_telephone_event={
00026         PAYLOAD_AUDIO_PACKETIZED, /*type */
00027         8000,   /*clock rate */
00028         0,              /* bytes per sample N/A */
00029         NULL,   /* zero pattern N/A*/
00030         0,              /*pattern_length N/A */
00031         0,              /*      normal_bitrate */
00032         "telephone-event",      /* MIME subtype */
00033         0,              /* Audio Channels N/A */
00034         0               /*flags */
00035 };
00036 
00044 int rtp_session_telephone_events_supported(RtpSession *session)
00045 {
00046         /* search for a telephony event payload in the current profile */
00047         session->snd.telephone_events_pt=rtp_profile_get_payload_number_from_mime(session->snd.profile,"telephone-event");
00048         session->rcv.telephone_events_pt=rtp_profile_get_payload_number_from_mime(session->rcv.profile,"telephone-event");
00049         /*printf("Telephone event pt is %i\n",session->telephone_events_pt);*/
00050         return session->snd.telephone_events_pt;
00051 }
00052 
00053 
00061 int rtp_session_send_telephone_events_supported(RtpSession *session)
00062 {
00063         /* search for a telephony event payload in the current profile */
00064         session->snd.telephone_events_pt=rtp_profile_get_payload_number_from_mime(session->snd.profile,"telephone-event");
00065         /*printf("Telephone event pt is %i\n",session->telephone_events_pt);*/
00066         return session->snd.telephone_events_pt;
00067 }
00068 int rtp_session_recv_telephone_events_supported(RtpSession *session)
00076 {
00077         /* search for a telephony event payload in the current profile */
00078         session->rcv.telephone_events_pt=rtp_profile_get_payload_number_from_mime(session->rcv.profile,"telephone-event");
00079         /*printf("Telephone event pt is %i\n",session->telephone_events_pt);*/
00080         return session->snd.telephone_events_pt;
00081 }
00082 
00083 
00096 mblk_t  *rtp_session_create_telephone_event_packet(RtpSession *session, int start)
00097 {
00098         mblk_t *mp;
00099         rtp_header_t *rtp;
00100         
00101         return_val_if_fail(session->snd.telephone_events_pt!=-1,NULL);
00102         
00103         mp=allocb(RTP_FIXED_HEADER_SIZE+TELEPHONY_EVENTS_ALLOCATED_SIZE,BPRI_MED);
00104         if (mp==NULL) return NULL;
00105         rtp=(rtp_header_t*)mp->b_rptr;
00106         rtp->version = 2;
00107         rtp->markbit=start;
00108         rtp->padbit = 0;
00109         rtp->extbit = 0;
00110         rtp->cc = 0;
00111         rtp->ssrc = session->snd.ssrc;
00112         /* timestamp set later, when packet is sended */
00113         /*seq number set later, when packet is sended */
00114         
00115         /*set the payload type */
00116         rtp->paytype=session->snd.telephone_events_pt;
00117         
00118         /*copy the payload */
00119         mp->b_wptr+=RTP_FIXED_HEADER_SIZE;
00120         return mp;
00121 }
00122 
00123 
00137 int rtp_session_add_telephone_event(RtpSession *session,
00138                         mblk_t *packet, uint8_t event, int end, uint8_t volume, uint16_t duration)
00139 {
00140         mblk_t *mp=packet;
00141         telephone_event_t *event_hdr;
00142 
00143 
00144         /* find the place where to add the new telephony event to the packet */
00145         while(mp->b_cont!=NULL) mp=mp->b_cont;
00146         /* see if we need to allocate a new mblk_t */
00147         if ( ( mp->b_wptr) >= (mp->b_datap->db_lim)){
00148                 mblk_t *newm=allocb(TELEPHONY_EVENTS_ALLOCATED_SIZE,BPRI_MED);
00149                 mp->b_cont=newm;
00150                 mp=mp->b_cont;
00151         }
00152         if (mp==NULL) return -1;
00153         event_hdr=(telephone_event_t*)mp->b_wptr;
00154         event_hdr->event=event;
00155         event_hdr->R=0;
00156         event_hdr->E=end;
00157         event_hdr->volume=volume;
00158         event_hdr->duration=htons(duration);
00159         mp->b_wptr+=sizeof(telephone_event_t);
00160         return 0;
00161 }
00173 int rtp_session_send_dtmf(RtpSession *session, char dtmf, uint32_t userts)
00174 {
00175   return rtp_session_send_dtmf2(session, dtmf, userts, 480);
00176 }
00177 
00187 int rtp_session_send_dtmf2(RtpSession *session, char dtmf, uint32_t userts, int duration)
00188 {
00189         mblk_t *m1,*m2,*m3;
00190         int tev_type;
00191         int durationtier = duration/3;
00192 
00193         /* create the first telephony event packet */
00194         switch (dtmf){
00195                 case '1':
00196                         tev_type=TEV_DTMF_1;
00197                 break;
00198                 case '2':
00199                         tev_type=TEV_DTMF_2;
00200                 break;
00201                 case '3':
00202                         tev_type=TEV_DTMF_3;
00203                 break;
00204                 case '4':
00205                         tev_type=TEV_DTMF_4;
00206                 break;
00207                 case '5':
00208                         tev_type=TEV_DTMF_5;
00209                 break;
00210                 case '6':
00211                         tev_type=TEV_DTMF_6;
00212                 break;
00213                 case '7':
00214                         tev_type=TEV_DTMF_7;
00215                 break;
00216                 case '8':
00217                         tev_type=TEV_DTMF_8;
00218                 break;
00219                 case '9':
00220                         tev_type=TEV_DTMF_9;
00221                 break;
00222                 case '*':
00223                         tev_type=TEV_DTMF_STAR;
00224                 break;
00225                 case '0':
00226                         tev_type=TEV_DTMF_0;
00227                 break;
00228                 case '#':
00229                         tev_type=TEV_DTMF_POUND;
00230                 break;
00231 
00232                 case 'A':
00233                 case 'a':
00234                   tev_type=TEV_DTMF_A;
00235                   break;
00236 
00237 
00238                 case 'B':
00239                 case 'b':
00240                   tev_type=TEV_DTMF_B;
00241                   break;
00242 
00243                 case 'C':
00244                 case 'c':
00245                   tev_type=TEV_DTMF_C;
00246                   break;
00247 
00248                 case 'D':
00249                 case 'd':
00250                   tev_type=TEV_DTMF_D;
00251                   break;
00252 
00253                 case '!':
00254                   tev_type=TEV_FLASH;
00255                   break;
00256 
00257 
00258                 default:
00259                 ortp_warning("Bad dtmf: %c.",dtmf);
00260                 return -1;
00261         }
00262 
00263         m1=rtp_session_create_telephone_event_packet(session,1);
00264         if (m1==NULL) return -1;
00265         rtp_session_add_telephone_event(session,m1,tev_type,0,10,durationtier);
00266         /* create a second packet */
00267         m2=rtp_session_create_telephone_event_packet(session,0);
00268         if (m2==NULL) return -1;
00269         rtp_session_add_telephone_event(session,m2,tev_type,0,10, durationtier+durationtier);
00270                 
00271         /* create a third and final packet */
00272         m3=rtp_session_create_telephone_event_packet(session,0);
00273         if (m3==NULL) return -1;
00274         rtp_session_add_telephone_event(session,m3,tev_type,1,10,duration);
00275         
00276         /* and now sends them */
00277         rtp_session_sendm_with_ts(session,m1,userts);
00278         rtp_session_sendm_with_ts(session,m2,userts);
00279         /* the last packet is sent three times in order to improve reliability*/
00280         m1=copymsg(m3);
00281         m2=copymsg(m3);
00282         /*                      NOTE:                   */
00283         /* we need to copymsg() instead of dupmsg() because the buffers are modified when
00284         the packet is sended because of the host-to-network conversion of timestamp,ssrc, csrc, and
00285         seq number.
00286         */
00287         rtp_session_sendm_with_ts(session,m3,userts);
00288         session->rtp.snd_seq--;
00289         rtp_session_sendm_with_ts(session,m1,userts);
00290         session->rtp.snd_seq--;
00291         rtp_session_sendm_with_ts(session,m2,userts);
00292         return 0;
00293 }
00294 
00295 
00304 int rtp_session_read_telephone_event(RtpSession *session,
00305                 mblk_t *packet,telephone_event_t **tab)
00306 {
00307         int datasize;
00308         int num;
00309         int i;
00310         telephone_event_t *tev;
00311         rtp_header_t *hdr=(rtp_header_t*)packet->b_rptr;
00312         return_val_if_fail(packet->b_cont!=NULL,-1);
00313         if (hdr->paytype!=session->rcv.telephone_events_pt) return 0;  /* this is not tel ev.*/
00314         datasize=msgdsize(packet);
00315         tev=*tab=(telephone_event_t*)packet->b_cont->b_rptr;
00316         /* convert from network to host order what should be */
00317         num=datasize/sizeof(telephone_event_t);
00318         for (i=0;i<num;i++)
00319         {
00320                 tev[i].duration=ntohs(tev[i].duration);
00321         }
00322         return num;
00323 }
00324 
00325 static void notify_tev(RtpSession *session, telephone_event_t *event){
00326         OrtpEvent *ev;
00327         OrtpEventData *evd;
00328         rtp_signal_table_emit2(&session->on_telephone_event,(long)(long)event[0].event);
00329         if (session->eventqs!=NULL){
00330                 ev=ortp_event_new(ORTP_EVENT_TELEPHONE_EVENT);
00331                 evd=ortp_event_get_data(ev);
00332                 evd->packet=dupmsg(session->current_tev);
00333                 evd->info.telephone_event=event[0].event;
00334                 rtp_session_dispatch_event(session,ev);
00335         }
00336 }
00337 
00338 static void notify_events_ended(RtpSession *session, telephone_event_t *events, int num){
00339         int i;
00340         for (i=0;i<num;i++){
00341                 if (events[i].E==1){
00342                         notify_tev(session, &events[i]);
00343                 }
00344         }
00345 }
00346 
00347 /* for high level telephony event callback */
00348 void rtp_session_check_telephone_events(RtpSession *session, mblk_t *m0)
00349 {
00350         telephone_event_t *events,*evbuf;
00351         int num;
00352         int i;
00353         mblk_t *mp;
00354         rtp_header_t *hdr;
00355         mblk_t *cur_tev;
00356         
00357         hdr=(rtp_header_t*)m0->b_rptr;
00358         mp=m0->b_cont;
00359         
00360         num=((int)(mp->b_wptr-mp->b_rptr))/sizeof(telephone_event_t);
00361         events=(telephone_event_t*)mp->b_rptr;
00362         
00363         
00364         if (hdr->markbit==1)
00365         {
00366                 /* this is a start of new events. Store the event buffer for later use*/
00367                 if (session->current_tev!=NULL) {
00368                         freemsg(session->current_tev);
00369                         session->current_tev=NULL;
00370                 }
00371                 session->current_tev=copymsg(m0);
00372                 /* handle the case where the events are short enough to end within the packet that has the marker bit*/
00373                 notify_events_ended(session,events,num);
00374         }
00375         /* whatever there is a markbit set or not, we parse the packet and compare it to previously received one */
00376         cur_tev=session->current_tev;
00377         if (cur_tev!=NULL)
00378         {
00379                 /* first compare timestamp, they must be identical */
00380                 if (((rtp_header_t*)cur_tev->b_rptr)->timestamp==
00381                         ((rtp_header_t*)m0->b_rptr)->timestamp)
00382                 {
00383                         evbuf=(telephone_event_t*)cur_tev->b_cont;
00384                         for (i=0;i<num;i++)
00385                         {
00386                                 if (events[i].E==1)
00387                                 {
00388                                         /* update events that have ended */
00389                                         if (evbuf[i].E==0){
00390                                                 evbuf[i].E=1;
00391                                                 /* this is a end of event, report it */
00392                                                 notify_tev(session,&events[i]);
00393                                         }
00394                                 }
00395                         }
00396                 }
00397                 else
00398                 {
00399                         /* timestamp are not identical: this is not the same events*/
00400                         if (session->current_tev!=NULL) {
00401                                 freemsg(session->current_tev);
00402                                 session->current_tev=NULL;
00403                         }
00404                         session->current_tev=copymsg(m0);
00405                         notify_events_ended(session,events,num);
00406                 }
00407         }
00408         else
00409         {
00410                 /* there is no pending events, but we did not received marked bit packet
00411                 either the sending implementation is not compliant, either it has been lost, 
00412                 we must deal with it anyway.*/
00413                 session->current_tev=copymsg(m0);
00414                 /* inform the application if there are tone ends */
00415                 notify_events_ended(session,events,num);
00416         }
00417 }

Generated on Fri Feb 15 00:06:03 2008 for oRTP by  doxygen 1.5.4