summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/audiostream.c
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/audiostream.c')
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/audiostream.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/audiostream.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/audiostream.c
new file mode 100644
index 00000000..f4ff4867
--- /dev/null
+++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/audiostream.c
@@ -0,0 +1,343 @@
+/*
+ The mediastreamer library aims at providing modular media processing and I/O
+ for linphone, but also for any telephony application.
+ Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#include "mediastream.h"
+#ifdef INET6
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+#endif
+
+
+#define MAX_RTP_SIZE 1500
+
+/* this code is not part of the library itself, it is part of the mediastream program */
+void audio_stream_free(AudioStream *stream)
+{
+ RtpSession *s;
+ RtpSession *destroyed=NULL;
+ if (stream->rtprecv!=NULL) {
+ s=ms_rtp_recv_get_session(MS_RTP_RECV(stream->rtprecv));
+ if (s!=NULL){
+ destroyed=s;
+ rtp_session_destroy(s);
+ }
+ ms_filter_destroy(stream->rtprecv);
+ }
+ if (stream->rtpsend!=NULL) {
+ s=ms_rtp_send_get_session(MS_RTP_SEND(stream->rtpsend));
+ if (s!=NULL){
+ if (s!=destroyed)
+ rtp_session_destroy(s);
+ }
+ ms_filter_destroy(stream->rtpsend);
+ }
+ if (stream->soundread!=NULL) ms_filter_destroy(stream->soundread);
+ if (stream->soundwrite!=NULL) ms_filter_destroy(stream->soundwrite);
+ if (stream->encoder!=NULL) ms_filter_destroy(stream->encoder);
+ if (stream->decoder!=NULL) ms_filter_destroy(stream->decoder);
+ if (stream->timer!=NULL) ms_sync_destroy(stream->timer);
+ g_free(stream);
+}
+
+static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
+
+static void on_dtmf_received(RtpSession *s,gint dtmf,gpointer user_data)
+{
+ AudioStream *stream=(AudioStream*)user_data;
+ if (dtmf>15){
+ g_warning("Unsupported telephone-event type.");
+ return;
+ }
+ g_message("Receiving dtmf %c.",dtmf_tab[dtmf]);
+ if (stream!=NULL){
+ if (strcmp(stream->soundwrite->klass->name,"OssWrite")==0)
+ ms_oss_write_play_dtmf(MS_OSS_WRITE(stream->soundwrite),dtmf_tab[dtmf]);
+ }
+}
+
+static void on_timestamp_jump(RtpSession *s,guint32* ts, gpointer user_data)
+{
+ g_warning("The remote sip-phone has send data with a future timestamp: %u,"
+ "resynchronising session.",*ts);
+ rtp_session_reset(s);
+}
+
+static const char *ip4local="0.0.0.0";
+static const char *ip6local="::";
+
+const char *get_local_addr_for(const char *remote)
+{
+ const char *ret;
+#ifdef INET6
+ char num[8];
+ struct addrinfo hints, *res0;
+ int err;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ err = getaddrinfo(remote,"8000", &hints, &res0);
+ if (err!=0) {
+ g_warning ("get_local_addr_for: %s", gai_strerror(err));
+ return ip4local;
+ }
+ ret=(res0->ai_addr->sa_family==AF_INET6) ? ip6local : ip4local;
+ freeaddrinfo(res0);
+#else
+ ret=ip4local;
+#endif
+ return ret;
+}
+
+void create_duplex_rtpsession(RtpProfile *profile, int locport,char *remip,int remport,
+ int payload,int jitt_comp,
+ RtpSession **recvsend){
+ RtpSession *rtpr;
+ rtpr=rtp_session_new(RTP_SESSION_SENDRECV);
+ rtp_session_max_buf_size_set(rtpr,MAX_RTP_SIZE);
+ rtp_session_set_profile(rtpr,profile);
+ rtp_session_set_local_addr(rtpr,get_local_addr_for(remip),locport);
+ if (remport>0) rtp_session_set_remote_addr(rtpr,remip,remport);
+ rtp_session_set_scheduling_mode(rtpr,0);
+ rtp_session_set_blocking_mode(rtpr,0);
+ rtp_session_set_payload_type(rtpr,payload);
+ rtp_session_set_jitter_compensation(rtpr,jitt_comp);
+ rtp_session_enable_adaptive_jitter_compensation(rtpr,TRUE);
+ /*rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)on_timestamp_jump,NULL);*/
+ *recvsend=rtpr;
+}
+
+void create_rtp_sessions(RtpProfile *profile, int locport,char *remip,int remport,
+ int payload,int jitt_comp,
+ RtpSession **recv, RtpSession **send){
+ RtpSession *rtps,*rtpr;
+ PayloadType *pt;
+ /* creates two rtp filters to recv send streams (remote part)*/
+
+ rtps=rtp_session_new(RTP_SESSION_SENDONLY);
+ rtp_session_max_buf_size_set(rtps,MAX_RTP_SIZE);
+ rtp_session_set_profile(rtps,profile);
+#ifdef INET6
+ rtp_session_set_local_addr(rtps,"::",locport+2);
+#else
+ rtp_session_set_local_addr(rtps,"0.0.0.0",locport+2);
+#endif
+ rtp_session_set_remote_addr(rtps,remip,remport);
+ rtp_session_set_scheduling_mode(rtps,0);
+ rtp_session_set_blocking_mode(rtps,0);
+ rtp_session_set_payload_type(rtps,payload);
+ rtp_session_set_jitter_compensation(rtps,jitt_comp);
+
+ rtpr=rtp_session_new(RTP_SESSION_RECVONLY);
+ rtp_session_max_buf_size_set(rtpr,MAX_RTP_SIZE);
+ rtp_session_set_profile(rtpr,profile);
+#ifdef INET6
+ rtp_session_set_local_addr(rtpr,"::",locport);
+#else
+ rtp_session_set_local_addr(rtpr,"0.0.0.0",locport);
+#endif
+ rtp_session_set_scheduling_mode(rtpr,0);
+ rtp_session_set_blocking_mode(rtpr,0);
+ rtp_session_set_payload_type(rtpr,payload);
+ rtp_session_set_jitter_compensation(rtpr,jitt_comp);
+ rtp_session_signal_connect(rtpr,"telephone-event",(RtpCallback)on_dtmf_received,NULL);
+ rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)on_timestamp_jump,NULL);
+ *recv=rtpr;
+ *send=rtps;
+
+}
+
+
+AudioStream * audio_stream_start_full(RtpProfile *profile, int locport,char *remip,int remport,
+ int payload,int jitt_comp, gchar *infile, gchar *outfile, SndCard *playcard, SndCard *captcard)
+{
+ AudioStream *stream=g_new0(AudioStream,1);
+ RtpSession *rtps,*rtpr;
+ PayloadType *pt;
+
+ /* //create_rtp_sessions(profile,locport,remip,remport,payload,jitt_comp,&rtpr,&rtps); */
+
+ create_duplex_rtpsession(profile,locport,remip,remport,payload,jitt_comp,&rtpr);
+ rtp_session_signal_connect(rtpr,"telephone-event",(RtpCallback)on_dtmf_received,(gpointer)stream);
+ rtps=rtpr;
+
+ stream->recv_session = rtpr;
+ stream->send_session = rtps;
+ stream->rtpsend=ms_rtp_send_new();
+ ms_rtp_send_set_session(MS_RTP_SEND(stream->rtpsend),rtps);
+ stream->rtprecv=ms_rtp_recv_new();
+ ms_rtp_recv_set_session(MS_RTP_RECV(stream->rtprecv),rtpr);
+
+
+ /* creates the local part */
+ if (infile==NULL) stream->soundread=snd_card_create_read_filter(captcard);
+ else stream->soundread=ms_read_new(infile);
+ if (outfile==NULL) stream->soundwrite=snd_card_create_write_filter(playcard);
+ else stream->soundwrite=ms_write_new(outfile);
+
+ /* creates the couple of encoder/decoder */
+ pt=rtp_profile_get_payload(profile,payload);
+ if (pt==NULL){
+ g_error("audiostream.c: undefined payload type.");
+ return NULL;
+ }
+ stream->encoder=ms_encoder_new_with_string_id(pt->mime_type);
+ stream->decoder=ms_decoder_new_with_string_id(pt->mime_type);
+ if ((stream->encoder==NULL) || (stream->decoder==NULL)){
+ /* big problem: we have not a registered codec for this payload...*/
+ audio_stream_free(stream);
+ g_error("mediastream.c: No decoder available for payload %i.",payload);
+ return NULL;
+ }
+ /* give the sound filters some properties */
+ ms_filter_set_property(stream->soundread,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate);
+ ms_filter_set_property(stream->soundwrite,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate);
+
+ /* give the encoder/decoder some parameters*/
+ ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate);
+ ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_BITRATE,&pt->normal_bitrate);
+ ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate);
+ ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_BITRATE,&pt->normal_bitrate);
+
+ ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_FMTP, (void*)pt->fmtp);
+ ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_FMTP,(void*)pt->fmtp);
+ /* create the synchronisation source */
+ stream->timer=ms_timer_new();
+
+ /* and then connect all */
+ ms_filter_add_link(stream->soundread,stream->encoder);
+ ms_filter_add_link(stream->encoder,stream->rtpsend);
+ ms_filter_add_link(stream->rtprecv,stream->decoder);
+ ms_filter_add_link(stream->decoder,stream->soundwrite);
+
+ ms_sync_attach(stream->timer,stream->soundread);
+ ms_sync_attach(stream->timer,stream->rtprecv);
+
+ /* and start */
+ ms_start(stream->timer);
+
+ return stream;
+}
+
+static int defcard=0;
+
+void audio_stream_set_default_card(int cardindex){
+ defcard=cardindex;
+}
+
+AudioStream * audio_stream_start_with_files(RtpProfile *prof,int locport,char *remip,
+ int remport,int profile,int jitt_comp,gchar *infile, gchar*outfile)
+{
+ return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,infile,outfile,NULL,NULL);
+}
+
+AudioStream * audio_stream_start(RtpProfile *prof,int locport,char *remip,int remport,int profile,int jitt_comp)
+{
+ SndCard *sndcard;
+ sndcard=snd_card_manager_get_card(snd_card_manager,defcard);
+ return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,NULL,NULL,sndcard,sndcard);
+}
+
+AudioStream *audio_stream_start_with_sndcards(RtpProfile *prof,int locport,char *remip,int remport,int profile,int jitt_comp,SndCard *playcard, SndCard *captcard)
+{
+ g_return_val_if_fail(playcard!=NULL,NULL);
+ g_return_val_if_fail(captcard!=NULL,NULL);
+ return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,NULL,NULL,playcard,captcard);
+}
+
+void audio_stream_set_rtcp_information(AudioStream *st, const char *cname){
+ if (st->send_session!=NULL){
+ rtp_session_set_source_description(st->send_session,cname,NULL,NULL,NULL, NULL,"linphone",
+ "This is free software (GPL) !");
+ }
+}
+
+void audio_stream_stop(AudioStream * stream)
+{
+
+ ms_stop(stream->timer);
+ ortp_global_stats_display();
+ ms_sync_detach(stream->timer,stream->soundread);
+ ms_sync_detach(stream->timer,stream->rtprecv);
+
+ ms_filter_remove_links(stream->soundread,stream->encoder);
+ ms_filter_remove_links(stream->encoder,stream->rtpsend);
+ ms_filter_remove_links(stream->rtprecv,stream->decoder);
+ ms_filter_remove_links(stream->decoder,stream->soundwrite);
+
+ audio_stream_free(stream);
+}
+
+RingStream * ring_start(gchar *file,gint interval,SndCard *sndcard)
+{
+ return ring_start_with_cb(file,interval,sndcard,NULL,NULL);
+}
+
+RingStream * ring_start_with_cb(gchar *file,gint interval,SndCard *sndcard, MSFilterNotifyFunc func,gpointer user_data)
+{
+ RingStream *stream;
+ int tmp;
+ g_return_val_if_fail(sndcard!=NULL,NULL);
+ stream=g_new0(RingStream,1);
+ stream->source=ms_ring_player_new(file,interval);
+ if (stream->source==NULL) {
+ g_warning("Could not create ring player. Probably the ring file (%s) does not exist.",file);
+ return NULL;
+ }
+ if (func!=NULL) ms_filter_set_notify_func(MS_FILTER(stream->source),func,user_data);
+ stream->sndwrite=snd_card_create_write_filter(sndcard);
+ ms_filter_get_property(stream->source,MS_FILTER_PROPERTY_FREQ,&tmp);
+ ms_filter_set_property(stream->sndwrite,MS_FILTER_PROPERTY_FREQ,&tmp);
+ ms_filter_get_property(stream->source,MS_FILTER_PROPERTY_CHANNELS,&tmp);
+ ms_filter_set_property(stream->sndwrite,MS_FILTER_PROPERTY_CHANNELS,&tmp);
+ stream->timer=ms_timer_new();
+ ms_filter_add_link(stream->source,stream->sndwrite);
+ ms_sync_attach(stream->timer,stream->source);
+ ms_start(stream->timer);
+ return stream;
+}
+
+void ring_stop(RingStream *stream)
+{
+ ms_stop(stream->timer);
+ ms_sync_detach(stream->timer,stream->source);
+ ms_sync_destroy(stream->timer);
+ ms_filter_remove_links(stream->source,stream->sndwrite);
+ ms_filter_destroy(stream->source);
+ ms_filter_destroy(stream->sndwrite);
+ g_free(stream);
+}
+
+/* returns the latency in samples if the audio device with id dev_id is openable in full duplex mode, else 0 */
+gint test_audio_dev(int dev_id)
+{
+ gint err;
+ SndCard *sndcard=snd_card_manager_get_card(snd_card_manager,dev_id);
+ if (sndcard==NULL) return -1;
+ err=snd_card_probe(sndcard,16,0,8000);
+ return err; /* return latency in number of sample */
+}
+
+gint audio_stream_send_dtmf(AudioStream *stream, gchar dtmf)
+{
+ ms_rtp_send_dtmf(MS_RTP_SEND(stream->rtpsend), dtmf);
+ ms_oss_write_play_dtmf(MS_OSS_WRITE(stream->soundwrite),dtmf);
+}