Thu, 05 Jan 2006 05:29:51 +0000
[gaim-migrate @ 15077]
jabber.c:389: warning: ISO C90 forbids mixed declarations and code
| 12024 | 1 | /* |
| 2 | The mediastreamer library aims at providing modular media processing and I/O | |
| 3 | for linphone, but also for any telephony application. | |
| 4 | Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org | |
| 5 | ||
| 6 | This library is free software; you can redistribute it and/or | |
| 7 | modify it under the terms of the GNU Lesser General Public | |
| 8 | License as published by the Free Software Foundation; either | |
| 9 | version 2.1 of the License, or (at your option) any later version. | |
| 10 | ||
| 11 | This library is distributed in the hope that it will be useful, | |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | Lesser General Public License for more details. | |
| 15 | ||
| 16 | You should have received a copy of the GNU Lesser General Public | |
| 17 | License along with this library; if not, write to the Free Software | |
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | */ | |
| 20 | ||
| 21 | #include "mediastream.h" | |
| 22 | #ifdef INET6 | |
| 23 | #include <sys/types.h> | |
| 24 | #include <sys/socket.h> | |
| 25 | #include <netdb.h> | |
| 26 | #endif | |
| 27 | ||
| 28 | ||
| 29 | #define MAX_RTP_SIZE 1500 | |
| 30 | ||
| 31 | /* this code is not part of the library itself, it is part of the mediastream program */ | |
| 32 | void audio_stream_free(AudioStream *stream) | |
| 33 | { | |
| 34 | RtpSession *s; | |
| 35 | RtpSession *destroyed=NULL; | |
| 36 | if (stream->rtprecv!=NULL) { | |
| 37 | s=ms_rtp_recv_get_session(MS_RTP_RECV(stream->rtprecv)); | |
| 38 | if (s!=NULL){ | |
| 39 | destroyed=s; | |
| 40 | rtp_session_destroy(s); | |
| 41 | } | |
| 42 | ms_filter_destroy(stream->rtprecv); | |
| 43 | } | |
| 44 | if (stream->rtpsend!=NULL) { | |
| 45 | s=ms_rtp_send_get_session(MS_RTP_SEND(stream->rtpsend)); | |
| 46 | if (s!=NULL){ | |
| 47 | if (s!=destroyed) | |
| 48 | rtp_session_destroy(s); | |
| 49 | } | |
| 50 | ms_filter_destroy(stream->rtpsend); | |
| 51 | } | |
| 52 | if (stream->soundread!=NULL) ms_filter_destroy(stream->soundread); | |
| 53 | if (stream->soundwrite!=NULL) ms_filter_destroy(stream->soundwrite); | |
| 54 | if (stream->encoder!=NULL) ms_filter_destroy(stream->encoder); | |
| 55 | if (stream->decoder!=NULL) ms_filter_destroy(stream->decoder); | |
| 56 | if (stream->timer!=NULL) ms_sync_destroy(stream->timer); | |
| 57 | g_free(stream); | |
| 58 | } | |
| 59 | ||
| 60 | static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'}; | |
| 61 | ||
| 62 | static void on_dtmf_received(RtpSession *s,gint dtmf,gpointer user_data) | |
| 63 | { | |
| 64 | AudioStream *stream=(AudioStream*)user_data; | |
| 65 | if (dtmf>15){ | |
| 66 | g_warning("Unsupported telephone-event type."); | |
| 67 | return; | |
| 68 | } | |
| 69 | g_message("Receiving dtmf %c.",dtmf_tab[dtmf]); | |
| 70 | if (stream!=NULL){ | |
| 71 | if (strcmp(stream->soundwrite->klass->name,"OssWrite")==0) | |
| 72 | ms_oss_write_play_dtmf(MS_OSS_WRITE(stream->soundwrite),dtmf_tab[dtmf]); | |
| 73 | } | |
| 74 | } | |
| 75 | ||
| 76 | static void on_timestamp_jump(RtpSession *s,guint32* ts, gpointer user_data) | |
| 77 | { | |
| 78 | g_warning("The remote sip-phone has send data with a future timestamp: %u," | |
| 79 | "resynchronising session.",*ts); | |
| 80 | rtp_session_reset(s); | |
| 81 | } | |
| 82 | ||
| 83 | static const char *ip4local="0.0.0.0"; | |
| 84 | static const char *ip6local="::"; | |
| 85 | ||
| 86 | const char *get_local_addr_for(const char *remote) | |
| 87 | { | |
| 88 | const char *ret; | |
| 89 | #ifdef INET6 | |
| 90 | struct addrinfo hints, *res0; | |
| 91 | int err; | |
| 92 | memset(&hints, 0, sizeof(hints)); | |
| 93 | hints.ai_family = PF_UNSPEC; | |
| 94 | hints.ai_socktype = SOCK_DGRAM; | |
| 95 | err = getaddrinfo(remote,"8000", &hints, &res0); | |
| 96 | if (err!=0) { | |
| 97 | g_warning ("get_local_addr_for: %s", gai_strerror(err)); | |
| 98 | return ip4local; | |
| 99 | } | |
| 100 | ret=(res0->ai_addr->sa_family==AF_INET6) ? ip6local : ip4local; | |
| 101 | freeaddrinfo(res0); | |
| 102 | #else | |
| 103 | ret=ip4local; | |
| 104 | #endif | |
| 105 | return ret; | |
| 106 | } | |
| 107 | ||
| 108 | void create_duplex_rtpsession(RtpProfile *profile, int locport,char *remip,int remport, | |
| 109 | int payload,int jitt_comp, | |
| 110 | RtpSession **recvsend){ | |
| 111 | RtpSession *rtpr; | |
| 112 | rtpr=rtp_session_new(RTP_SESSION_SENDRECV); | |
| 113 | rtp_session_max_buf_size_set(rtpr,MAX_RTP_SIZE); | |
| 114 | rtp_session_set_profile(rtpr,profile); | |
| 115 | rtp_session_set_local_addr(rtpr,get_local_addr_for(remip),locport); | |
| 116 | if (remport>0) rtp_session_set_remote_addr(rtpr,remip,remport); | |
| 117 | rtp_session_set_scheduling_mode(rtpr,0); | |
| 118 | rtp_session_set_blocking_mode(rtpr,0); | |
| 119 | rtp_session_set_payload_type(rtpr,payload); | |
| 120 | rtp_session_set_jitter_compensation(rtpr,jitt_comp); | |
| 121 | rtp_session_enable_adaptive_jitter_compensation(rtpr,TRUE); | |
| 122 | /*rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)on_timestamp_jump,NULL);*/ | |
| 123 | *recvsend=rtpr; | |
| 124 | } | |
| 125 | ||
| 126 | void create_rtp_sessions(RtpProfile *profile, int locport,char *remip,int remport, | |
| 127 | int payload,int jitt_comp, | |
| 128 | RtpSession **recv, RtpSession **send){ | |
| 129 | RtpSession *rtps,*rtpr; | |
| 130 | /* creates two rtp filters to recv send streams (remote part)*/ | |
| 131 | ||
| 132 | rtps=rtp_session_new(RTP_SESSION_SENDONLY); | |
| 133 | rtp_session_max_buf_size_set(rtps,MAX_RTP_SIZE); | |
| 134 | rtp_session_set_profile(rtps,profile); | |
| 135 | #ifdef INET6 | |
| 136 | rtp_session_set_local_addr(rtps,"::",locport+2); | |
| 137 | #else | |
| 138 | rtp_session_set_local_addr(rtps,"0.0.0.0",locport+2); | |
| 139 | #endif | |
| 140 | rtp_session_set_remote_addr(rtps,remip,remport); | |
| 141 | rtp_session_set_scheduling_mode(rtps,0); | |
| 142 | rtp_session_set_blocking_mode(rtps,0); | |
| 143 | rtp_session_set_payload_type(rtps,payload); | |
| 144 | rtp_session_set_jitter_compensation(rtps,jitt_comp); | |
| 145 | ||
| 146 | rtpr=rtp_session_new(RTP_SESSION_RECVONLY); | |
| 147 | rtp_session_max_buf_size_set(rtpr,MAX_RTP_SIZE); | |
| 148 | rtp_session_set_profile(rtpr,profile); | |
| 149 | #ifdef INET6 | |
| 150 | rtp_session_set_local_addr(rtpr,"::",locport); | |
| 151 | #else | |
| 152 | rtp_session_set_local_addr(rtpr,"0.0.0.0",locport); | |
| 153 | #endif | |
| 154 | rtp_session_set_scheduling_mode(rtpr,0); | |
| 155 | rtp_session_set_blocking_mode(rtpr,0); | |
| 156 | rtp_session_set_payload_type(rtpr,payload); | |
| 157 | rtp_session_set_jitter_compensation(rtpr,jitt_comp); | |
| 158 | rtp_session_signal_connect(rtpr,"telephone-event",(RtpCallback)on_dtmf_received,NULL); | |
| 159 | rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)on_timestamp_jump,NULL); | |
| 160 | *recv=rtpr; | |
| 161 | *send=rtps; | |
| 162 | ||
| 163 | } | |
| 164 | ||
| 165 | ||
| 166 | AudioStream * audio_stream_start_full(RtpProfile *profile, int locport,char *remip,int remport, | |
| 167 | int payload,int jitt_comp, gchar *infile, gchar *outfile, SndCard *playcard, SndCard *captcard) | |
| 168 | { | |
| 169 | AudioStream *stream=g_new0(AudioStream,1); | |
| 170 | RtpSession *rtps,*rtpr; | |
| 171 | PayloadType *pt; | |
| 172 | ||
| 173 | //create_rtp_sessions(profile,locport,remip,remport,payload,jitt_comp,&rtpr,&rtps); | |
| 174 | ||
| 175 | create_duplex_rtpsession(profile,locport,remip,remport,payload,jitt_comp,&rtpr); | |
| 176 | rtp_session_signal_connect(rtpr,"telephone-event",(RtpCallback)on_dtmf_received,(gpointer)stream); | |
| 177 | rtps=rtpr; | |
| 178 | ||
| 179 | stream->rtpsend=ms_rtp_send_new(); | |
| 180 | ms_rtp_send_set_session(MS_RTP_SEND(stream->rtpsend),rtps); | |
| 181 | stream->rtprecv=ms_rtp_recv_new(); | |
| 182 | ms_rtp_recv_set_session(MS_RTP_RECV(stream->rtprecv),rtpr); | |
| 183 | ||
| 184 | ||
| 185 | /* creates the local part */ | |
| 186 | if (infile==NULL) stream->soundread=snd_card_create_read_filter(captcard); | |
| 187 | else stream->soundread=ms_read_new(infile); | |
| 188 | if (outfile==NULL) stream->soundwrite=snd_card_create_write_filter(playcard); | |
| 189 | else stream->soundwrite=ms_write_new(outfile); | |
| 190 | ||
| 191 | /* creates the couple of encoder/decoder */ | |
| 192 | pt=rtp_profile_get_payload(profile,payload); | |
| 193 | if (pt==NULL){ | |
| 194 | g_error("audiostream.c: undefined payload type."); | |
| 195 | return NULL; | |
| 196 | } | |
| 197 | stream->encoder=ms_encoder_new_with_string_id(pt->mime_type); | |
| 198 | stream->decoder=ms_decoder_new_with_string_id(pt->mime_type); | |
| 199 | if ((stream->encoder==NULL) || (stream->decoder==NULL)){ | |
| 200 | /* big problem: we have not a registered codec for this payload...*/ | |
| 201 | audio_stream_free(stream); | |
| 202 | g_error("mediastream.c: No decoder available for payload %i.",payload); | |
| 203 | return NULL; | |
| 204 | } | |
| 205 | /* give the sound filters some properties */ | |
| 206 | ms_filter_set_property(stream->soundread,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate); | |
| 207 | ms_filter_set_property(stream->soundwrite,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate); | |
| 208 | ||
| 209 | /* give the encoder/decoder some parameters*/ | |
| 210 | ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate); | |
| 211 | ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_BITRATE,&pt->normal_bitrate); | |
| 212 | ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate); | |
| 213 | ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_BITRATE,&pt->normal_bitrate); | |
| 214 | ||
| 215 | ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_FMTP, (void*)pt->fmtp); | |
| 216 | ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_FMTP,(void*)pt->fmtp); | |
| 217 | /* create the synchronisation source */ | |
| 218 | stream->timer=ms_timer_new(); | |
| 219 | ||
| 220 | /* and then connect all */ | |
| 221 | ms_filter_add_link(stream->soundread,stream->encoder); | |
| 222 | ms_filter_add_link(stream->encoder,stream->rtpsend); | |
| 223 | ms_filter_add_link(stream->rtprecv,stream->decoder); | |
| 224 | ms_filter_add_link(stream->decoder,stream->soundwrite); | |
| 225 | ||
| 226 | ms_sync_attach(stream->timer,stream->soundread); | |
| 227 | ms_sync_attach(stream->timer,stream->rtprecv); | |
| 228 | ||
| 229 | /* and start */ | |
| 230 | ms_start(stream->timer); | |
| 231 | ||
| 232 | return stream; | |
| 233 | } | |
| 234 | ||
| 235 | static int defcard=0; | |
| 236 | ||
| 237 | void audio_stream_set_default_card(int cardindex){ | |
| 238 | defcard=cardindex; | |
| 239 | } | |
| 240 | ||
| 241 | AudioStream * audio_stream_start_with_files(RtpProfile *prof,int locport,char *remip, | |
| 242 | int remport,int profile,int jitt_comp,gchar *infile, gchar*outfile) | |
| 243 | { | |
| 244 | return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,infile,outfile,NULL,NULL); | |
| 245 | } | |
| 246 | ||
| 247 | AudioStream * audio_stream_start(RtpProfile *prof,int locport,char *remip,int remport,int profile,int jitt_comp) | |
| 248 | { | |
| 249 | SndCard *sndcard; | |
| 250 | sndcard=snd_card_manager_get_card(snd_card_manager,defcard); | |
| 251 | return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,NULL,NULL,sndcard,sndcard); | |
| 252 | } | |
| 253 | ||
| 254 | AudioStream *audio_stream_start_with_sndcards(RtpProfile *prof,int locport,char *remip,int remport,int profile,int jitt_comp,SndCard *playcard, SndCard *captcard) | |
| 255 | { | |
| 256 | g_return_val_if_fail(playcard!=NULL,NULL); | |
| 257 | g_return_val_if_fail(captcard!=NULL,NULL); | |
| 258 | return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,NULL,NULL,playcard,captcard); | |
| 259 | } | |
| 260 | ||
| 261 | void audio_stream_set_rtcp_information(AudioStream *st, const char *cname){ | |
| 262 | if (st->send_session!=NULL){ | |
| 263 | rtp_session_set_source_description(st->send_session,cname,NULL,NULL,NULL,NULL,"linphone-" "2.0.0", // SME | |
| 264 | "This is free software (GPL) !"); | |
| 265 | } | |
| 266 | } | |
| 267 | ||
| 268 | void audio_stream_stop(AudioStream * stream) | |
| 269 | { | |
| 270 | ||
| 271 | ms_stop(stream->timer); | |
| 272 | ortp_global_stats_display(); | |
| 273 | ms_sync_detach(stream->timer,stream->soundread); | |
| 274 | ms_sync_detach(stream->timer,stream->rtprecv); | |
| 275 | ||
| 276 | ms_filter_remove_links(stream->soundread,stream->encoder); | |
| 277 | ms_filter_remove_links(stream->encoder,stream->rtpsend); | |
| 278 | ms_filter_remove_links(stream->rtprecv,stream->decoder); | |
| 279 | ms_filter_remove_links(stream->decoder,stream->soundwrite); | |
| 280 | ||
| 281 | audio_stream_free(stream); | |
| 282 | } | |
| 283 | ||
| 284 | RingStream * ring_start(gchar *file,gint interval,SndCard *sndcard) | |
| 285 | { | |
| 286 | return ring_start_with_cb(file,interval,sndcard,NULL,NULL); | |
| 287 | } | |
| 288 | ||
| 289 | RingStream * ring_start_with_cb(gchar *file,gint interval,SndCard *sndcard, MSFilterNotifyFunc func,gpointer user_data) | |
| 290 | { | |
| 291 | RingStream *stream; | |
| 292 | int tmp; | |
| 293 | g_return_val_if_fail(sndcard!=NULL,NULL); | |
| 294 | stream=g_new0(RingStream,1); | |
| 295 | stream->source=ms_ring_player_new(file,interval); | |
| 296 | if (stream->source==NULL) { | |
| 297 | g_warning("Could not create ring player. Probably the ring file (%s) does not exist.",file); | |
| 298 | return NULL; | |
| 299 | } | |
| 300 | if (func!=NULL) ms_filter_set_notify_func(MS_FILTER(stream->source),func,user_data); | |
| 301 | stream->sndwrite=snd_card_create_write_filter(sndcard); | |
| 302 | ms_filter_get_property(stream->source,MS_FILTER_PROPERTY_FREQ,&tmp); | |
| 303 | ms_filter_set_property(stream->sndwrite,MS_FILTER_PROPERTY_FREQ,&tmp); | |
| 304 | ms_filter_get_property(stream->source,MS_FILTER_PROPERTY_CHANNELS,&tmp); | |
| 305 | ms_filter_set_property(stream->sndwrite,MS_FILTER_PROPERTY_CHANNELS,&tmp); | |
| 306 | stream->timer=ms_timer_new(); | |
| 307 | ms_filter_add_link(stream->source,stream->sndwrite); | |
| 308 | ms_sync_attach(stream->timer,stream->source); | |
| 309 | ms_start(stream->timer); | |
| 310 | return stream; | |
| 311 | } | |
| 312 | ||
| 313 | void ring_stop(RingStream *stream) | |
| 314 | { | |
| 315 | ms_stop(stream->timer); | |
| 316 | ms_sync_detach(stream->timer,stream->source); | |
| 317 | ms_sync_destroy(stream->timer); | |
| 318 | ms_filter_remove_links(stream->source,stream->sndwrite); | |
| 319 | ms_filter_destroy(stream->source); | |
| 320 | ms_filter_destroy(stream->sndwrite); | |
| 321 | g_free(stream); | |
| 322 | } | |
| 323 | ||
| 324 | /* returns the latency in samples if the audio device with id dev_id is openable in full duplex mode, else 0 */ | |
| 325 | gint test_audio_dev(int dev_id) | |
| 326 | { | |
| 327 | gint err; | |
| 328 | SndCard *sndcard=snd_card_manager_get_card(snd_card_manager,dev_id); | |
| 329 | if (sndcard==NULL) return -1; | |
| 330 | err=snd_card_probe(sndcard,16,0,8000); | |
| 331 | return err; /* return latency in number of sample */ | |
| 332 | } | |
| 333 | ||
| 334 | gint audio_stream_send_dtmf(AudioStream *stream, gchar dtmf) | |
| 335 | { | |
| 336 | ms_rtp_send_dtmf(MS_RTP_SEND(stream->rtpsend), dtmf); | |
| 337 | ms_oss_write_play_dtmf(MS_OSS_WRITE(stream->soundwrite),dtmf); | |
|
12029
e47434c9f4af
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
338 | |
|
e47434c9f4af
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
339 | /* not sure what this should be returning, nothing in mediastreamer calls |
|
e47434c9f4af
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
340 | * it directly, assuming 0 is okay here. -- Gary |
|
e47434c9f4af
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
341 | */ |
|
e47434c9f4af
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
342 | return 0; |
| 12024 | 343 | } |