source: mediastreamer2/src/audiostream.c @ 1013:070963a32165

Last change on this file since 1013:070963a32165 was 1013:070963a32165, checked in by Simon Morlat <simon.morlat@…>, 3 years ago

fix compil error

File size: 21.6 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20
21#ifdef HAVE_CONFIG_H
22#include "mediastreamer-config.h"
23#endif
24
25#include "mediastreamer2/mediastream.h"
26
27#include "mediastreamer2/dtmfgen.h"
28#include "mediastreamer2/mssndcard.h"
29#include "mediastreamer2/msrtp.h"
30#include "mediastreamer2/msfileplayer.h"
31#include "mediastreamer2/msfilerec.h"
32#include "mediastreamer2/msvolume.h"
33#include "mediastreamer2/msequalizer.h"
34
35#ifdef INET6
36        #include <sys/types.h>
37#ifndef WIN32
38        #include <sys/socket.h>
39        #include <netdb.h>
40#endif
41#endif
42
43
44#define MAX_RTP_SIZE    1500
45
46
47/* this code is not part of the library itself, it is part of the mediastream program */
48void audio_stream_free(AudioStream *stream)
49{
50        if (stream->session!=NULL) rtp_session_destroy(stream->session);
51        if (stream->rtpsend!=NULL) ms_filter_destroy(stream->rtpsend);
52        if (stream->rtprecv!=NULL) ms_filter_destroy(stream->rtprecv);
53        if (stream->soundread!=NULL) ms_filter_destroy(stream->soundread);
54        if (stream->soundwrite!=NULL) ms_filter_destroy(stream->soundwrite);
55        if (stream->encoder!=NULL) ms_filter_destroy(stream->encoder);
56        if (stream->decoder!=NULL) ms_filter_destroy(stream->decoder);
57        if (stream->dtmfgen!=NULL) ms_filter_destroy(stream->dtmfgen);
58        if (stream->ec!=NULL)   ms_filter_destroy(stream->ec);
59        if (stream->volrecv!=NULL) ms_filter_destroy(stream->volrecv);
60        if (stream->volsend!=NULL) ms_filter_destroy(stream->volsend);
61        if (stream->equalizer!=NULL) ms_filter_destroy(stream->equalizer);
62        if (stream->ticker!=NULL) ms_ticker_destroy(stream->ticker);
63        if (stream->read_resampler!=NULL) ms_filter_destroy(stream->read_resampler);
64        if (stream->write_resampler!=NULL) ms_filter_destroy(stream->write_resampler);
65        ms_free(stream);
66}
67
68static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
69
70static void on_dtmf_received(RtpSession *s, int dtmf, void * user_data)
71{
72        AudioStream *stream=(AudioStream*)user_data;
73        if (dtmf>15){
74                ms_warning("Unsupported telephone-event type.");
75                return;
76        }
77        ms_message("Receiving dtmf %c.",dtmf_tab[dtmf]);
78        if (stream->dtmfgen!=NULL && stream->play_dtmfs){
79                ms_filter_call_method(stream->dtmfgen,MS_DTMF_GEN_PUT,&dtmf_tab[dtmf]);
80        }
81}
82
83bool_t ms_is_ipv6(const char *remote){
84        bool_t ret=FALSE;
85#ifdef INET6
86        struct addrinfo hints, *res0;
87
88        int err;
89        memset(&hints, 0, sizeof(hints));
90        hints.ai_family = PF_UNSPEC;
91        hints.ai_socktype = SOCK_DGRAM;
92        err = getaddrinfo(remote,"8000", &hints, &res0);
93        if (err!=0) {
94                ms_warning ("get_local_addr_for: %s", gai_strerror(err));
95                return FALSE;
96        }
97        ret=(res0->ai_addr->sa_family==AF_INET6);
98        freeaddrinfo(res0);
99#endif
100        return ret;
101}
102
103static void audio_stream_configure_resampler(MSFilter *resampler,MSFilter *from,MSFilter *to) {
104        int from_rate=0, to_rate=0;
105        ms_filter_call_method(from,MS_FILTER_GET_SAMPLE_RATE,&from_rate);
106        ms_filter_call_method(to,MS_FILTER_GET_SAMPLE_RATE,&to_rate);
107        ms_filter_call_method(resampler,MS_FILTER_SET_SAMPLE_RATE,&from_rate);
108        ms_filter_call_method(resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&to_rate);
109        ms_debug("configuring from rate[%i] to rate [%i]",from_rate,to_rate);
110}
111
112RtpSession * create_duplex_rtpsession( int locport, bool_t ipv6){
113        RtpSession *rtpr;
114        rtpr=rtp_session_new(RTP_SESSION_SENDRECV);
115        rtp_session_set_recv_buf_size(rtpr,MAX_RTP_SIZE);
116        rtp_session_set_scheduling_mode(rtpr,0);
117        rtp_session_set_blocking_mode(rtpr,0);
118        rtp_session_enable_adaptive_jitter_compensation(rtpr,TRUE);
119        rtp_session_set_symmetric_rtp(rtpr,TRUE);
120        rtp_session_set_local_addr(rtpr,ipv6 ? "::" : "0.0.0.0",locport);
121        rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)rtp_session_resync,(long)NULL);
122        rtp_session_signal_connect(rtpr,"ssrc_changed",(RtpCallback)rtp_session_resync,(long)NULL);
123        rtp_session_set_ssrc_changed_threshold(rtpr,0);
124        return rtpr;
125}
126
127#if defined(_WIN32_WCE)
128time_t
129ms_time (time_t *t)
130{
131    DWORD timemillis = GetTickCount();
132        if (timemillis>0)
133        {
134                if (t!=NULL)
135                        *t = timemillis/1000;
136        }
137        return timemillis/1000;
138}
139#endif
140
141bool_t audio_stream_alive(AudioStream * stream, int timeout){
142        RtpSession *session=stream->session;
143        const rtp_stats_t *stats=rtp_session_get_stats(session);
144        if (stats->recv!=0){
145                if (stats->recv!=stream->last_packet_count){
146                        stream->last_packet_count=stats->recv;
147                        stream->last_packet_time=ms_time(NULL);
148                }else{
149                        if (ms_time(NULL)-stream->last_packet_time>timeout){
150                                /* more than timeout seconds of inactivity*/
151                                return FALSE;
152                        }
153                }
154        }
155        return TRUE;
156}
157
158/*this function must be called from the MSTicker thread:
159it replaces one filter by another one.
160This is a dirty hack that works anyway.
161It would be interesting to have something that does the job
162simplier within the MSTicker api
163*/
164void audio_stream_change_decoder(AudioStream *stream, int payload){
165        RtpSession *session=stream->session;
166        RtpProfile *prof=rtp_session_get_profile(session);
167        PayloadType *pt=rtp_profile_get_payload(prof,payload);
168        if (pt!=NULL){
169                MSFilter *dec=ms_filter_create_decoder(pt->mime_type);
170                if (dec!=NULL){
171                        ms_filter_unlink(stream->rtprecv, 0, stream->decoder, 0);
172                        ms_filter_unlink(stream->decoder,0,stream->dtmfgen,0);
173                        ms_filter_postprocess(stream->decoder);
174                        ms_filter_destroy(stream->decoder);
175                        stream->decoder=dec;
176                        if (pt->recv_fmtp!=NULL)
177                                ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp);
178                        ms_filter_link (stream->rtprecv, 0, stream->decoder, 0);
179                        ms_filter_link (stream->decoder,0 , stream->dtmfgen, 0);
180                        ms_filter_preprocess(stream->decoder,stream->ticker);
181
182                }else{
183                        ms_warning("No decoder found for %s",pt->mime_type);
184                }
185        }else{
186                ms_warning("No payload defined with number %i",payload);
187        }
188}
189
190static void payload_type_changed(RtpSession *session, unsigned long data){
191        AudioStream *stream=(AudioStream*)data;
192        int pt=rtp_session_get_recv_payload_type(stream->session);
193        audio_stream_change_decoder(stream,pt);
194}
195
196
197int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char *remip,int remport,
198        int rem_rtcp_port, int payload,int jitt_comp, const char *infile, const char *outfile,
199        MSSndCard *playcard, MSSndCard *captcard, bool_t use_ec)
200{
201        RtpSession *rtps=stream->session;
202        PayloadType *pt;
203        int tmp;
204        MSConnectionHelper h;
205
206        rtp_session_set_profile(rtps,profile);
207        if (remport>0) rtp_session_set_remote_addr_full(rtps,remip,remport,rem_rtcp_port);
208        rtp_session_set_payload_type(rtps,payload);
209        rtp_session_set_jitter_compensation(rtps,jitt_comp);
210
211        if (remport>0)
212                ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_SET_SESSION,rtps);
213        stream->rtprecv=ms_filter_new(MS_RTP_RECV_ID);
214        ms_filter_call_method(stream->rtprecv,MS_RTP_RECV_SET_SESSION,rtps);
215        stream->session=rtps;
216
217        stream->dtmfgen=ms_filter_new(MS_DTMF_GEN_ID);
218        rtp_session_signal_connect(rtps,"telephone-event",(RtpCallback)on_dtmf_received,(unsigned long)stream);
219        rtp_session_signal_connect(rtps,"payload_type_changed",(RtpCallback)payload_type_changed,(unsigned long)stream);
220
221        /* creates the local part */
222        if (captcard!=NULL) stream->soundread=ms_snd_card_create_reader(captcard);
223        else {
224                stream->soundread=ms_filter_new(MS_FILE_PLAYER_ID);
225                stream->read_resampler=ms_filter_new(MS_RESAMPLE_ID);
226                if (infile!=NULL) audio_stream_play(stream,infile);
227        }
228        if (playcard!=NULL) stream->soundwrite=ms_snd_card_create_writer(playcard);
229        else {
230                stream->soundwrite=ms_filter_new(MS_FILE_REC_ID);
231                if (outfile!=NULL) audio_stream_record(stream,outfile);
232        }
233
234        /* creates the couple of encoder/decoder */
235        pt=rtp_profile_get_payload(profile,payload);
236        if (pt==NULL){
237                ms_error("audiostream.c: undefined payload type.");
238                return -1;
239        }
240        stream->encoder=ms_filter_create_encoder(pt->mime_type);
241        stream->decoder=ms_filter_create_decoder(pt->mime_type);
242        if ((stream->encoder==NULL) || (stream->decoder==NULL)){
243                /* big problem: we have not a registered codec for this payload...*/
244                ms_error("mediastream.c: No decoder available for payload %i.",payload);
245                return -1;
246        }
247
248        if (use_ec) {
249                stream->ec=ms_filter_new(MS_SPEEX_EC_ID);
250                ms_filter_call_method(stream->ec,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate);
251                if (stream->ec_tail_len!=0)
252                        ms_filter_call_method(stream->ec,MS_ECHO_CANCELLER_SET_TAIL_LENGTH,&stream->ec_tail_len);
253                if (stream->ec_delay!=0)
254                        ms_filter_call_method(stream->ec,MS_ECHO_CANCELLER_SET_DELAY,&stream->ec_delay);
255                if (stream->ec_framesize!=0)
256                        ms_filter_call_method(stream->ec,MS_ECHO_CANCELLER_SET_FRAMESIZE,&stream->ec_framesize);
257        }
258
259        if (stream->el_type!=ELInactive || stream->use_gc || stream->use_ng){
260                stream->volsend=ms_filter_new(MS_VOLUME_ID);
261                stream->volrecv=ms_filter_new(MS_VOLUME_ID);
262                if (stream->el_type!=ELInactive){
263                        if (stream->el_type==ELControlSpeaker)
264                                ms_filter_call_method(stream->volrecv,MS_VOLUME_SET_PEER,stream->volsend);
265                        else ms_filter_call_method(stream->volsend,MS_VOLUME_SET_PEER,stream->volrecv);
266                }
267                if (stream->use_ng){
268                        int tmp=1;
269                        ms_filter_call_method(stream->volsend,MS_VOLUME_ENABLE_NOISE_GATE,&tmp);
270                }
271        }
272
273        if (stream->use_agc){
274                int tmp=1;
275                if (stream->volsend==NULL)
276                        stream->volsend=ms_filter_new(MS_VOLUME_ID);
277                ms_filter_call_method(stream->volsend,MS_VOLUME_ENABLE_AGC,&tmp);
278        }
279
280        /* give the sound filters some properties */
281        if (ms_filter_call_method(stream->soundread,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate) != 0) {
282                /* need to add resampler*/
283                if (stream->read_resampler == NULL) stream->read_resampler=ms_filter_new(MS_RESAMPLE_ID);
284        }
285
286        if (ms_filter_call_method(stream->soundwrite,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate) != 0) {
287                /* need to add resampler*/
288                if (stream->write_resampler == NULL) stream->write_resampler=ms_filter_new(MS_RESAMPLE_ID);
289        }
290
291
292        tmp=1;
293        ms_filter_call_method(stream->soundwrite,MS_FILTER_SET_NCHANNELS, &tmp);
294
295        /* give the encoder/decoder some parameters*/
296        ms_filter_call_method(stream->encoder,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate);
297        ms_message("Payload's bitrate is %i",pt->normal_bitrate);
298        if (pt->normal_bitrate>0){
299                ms_message("Setting audio encoder network bitrate to %i",pt->normal_bitrate);
300                ms_filter_call_method(stream->encoder,MS_FILTER_SET_BITRATE,&pt->normal_bitrate);
301        }
302        ms_filter_call_method(stream->decoder,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate);
303
304        if (pt->send_fmtp!=NULL) ms_filter_call_method(stream->encoder,MS_FILTER_ADD_FMTP, (void*)pt->send_fmtp);
305        if (pt->recv_fmtp!=NULL) ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp);
306
307        /*create the equalizer*/
308        stream->equalizer=ms_filter_new(MS_EQUALIZER_ID);
309        tmp=stream->eq_active;
310        ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp);
311        /*configure resampler if needed*/
312        if (stream->read_resampler){
313                audio_stream_configure_resampler(stream->read_resampler,stream->soundread,stream->rtpsend);
314        }
315
316        if (stream->write_resampler){
317                audio_stream_configure_resampler(stream->write_resampler,stream->rtprecv,stream->soundwrite);
318        }
319        /* and then connect all */
320        /* tip: draw yourself the picture if you don't understand */
321
322        /*sending graph*/
323        ms_connection_helper_start(&h);
324        ms_connection_helper_link(&h,stream->soundread,-1,0);
325        if (stream->read_resampler)
326                ms_connection_helper_link(&h,stream->read_resampler,0,0);
327        if (stream->ec)
328                ms_connection_helper_link(&h,stream->ec,1,1);
329        if (stream->volsend)
330                ms_connection_helper_link(&h,stream->volsend,0,0);
331        ms_connection_helper_link(&h,stream->encoder,0,0);
332        ms_connection_helper_link(&h,stream->rtpsend,0,-1);
333
334        /*receiving graph*/
335        ms_connection_helper_start(&h);
336        ms_connection_helper_link(&h,stream->rtprecv,-1,0);
337        ms_connection_helper_link(&h,stream->decoder,0,0);
338        ms_connection_helper_link(&h,stream->dtmfgen,0,0);
339        if (stream->equalizer)
340                ms_connection_helper_link(&h,stream->equalizer,0,0);
341        if (stream->volrecv)
342                ms_connection_helper_link(&h,stream->volrecv,0,0);
343        if (stream->ec)
344                ms_connection_helper_link(&h,stream->ec,0,0);
345        if (stream->write_resampler)
346                ms_connection_helper_link(&h,stream->write_resampler,0,0);
347        ms_connection_helper_link(&h,stream->soundwrite,0,-1);
348
349        /* create ticker */
350        stream->ticker=ms_ticker_new();
351        ms_ticker_set_name(stream->ticker,"Audio MSTicker");
352        ms_ticker_attach(stream->ticker,stream->soundread);
353        ms_ticker_attach(stream->ticker,stream->rtprecv);
354
355        return 0;
356}
357
358
359int audio_stream_start_with_files(AudioStream *stream, RtpProfile *prof,const char *remip, int remport,
360        int rem_rtcp_port, int pt,int jitt_comp, const char *infile, const char * outfile)
361{
362        return audio_stream_start_full(stream,prof,remip,remport,rem_rtcp_port,pt,jitt_comp,infile,outfile,NULL,NULL,FALSE);
363}
364
365AudioStream * audio_stream_start(RtpProfile *prof,int locport,const char *remip,int remport,int profile,int jitt_comp,bool_t use_ec)
366{
367        MSSndCard *sndcard_playback;
368        MSSndCard *sndcard_capture;
369        AudioStream *stream;
370        sndcard_capture=ms_snd_card_manager_get_default_capture_card(ms_snd_card_manager_get());
371        sndcard_playback=ms_snd_card_manager_get_default_playback_card(ms_snd_card_manager_get());
372        if (sndcard_capture==NULL || sndcard_playback==NULL)
373                return NULL;
374        stream=audio_stream_new(locport, ms_is_ipv6(remip));
375        if (audio_stream_start_full(stream,prof,remip,remport,remport+1,profile,jitt_comp,NULL,NULL,sndcard_playback,sndcard_capture,use_ec)==0) return stream;
376        audio_stream_free(stream);
377        return NULL;
378}
379
380AudioStream *audio_stream_start_with_sndcards(RtpProfile *prof,int locport,const char *remip,int remport,int profile,int jitt_comp,MSSndCard *playcard, MSSndCard *captcard, bool_t use_ec)
381{
382        AudioStream *stream;
383        if (playcard==NULL) {
384                ms_error("No playback card.");
385                return NULL;
386        }
387        if (captcard==NULL) {
388                ms_error("No capture card.");
389                return NULL;
390        }
391        stream=audio_stream_new(locport, ms_is_ipv6(remip));
392        if (audio_stream_start_full(stream,prof,remip,remport,remport+1,profile,jitt_comp,NULL,NULL,playcard,captcard,use_ec)==0) return stream;
393        audio_stream_free(stream);
394        return NULL;
395}
396
397void audio_stream_set_rtcp_information(AudioStream *st, const char *cname, const char *tool){
398        if (st->session!=NULL){
399                rtp_session_set_source_description(st->session,cname,NULL,NULL,NULL,NULL,tool , "This is free software (GPL) !");
400        }
401}
402
403void audio_stream_play(AudioStream *st, const char *name){
404        if (ms_filter_get_id(st->soundread)==MS_FILE_PLAYER_ID){
405                ms_filter_call_method_noarg(st->soundread,MS_FILE_PLAYER_CLOSE);
406                ms_filter_call_method(st->soundread,MS_FILE_PLAYER_OPEN,(void*)name);
407                if (st->read_resampler){
408                        audio_stream_configure_resampler(st->read_resampler,st->soundread,st->rtpsend);
409                }
410                ms_filter_call_method_noarg(st->soundread,MS_FILE_PLAYER_START);
411        }else{
412                ms_error("Cannot play file: the stream hasn't been started with"
413                " audio_stream_start_with_files");
414        }
415}
416
417void audio_stream_record(AudioStream *st, const char *name){
418        if (ms_filter_get_id(st->soundwrite)==MS_FILE_REC_ID){
419                ms_filter_call_method_noarg(st->soundwrite,MS_FILE_REC_CLOSE);
420                ms_filter_call_method(st->soundwrite,MS_FILE_REC_OPEN,(void*)name);
421                ms_filter_call_method_noarg(st->soundwrite,MS_FILE_REC_START);
422        }else{
423                ms_error("Cannot record file: the stream hasn't been started with"
424                " audio_stream_start_with_files");
425        }
426}
427
428
429AudioStream *audio_stream_new(int locport, bool_t ipv6){
430        AudioStream *stream=(AudioStream *)ms_new0(AudioStream,1);
431        stream->session=create_duplex_rtpsession(locport,ipv6);
432        stream->rtpsend=ms_filter_new(MS_RTP_SEND_ID);
433        stream->play_dtmfs=TRUE;
434        stream->use_gc=FALSE;
435        stream->use_agc=FALSE;
436        stream->use_ng=FALSE;
437        return stream;
438}
439
440void audio_stream_play_received_dtmfs(AudioStream *st, bool_t yesno){
441        st->play_dtmfs=yesno;
442}
443
444int audio_stream_start_now(AudioStream *stream, RtpProfile * prof,  const char *remip, int remport, int rem_rtcp_port, int payload_type, int jitt_comp, MSSndCard *playcard, MSSndCard *captcard, bool_t use_ec){
445        return audio_stream_start_full(stream,prof,remip,remport,rem_rtcp_port,
446                payload_type,jitt_comp,NULL,NULL,playcard,captcard,use_ec);
447}
448
449void audio_stream_set_relay_session_id(AudioStream *stream, const char *id){
450        ms_filter_call_method(stream->rtpsend, MS_RTP_SEND_SET_RELAY_SESSION_ID,(void*)id);
451}
452
453void audio_stream_set_echo_canceller_params(AudioStream *st, int tail_len_ms, int delay_ms, int framesize){
454        st->ec_tail_len=tail_len_ms;
455        st->ec_delay=delay_ms;
456        st->ec_framesize=framesize;
457}
458
459void audio_stream_enable_echo_limiter(AudioStream *stream, EchoLimiterType type){
460        stream->el_type=type;
461}
462
463void audio_stream_enable_gain_control(AudioStream *stream, bool_t val){
464        stream->use_gc=val;
465}
466
467void audio_stream_enable_automatic_gain_control(AudioStream *stream, bool_t val){
468        stream->use_agc=val;
469}
470
471void audio_stream_enable_noise_gate(AudioStream *stream, bool_t val){
472        stream->use_ng=val;
473}
474
475void audio_stream_set_mic_gain(AudioStream *stream, float gain){
476        if (stream->volsend){
477                ms_filter_call_method(stream->volsend,MS_VOLUME_SET_GAIN,&gain);
478        }else ms_warning("Could not apply gain: gain control wasn't activated. "
479                        "Use audio_stream_enable_gain_control() before starting the stream.");
480}
481
482void audio_stream_enable_equalizer(AudioStream *stream, bool_t enabled){
483        stream->eq_active=enabled;
484        if (stream->equalizer){
485                int tmp=enabled;
486                ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp);
487        }
488}
489
490void audio_stream_equalizer_set_gain(AudioStream *stream, int frequency, float gain, int freq_width){
491        if (stream->equalizer){
492                MSEqualizerGain d;
493                d.frequency=frequency;
494                d.gain=gain;
495                d.width=freq_width;
496                ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_GAIN,&d);
497        }
498}
499
500void audio_stream_stop(AudioStream * stream)
501{
502        if (stream->ticker){
503                MSConnectionHelper h;
504                ms_ticker_detach(stream->ticker,stream->soundread);
505                ms_ticker_detach(stream->ticker,stream->rtprecv);
506
507                rtp_stats_display(rtp_session_get_stats(stream->session),"Audio session's RTP statistics");
508
509                /*dismantle the outgoing graph*/
510                ms_connection_helper_start(&h);
511                ms_connection_helper_unlink(&h,stream->soundread,-1,0);
512                if (stream->read_resampler!=NULL)
513                        ms_connection_helper_unlink(&h,stream->read_resampler,0,0);
514                if (stream->ec!=NULL)
515                        ms_connection_helper_unlink(&h,stream->ec,1,1);
516                if (stream->volsend!=NULL)
517                        ms_connection_helper_unlink(&h,stream->volsend,0,0);
518                ms_connection_helper_unlink(&h,stream->encoder,0,0);
519                ms_connection_helper_unlink(&h,stream->rtpsend,0,-1);
520
521                /*dismantle the receiving graph*/
522                ms_connection_helper_start(&h);
523                ms_connection_helper_unlink(&h,stream->rtprecv,-1,0);
524                ms_connection_helper_unlink(&h,stream->decoder,0,0);
525                ms_connection_helper_unlink(&h,stream->dtmfgen,0,0);
526                if (stream->equalizer)
527                        ms_connection_helper_unlink(&h,stream->equalizer,0,0);
528                if (stream->volrecv!=NULL)
529                        ms_connection_helper_unlink(&h,stream->volrecv,0,0);
530                if (stream->ec!=NULL)
531                        ms_connection_helper_unlink(&h,stream->ec,0,0);
532                if (stream->write_resampler!=NULL)
533                        ms_connection_helper_unlink(&h,stream->write_resampler,0,0);
534                ms_connection_helper_unlink(&h,stream->soundwrite,0,-1);
535
536        }
537        audio_stream_free(stream);
538}
539
540RingStream * ring_start(const char *file, int interval, MSSndCard *sndcard){
541   return ring_start_with_cb(file,interval,sndcard,NULL,NULL);
542}
543
544RingStream * ring_start_with_cb(const char *file,int interval,MSSndCard *sndcard, MSFilterNotifyFunc func,void * user_data)
545{
546        RingStream *stream;
547        int tmp;
548        stream=(RingStream *)ms_new0(RingStream,1);
549        stream->source=ms_filter_new(MS_FILE_PLAYER_ID);
550        if (ms_filter_call_method(stream->source,MS_FILE_PLAYER_OPEN,(void*)file)<0){
551                ms_filter_destroy(stream->source);
552                ms_free(stream);
553                return NULL;
554        }
555        ms_filter_call_method(stream->source,MS_FILE_PLAYER_LOOP,&interval);
556        ms_filter_call_method_noarg(stream->source,MS_FILE_PLAYER_START);
557        if (func!=NULL)
558                ms_filter_set_notify_callback(stream->source,func,user_data);
559        stream->sndwrite=ms_snd_card_create_writer(sndcard);
560        ms_filter_call_method(stream->source,MS_FILTER_GET_SAMPLE_RATE,&tmp);
561        ms_filter_call_method(stream->sndwrite,MS_FILTER_SET_SAMPLE_RATE,&tmp);
562        ms_filter_call_method(stream->source,MS_FILTER_GET_NCHANNELS,&tmp);
563        ms_filter_call_method(stream->sndwrite,MS_FILTER_SET_NCHANNELS,&tmp);
564        stream->ticker=ms_ticker_new();
565        ms_ticker_set_name(stream->ticker,"Audio (ring) MSTicker");
566        ms_filter_link(stream->source,0,stream->sndwrite,0);
567        ms_ticker_attach(stream->ticker,stream->source);
568        return stream;
569}
570
571void ring_stop(RingStream *stream){
572        ms_ticker_detach(stream->ticker,stream->source);
573        ms_filter_unlink(stream->source,0,stream->sndwrite,0);
574        ms_ticker_destroy(stream->ticker);
575        ms_filter_destroy(stream->source);
576        ms_filter_destroy(stream->sndwrite);
577        ms_free(stream);
578#ifdef _WIN32_WCE
579        ms_warning("Sleeping a bit after closing the audio device...");
580        ms_sleep(1);
581#endif
582}
583
584
585int audio_stream_send_dtmf(AudioStream *stream, char dtmf)
586{
587        if (stream->rtpsend)
588                ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_SEND_DTMF,&dtmf);
589        if (stream->dtmfgen)
590                ms_filter_call_method(stream->dtmfgen,MS_DTMF_GEN_PUT,&dtmf);
591        return 0;
592}
593
594void audio_stream_get_local_rtp_stats(AudioStream *stream, rtp_stats_t *lstats){
595        if (stream->session){
596                const rtp_stats_t *stats=rtp_session_get_stats(stream->session);
597                memcpy(lstats,stats,sizeof(*stats));
598        }else memset(lstats,0,sizeof(rtp_stats_t));
599}
600
601
602void audio_stream_mute_rtp(AudioStream *stream, bool_t val) 
603{
604  if (stream->rtpsend){
605    if (val)
606      ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_MUTE_MIC,&val);
607    else
608      ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_UNMUTE_MIC,&val);
609  }
610}
Note: See TracBrowser for help on using the repository browser.