ringstream.c 6.48 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2006-2013 Belledonne Communications, Grenoble

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/



#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/dtmfgen.h"
#include "mediastreamer2/msfileplayer.h"
25
#include "private.h"
26 27


28 29
static void ring_player_event_handler(void *ud, MSFilter *f, unsigned int evid, void *arg){
	RingStream *stream=(RingStream*)ud;
30

31
	if (evid==MS_FILTER_OUTPUT_FMT_CHANGED){
32 33 34 35 36 37 38
		MSPinFormat pinfmt={0};
		ms_filter_call_method(stream->source, MS_FILTER_GET_OUTPUT_FMT, &pinfmt);
		if (pinfmt.fmt == NULL){
			pinfmt.pin = 1;
			ms_filter_call_method(stream->source, MS_FILTER_GET_OUTPUT_FMT, &pinfmt);
		}
		
39
		if (stream->write_resampler){
40 41 42
			ms_message("Configuring resampler input with rate=[%i], nchannels=[%i]",pinfmt.fmt->rate, pinfmt.fmt->nchannels);
			ms_filter_call_method(stream->write_resampler,MS_FILTER_SET_NCHANNELS,(void*)&pinfmt.fmt->nchannels);
			ms_filter_call_method(stream->write_resampler,MS_FILTER_SET_SAMPLE_RATE,(void*)&pinfmt.fmt->rate);
43
		}
44 45
		ms_filter_call_method(stream->gendtmf,MS_FILTER_SET_SAMPLE_RATE, (void*)&pinfmt.fmt->rate);
		ms_filter_call_method(stream->gendtmf,MS_FILTER_SET_NCHANNELS, (void*)&pinfmt.fmt->nchannels);
46 47 48
	}
}

49 50 51 52 53 54 55
RingStream * ring_start(const char *file, int interval, MSSndCard *sndcard){
   return ring_start_with_cb(file,interval,sndcard,NULL,NULL);
}

