]> sjero.net Git - linphone/blob - coreapi/conference.c
update ms2 for conference fixes
[linphone] / coreapi / conference.c
1 /***************************************************************************
2  *            conference.c
3  *
4  *  Mon Sep 12, 2011
5  *  Copyright  2011  Belledonne Communications
6  *  Author: Simon Morlat
7  *  Email simon dot morlat at linphone dot org
8  ****************************************************************************/
9
10 /*
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25  
26 #include "private.h"
27 #include "lpconfig.h"
28
29 #include "mediastreamer2/msvolume.h"
30
31 static void conference_check_init(LinphoneConference *ctx, int samplerate){
32         if (ctx->conf==NULL){
33                 MSAudioConferenceParams params;
34                 params.samplerate=samplerate;
35                 ctx->conf=ms_audio_conference_new(&params);
36         }
37 }
38
39 static void remove_local_endpoint(LinphoneConference *ctx){
40         if (ctx->local_endpoint){
41                 ms_audio_conference_remove_member(ctx->conf,ctx->local_endpoint);
42                 ms_audio_endpoint_release_from_stream(ctx->local_endpoint);
43                 ctx->local_endpoint=NULL;
44                 audio_stream_stop(ctx->local_participant);
45                 ctx->local_participant=NULL;
46                 rtp_profile_destroy(ctx->local_dummy_profile);
47         }
48 }
49
50 void linphone_core_conference_check_uninit(LinphoneConference *ctx){
51         if (ctx->conf){
52                 ms_message("conference_check_uninit(): nmembers=%i",ctx->conf->nmembers);
53                 if (ctx->conf->nmembers==1 && ctx->local_participant!=NULL){
54                         remove_local_endpoint(ctx);
55                 }
56                 if (ctx->conf->nmembers==0){
57                         ms_audio_conference_destroy(ctx->conf);
58                         ctx->conf=NULL;
59                 }
60         }
61 }
62
63 void linphone_call_add_to_conf(LinphoneCall *call, bool_t muted){
64         LinphoneCore *lc=call->core;
65         LinphoneConference *conf=&lc->conf_ctx;
66         MSAudioEndpoint *ep;
67         call->params.has_video = FALSE;
68         call->camera_active = FALSE;
69         ep=ms_audio_endpoint_get_from_stream(call->audiostream,TRUE);
70         ms_audio_conference_add_member(conf->conf,ep);
71         ms_audio_conference_mute_member(conf->conf,ep,muted);
72         call->endpoint=ep;
73 }
74
75 void linphone_call_remove_from_conf(LinphoneCall *call){
76         LinphoneCore *lc=call->core;
77         LinphoneConference *conf=&lc->conf_ctx;
78         
79         ms_audio_conference_remove_member(conf->conf,call->endpoint);
80         ms_audio_endpoint_release_from_stream(call->endpoint);
81         call->endpoint=NULL;
82 }
83
84 static RtpProfile *make_dummy_profile(int samplerate){
85         RtpProfile *prof=rtp_profile_new("dummy");
86         PayloadType *pt=payload_type_clone(&payload_type_l16_mono);
87         pt->clock_rate=samplerate;
88         rtp_profile_set_payload(prof,0,pt);
89         return prof;
90 }
91
92 static void add_local_endpoint(LinphoneConference *conf,LinphoneCore *lc){
93         /*create a dummy audiostream in order to extract the local part of it */
94         /* network address and ports have no meaning and are not used here. */
95         AudioStream *st=audio_stream_new(65000,FALSE);
96         MSSndCard *playcard=lc->sound_conf.lsd_card ? 
97                         lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
98         MSSndCard *captcard=lc->sound_conf.capt_sndcard;
99         const MSAudioConferenceParams *params=ms_audio_conference_get_params(conf->conf);
100         conf->local_dummy_profile=make_dummy_profile(params->samplerate);
101         
102         audio_stream_start_full(st, conf->local_dummy_profile,
103                                 "127.0.0.1",
104                                 65000,
105                                 65001,
106                                 0,
107                                 40,
108                                 NULL,
109                                 NULL,
110                                 playcard,
111                                 captcard,
112                                 linphone_core_echo_cancellation_enabled(lc)
113                                 );
114         _post_configure_audio_stream(st,lc,FALSE);
115         conf->local_participant=st;
116         conf->local_endpoint=ms_audio_endpoint_get_from_stream(st,FALSE);
117         ms_audio_conference_add_member(conf->conf,conf->local_endpoint);
118         
119 }
120
121 float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
122         LinphoneConference *conf=&lc->conf_ctx;
123         AudioStream *st=conf->local_participant;
124         if (st && st->volsend && !conf->local_muted){
125                 float vol=0;
126                 ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol);
127                 return vol;
128                 
129         }
130         return LINPHONE_VOLUME_DB_LOWEST;
131 }
132
133 int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
134         LinphoneCallParams params;
135         LinphoneConference *conf=&lc->conf_ctx;
136         
137         if (call->current_params.in_conference){
138                 ms_error("Already in conference");
139                 return -1;
140         }
141         conference_check_init(&lc->conf_ctx, lp_config_get_int(lc->config, "sound","conference_rate",16000));
142         call->params.in_conference=TRUE;
143         call->params.has_video=FALSE;
144         call->params.media_encryption=LinphoneMediaEncryptionNone;
145         params=call->params;
146         if (call->state==LinphoneCallPaused)
147                 linphone_core_resume_call(lc,call);
148         else if (call->state==LinphoneCallStreamsRunning){
149                 /*this will trigger a reINVITE that will later redraw the streams */
150                 if (call->audiostream || call->videostream){
151                         linphone_call_stop_media_streams (call); /*free the audio & video local resources*/
152                 }
153                 if (call==lc->current_call){
154                         lc->current_call=NULL;
155                 }
156                 linphone_core_update_call(lc,call,&params);
157                 add_local_endpoint(conf,lc);
158         }else{
159                 ms_error("Call is in state %s, it cannot be added to the conference.",linphone_call_state_to_string(call->state));
160                 return -1;
161         }
162         return 0;
163 }
164
165 int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){
166         int err=0;
167
168         if (!call->current_params.in_conference){
169                 if (call->params.in_conference){
170                         ms_warning("Not (yet) in conference, be patient");
171                         return -1;
172                 }else{
173                         ms_error("Not in a conference.");
174                         return -1;
175                 }
176         }
177         call->params.in_conference=FALSE;
178         err=linphone_core_pause_call(lc,call);
179         return err;
180 }
181
182 bool_t linphone_core_is_in_conference(const LinphoneCore *lc){
183         return lc->conf_ctx.local_participant!=NULL;
184 }
185
186 int linphone_core_leave_conference(LinphoneCore *lc){
187         LinphoneConference *conf=&lc->conf_ctx;
188         if (linphone_core_is_in_conference(lc))
189                 remove_local_endpoint(conf);
190         return 0;
191 }
192
193
194 int linphone_core_enter_conference(LinphoneCore *lc){
195         if (linphone_core_sound_resources_locked(lc)) {
196                 return -1;
197         }
198         if (lc->current_call != NULL) {
199                 linphone_core_pause_call(lc, lc->current_call);
200         }
201         LinphoneConference *conf=&lc->conf_ctx;
202         if (conf->local_participant==NULL) add_local_endpoint(conf,lc);
203         return 0;
204 }
205
206 int linphone_core_add_all_to_conference(LinphoneCore *lc) {
207         MSList *calls=lc->calls;
208         while (calls) {
209                 LinphoneCall *call=(LinphoneCall*)calls->data;
210                 calls=calls->next;
211                 if (!call->current_params.in_conference) {
212                         linphone_core_add_to_conference(lc, call);
213                 }
214         }
215         return 0;
216 }
217
218 int linphone_core_terminate_conference(LinphoneCore *lc) {
219         MSList *calls=lc->calls;
220         while (calls) {
221                 LinphoneCall *call=(LinphoneCall*)calls->data;
222                 calls=calls->next;
223                 if (call->current_params.in_conference) {
224                         linphone_core_terminate_call(lc, call);
225                 }
226         }
227         return 0;
228 }
229
230 int linphone_core_get_conference_size(LinphoneCore *lc) {
231         return ms_audio_conference_size(lc->conf_ctx.conf);
232 }