]> sjero.net Git - linphone/blob - coreapi/conference.c
Merge branch 'local_videoios' into dev_videoios
[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
28 #include "mediastreamer2/msvolume.h"
29
30 static void conference_check_init(LinphoneConference *ctx){
31         if (ctx->conf==NULL){
32                 MSAudioConferenceParams params;
33                 params.samplerate=16000;
34                 ctx->conf=ms_audio_conference_new(&params);
35         }
36 }
37
38 static void remove_local_endpoint(LinphoneConference *ctx){
39         if (ctx->local_endpoint){
40                 ms_audio_conference_remove_member(ctx->conf,ctx->local_endpoint);
41                 ms_audio_endpoint_release_from_stream(ctx->local_endpoint);
42                 ctx->local_endpoint=NULL;
43                 audio_stream_stop(ctx->local_participant);
44                 ctx->local_participant=NULL;
45         }
46 }
47
48 void linphone_core_conference_check_uninit(LinphoneConference *ctx){
49         if (ctx->conf){
50                 ms_message("conference_check_uninit(): nmembers=%i",ctx->conf->nmembers);
51                 if (ctx->conf->nmembers==1 && ctx->local_participant!=NULL){
52                         remove_local_endpoint(ctx);
53                 }
54                 if (ctx->conf->nmembers==0){
55                         ms_audio_conference_destroy(ctx->conf);
56                         ctx->conf=NULL;
57                 }
58         }
59 }
60
61
62 void linphone_call_add_to_conf(LinphoneCall *call){
63         LinphoneCore *lc=call->core;
64         LinphoneConference *conf=&lc->conf_ctx;
65         MSAudioEndpoint *ep;
66         call->params.has_video = FALSE;
67         call->camera_active = FALSE;
68         ep=ms_audio_endpoint_get_from_stream(call->audiostream,TRUE);
69         ms_audio_conference_add_member(conf->conf,ep);
70         call->endpoint=ep;
71 }
72
73 void linphone_call_remove_from_conf(LinphoneCall *call){
74         LinphoneCore *lc=call->core;
75         LinphoneConference *conf=&lc->conf_ctx;
76         
77         ms_audio_conference_remove_member(conf->conf,call->endpoint);
78         ms_audio_endpoint_release_from_stream(call->endpoint);
79         call->endpoint=NULL;
80 }
81
82 static RtpProfile *make_dummy_profile(int samplerate){
83         RtpProfile *prof=rtp_profile_new("dummy");
84         PayloadType *pt=payload_type_clone(&payload_type_l16_mono);
85         pt->clock_rate=samplerate;
86         rtp_profile_set_payload(prof,0,pt);
87         return prof;
88 }
89
90 static void add_local_endpoint(LinphoneConference *conf,LinphoneCore *lc){
91         /*create a dummy audiostream in order to extract the local part of it */
92         /* network address and ports have no meaning and are not used here. */
93         AudioStream *st=audio_stream_new(65000,FALSE);
94         MSSndCard *playcard=lc->sound_conf.lsd_card ? 
95                         lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
96         MSSndCard *captcard=lc->sound_conf.capt_sndcard;
97         const MSAudioConferenceParams *params=ms_audio_conference_get_params(conf->conf);
98         RtpProfile *prof=make_dummy_profile(params->samplerate);
99         
100         audio_stream_start_full(st, prof,
101                                 "127.0.0.1",
102                                 65000,
103                                 65001,
104                                 0,
105                                 40,
106                                 NULL,
107                                 NULL,
108                                 playcard,
109                                 captcard,
110                                 linphone_core_echo_cancellation_enabled(lc)
111                                 );
112         _post_configure_audio_stream(st,lc,FALSE);
113         conf->local_participant=st;
114         conf->local_endpoint=ms_audio_endpoint_get_from_stream(st,FALSE);
115         ms_audio_conference_add_member(conf->conf,conf->local_endpoint);
116         /*normally and exceptionnaly, the profile is no more accessed past this point*/
117         rtp_profile_destroy(prof);
118 }
119
120 float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
121         LinphoneConference *conf=&lc->conf_ctx;
122         AudioStream *st=conf->local_participant;
123         if (st && st->volsend && !conf->local_muted){
124                 float vol=0;
125                 ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol);
126                 return vol;
127                 
128         }
129         return LINPHONE_VOLUME_DB_LOWEST;
130 }
131
132 int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
133         LinphoneCallParams params;
134         LinphoneConference *conf=&lc->conf_ctx;
135         
136         if (call->current_params.in_conference){
137                 ms_error("Already in conference");
138                 return -1;
139         }
140         conference_check_init(&lc->conf_ctx);
141         call->params.in_conference=TRUE;
142         call->params.has_video=FALSE;
143         params=call->params;
144         if (call->state==LinphoneCallPaused)
145                 linphone_core_resume_call(lc,call);
146         else if (call->state==LinphoneCallStreamsRunning){
147                 /*this will trigger a reINVITE that will later redraw the streams */
148                 if (call->audiostream || call->videostream){
149                         linphone_call_stop_media_streams (call); /*free the audio & video local resources*/
150                 }
151                 if (call==lc->current_call){
152                         lc->current_call=NULL;
153                 }
154                 linphone_core_update_call(lc,call,&params);
155                 add_local_endpoint(conf,lc);
156         }else{
157                 ms_error("Call is in state %s, it cannot be added to the conference.",linphone_call_state_to_string(call->state));
158                 return -1;
159         }
160         return 0;
161 }
162
163 int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){
164         int err=0;
165         if (!call->current_params.in_conference){
166                 if (call->params.in_conference){
167                         ms_warning("Not (yet) in conference, be patient");
168                         return -1;
169                 }else{
170                         ms_error("Not in a conference.");
171                         return -1;
172                 }
173         }
174         call->params.in_conference=FALSE;
175         err=linphone_core_pause_call(lc,call);
176         return err;
177 }
178
179 bool_t linphone_core_is_in_conference(const LinphoneCore *lc){
180         return lc->conf_ctx.local_participant!=NULL;
181 }
182
183 int linphone_core_leave_conference(LinphoneCore *lc){
184         LinphoneConference *conf=&lc->conf_ctx;
185         if (linphone_core_is_in_conference(lc))
186                 remove_local_endpoint(conf);
187         return 0;
188 }
189
190
191 int linphone_core_enter_conference(LinphoneCore *lc){
192         LinphoneConference *conf=&lc->conf_ctx;
193         if (conf->local_participant==NULL) add_local_endpoint(conf,lc);
194         return 0;
195 }
196
197 int linphone_core_add_all_to_conference(LinphoneCore *lc) {
198         MSList *calls=lc->calls;
199         while (calls) {
200                 LinphoneCall *call=(LinphoneCall*)calls->data;
201                 calls=calls->next;
202                 if (!call->current_params.in_conference) {
203                         linphone_core_add_to_conference(lc, call);
204                 }
205         }
206         return 0;
207 }
208
209 int linphone_core_terminate_conference(LinphoneCore *lc) {
210         MSList *calls=lc->calls;
211         while (calls) {
212                 LinphoneCall *call=(LinphoneCall*)calls->data;
213                 calls=calls->next;
214                 if (call->current_params.in_conference) {
215                         linphone_core_terminate_call(lc, call);
216                 }
217         }
218         return 0;
219 }
220
221 int linphone_core_get_conference_size(LinphoneCore *lc) {
222         return ms_audio_conference_size(lc->conf_ctx.conf);
223 }