RingStream * ring_start_with_cb(const char *file,int interval,MSSndCard *sndcard, MSFilterNotifyFunc func,void * user_data)
{
	RingStream *stream;
56
	int srcchannels=1, dstchannels=1;
57 58 59
	int srcrate,dstrate;
	MSConnectionHelper h;
	MSTickerParams params={0};
60
	MSPinFormat pinfmt={0};
61 62

	stream=(RingStream *)ms_new0(RingStream,1);
63 64 65 66 67 68
	if (file) {
		stream->source=_ms_create_av_player(file);
	} else {
		/*create dummy source*/
		stream->source=ms_filter_new(MS_FILE_PLAYER_ID);
	}
69
	ms_filter_add_notify_callback(stream->source,ring_player_event_handler,stream,TRUE);
70
	if (func!=NULL)
71
		ms_filter_add_notify_callback(stream->source,func,user_data,FALSE);
72 73
	stream->gendtmf=ms_filter_new(MS_DTMF_GEN_ID);
	stream->sndwrite=ms_snd_card_create_writer(sndcard);
74 75 76
	stream->write_resampler=ms_filter_new(MS_RESAMPLE_ID);
	
	if (file){
77 78 79
		ms_filter_call_method(stream->source,MS_PLAYER_OPEN,(void*)file);
		ms_filter_call_method(stream->source,MS_PLAYER_SET_LOOP,&interval);
		ms_filter_call_method_noarg(stream->source,MS_PLAYER_START);
80
	}
81
	
82 83 84 85 86 87 88 89 90 91 92 93 94
	/*configure sound output filter*/
	ms_filter_call_method(stream->source, MS_FILTER_GET_OUTPUT_FMT, &pinfmt);
	if (pinfmt.fmt == NULL){
		pinfmt.pin = 1;
		ms_filter_call_method(stream->source, MS_FILTER_GET_OUTPUT_FMT, &pinfmt);
		if (pinfmt.fmt == NULL){
			/*probably no file is being played, assume pcm*/
			pinfmt.fmt = ms_factory_get_audio_format(ms_factory_get_fallback(), "pcm", 8000, 1, NULL);
		}
	}
	srcrate = pinfmt.fmt->rate;
	srcchannels = pinfmt.fmt->nchannels;

95 96
	ms_filter_call_method(stream->sndwrite,MS_FILTER_SET_SAMPLE_RATE,&srcrate);
	ms_filter_call_method(stream->sndwrite,MS_FILTER_GET_SAMPLE_RATE,&dstrate);
Sylvain Berfini's avatar
Sylvain Berfini committed
97 98 99
	ms_filter_call_method(stream->sndwrite,MS_FILTER_SET_NCHANNELS,&srcchannels);
	ms_filter_call_method(stream->sndwrite,MS_FILTER_GET_NCHANNELS,&dstchannels);
	
100 101 102 103 104 105 106 107 108 109
	/*eventually create a decoder*/
	if (strcasecmp(pinfmt.fmt->encoding, "pcm") != 0){
		stream->decoder = ms_filter_create_decoder(pinfmt.fmt->encoding);
		if (!stream->decoder){
			ms_error("RingStream: could not create decoder for '%s'", pinfmt.fmt->encoding);
			ring_stop(stream);
			return NULL;
		}
	}
	
110
	/*configure output of resampler*/
111 112 113
	if (stream->write_resampler){
		ms_filter_call_method(stream->write_resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&dstrate);
		ms_filter_call_method(stream->write_resampler,MS_FILTER_SET_OUTPUT_NCHANNELS,&dstchannels);
114
	
115 116 117 118
		/*the input of the resampler, as well as dtmf generator are configured within the ring_player_event_handler()
		 * callback triggered during the open of the file player*/
		ms_message("configuring resampler output to rate=[%i], nchannels=[%i]",dstrate,dstchannels);
	}
119
	
120 121 122 123 124
	params.name="Ring MSTicker";
	params.prio=MS_TICKER_PRIO_HIGH;
	stream->ticker=ms_ticker_new_with_params(&params);

	ms_connection_helper_start(&h);
125 126 127 128 129 130
	ms_connection_helper_link(&h,stream->source, -1, pinfmt.pin);
	stream->srcpin = pinfmt.pin;
	if (stream->decoder){
		ms_filter_call_method(stream->decoder, MS_FILTER_SET_NCHANNELS, &srcchannels);
		ms_connection_helper_link(&h, stream->decoder, 0, 0);
	}
131 132 133
	ms_connection_helper_link(&h,stream->gendtmf,0,0);
	if (stream->write_resampler)
		ms_connection_helper_link(&h,stream->write_resampler,0,0);
134
	ms_connection_helper_link(&h, stream->sndwrite, 0, -1);
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
	ms_ticker_attach(stream->ticker,stream->source);

	return stream;
}

void ring_play_dtmf(RingStream *stream, char dtmf, int duration_ms){
	if (duration_ms>0)
		ms_filter_call_method(stream->gendtmf, MS_DTMF_GEN_PLAY, &dtmf);
	else ms_filter_call_method(stream->gendtmf, MS_DTMF_GEN_START, &dtmf);
}

void ring_stop_dtmf(RingStream *stream){
	ms_filter_call_method_noarg(stream->gendtmf, MS_DTMF_GEN_STOP);
}

void ring_stop(RingStream *stream){
	MSConnectionHelper h;
152 153 154
	
	if (stream->ticker){
		ms_ticker_detach(stream->ticker,stream->source);
155

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
		ms_connection_helper_start(&h);
		ms_connection_helper_unlink(&h,stream->source,-1, stream->srcpin);
		if (stream->decoder){
			ms_connection_helper_unlink(&h,stream->decoder, 0, 0);
		}
		ms_connection_helper_unlink(&h,stream->gendtmf,0,0);
		if (stream->write_resampler)
			ms_connection_helper_unlink(&h,stream->write_resampler,0,0);
		ms_connection_helper_unlink(&h,stream->sndwrite,0,-1);
		ms_ticker_destroy(stream->ticker);
	}
	if (stream->source) ms_filter_destroy(stream->source);
	if (stream->gendtmf) ms_filter_destroy(stream->gendtmf);
	if (stream->sndwrite) ms_filter_destroy(stream->sndwrite);
	if (stream->decoder) ms_filter_destroy(stream->decoder);
171 172
	if (stream->write_resampler)
		ms_filter_destroy(stream->write_resampler);
173 174
	ms_free(stream);
}