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