audio: fix compilation when libnice has needed patches
[siplcs.git] / src / purple / purple-media.c
bloba840210ab06a11ab4884fb6fe0cb53f6db24ab34
1 /**
2 * @file purple-media.c
4 * pidgin-sipe
6 * Copyright (C) 2010 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include "glib.h"
29 #include "sipe-common.h"
31 #include "mediamanager.h"
32 #include "request.h"
33 #include "agent.h"
35 #include "sipe-backend.h"
36 #include "sipe-core.h"
37 #include "sipe-media.h"
39 #include "purple-private.h"
41 typedef struct _sipe_purple_media {
42 PurpleMedia *m;
43 // Prevent infinite recursion in on_stream_info_cb
44 gboolean in_recursion;
45 } sipe_purple_media;
47 static PurpleMediaSessionType sipe_media_to_purple(SipeMediaType type);
48 static PurpleMediaCandidateType sipe_candidate_type_to_purple(SipeCandidateType type);
49 static PurpleMediaNetworkProtocol sipe_network_protocol_to_purple(SipeNetworkProtocol proto);
50 static SipeNetworkProtocol purple_network_protocol_to_sipe(PurpleMediaNetworkProtocol proto);
52 static void
53 on_candidates_prepared_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,
54 SIPE_UNUSED_PARAMETER gchar *sessionid,
55 SIPE_UNUSED_PARAMETER gchar *participant,
56 sipe_media_call *call)
58 if (call->candidates_prepared_cb)
59 call->candidates_prepared_cb(call);
62 static void
63 on_state_changed_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,
64 PurpleMediaState state,
65 gchar *sessionid,
66 gchar *participant,
67 sipe_media_call *call)
69 printf("sipe_media_state_changed_cb: %d %s %s\n", state, sessionid, participant);
70 if (state == PURPLE_MEDIA_STATE_CONNECTED && call->media_connected_cb)
71 call->media_connected_cb(call);
74 static void
75 on_stream_info_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,
76 PurpleMediaInfoType type,
77 SIPE_UNUSED_PARAMETER gchar *sessionid,
78 SIPE_UNUSED_PARAMETER gchar *participant,
79 gboolean local, sipe_media_call *call)
81 sipe_purple_media *m = call->media;
82 if (m->in_recursion) {
83 m->in_recursion = FALSE;
84 return;
87 if (type == PURPLE_MEDIA_INFO_ACCEPT && call->call_accept_cb)
88 call->call_accept_cb(call, local);
89 else if (type == PURPLE_MEDIA_INFO_REJECT && call->call_reject_cb)
90 call->call_reject_cb(call, local);
91 else if (type == PURPLE_MEDIA_INFO_HOLD && call->call_hold_cb) {
92 call->call_hold_cb(call, local, TRUE);
93 if (!local) {
94 m->in_recursion = TRUE;
95 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_HOLD, NULL, NULL, TRUE);
97 } else if (type == PURPLE_MEDIA_INFO_UNHOLD && call->call_hold_cb) {
98 call->call_hold_cb(call, local, FALSE);
99 m->in_recursion = TRUE;
100 if (!call->local_on_hold && !call->remote_on_hold) {
101 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_UNHOLD, NULL, NULL, TRUE);
102 } else {
103 /* Remote side is still on hold, keep local also held to prevent sending
104 * unnecessary media over network */
105 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_HOLD, NULL, NULL, TRUE);
107 } else if (type == PURPLE_MEDIA_INFO_HANGUP && call->call_hangup_cb)
108 call->call_hangup_cb(call, local);
111 struct sipe_media *
112 sipe_backend_media_new(struct sipe_core_public *sipe_public,
113 struct sipe_media_call *call,
114 const gchar *participant,
115 gboolean initiator)
117 sipe_purple_media *m = g_new0(sipe_purple_media, 1);
118 struct sipe_backend_private *purple_private = sipe_public->backend_private;
119 PurpleMediaManager *manager = purple_media_manager_get();
121 m->m = purple_media_manager_create_media(manager,
122 purple_private->account,
123 "fsrtpconference",
124 participant, initiator);
126 g_signal_connect(G_OBJECT(m->m), "candidates-prepared",
127 G_CALLBACK(on_candidates_prepared_cb), call);
128 g_signal_connect(G_OBJECT(m->m), "stream-info",
129 G_CALLBACK(on_stream_info_cb), call);
130 g_signal_connect(G_OBJECT(m->m), "state-changed",
131 G_CALLBACK(on_state_changed_cb), call);
133 return (struct sipe_media *)m;
136 void
137 sipe_backend_media_free(sipe_media *media)
139 sipe_purple_media *m = (sipe_purple_media *)media;
140 purple_media_manager_remove_media(purple_media_manager_get(), m->m);
141 g_free(m);
144 gboolean
145 sipe_backend_media_add_stream(sipe_media *media, const gchar* participant,
146 SipeMediaType type, gboolean use_nice,
147 gboolean initiator)
149 sipe_purple_media *m = (sipe_purple_media *)media;
150 PurpleMediaSessionType prpl_type = sipe_media_to_purple(type);
151 GParameter *params = NULL;
152 guint params_cnt = 0;
153 gchar *transmitter;
155 if (use_nice) {
156 transmitter = "nice";
157 params_cnt = 2;
159 params = g_new0(GParameter, params_cnt);
160 params[0].name = "controlling-mode";
161 g_value_init(&params[0].value, G_TYPE_BOOLEAN);
162 g_value_set_boolean(&params[0].value, initiator);
163 params[1].name = "compatibility-mode";
164 g_value_init(&params[1].value, G_TYPE_UINT);
166 * !!!TEMPORARY HACK!!!
168 * This enables successful compilation with libnice < 0.0.12
170 * This DOES NOT mean that the resulting code will work!!!
172 #ifdef NICE_HAS_COMPATIBILITY
173 g_value_set_uint(&params[1].value, NICE_COMPATIBILITY_OC2007R2);
174 #endif
175 } else {
176 transmitter = "rawudp";
179 return purple_media_add_stream(m->m, "sipe-voice", participant, prpl_type,
180 initiator, transmitter, params_cnt, params);
183 void
184 sipe_backend_media_add_remote_candidates(sipe_media *media, gchar* participant, GList *candidates)
186 sipe_purple_media *m = (sipe_purple_media *)media;
187 purple_media_add_remote_candidates(m->m, "sipe-voice", participant, candidates);
190 gboolean sipe_backend_media_is_initiator(sipe_media *media, gchar *participant)
192 sipe_purple_media *m = (sipe_purple_media *)media;
193 return purple_media_is_initiator(m->m, "sipe-voice", participant);
196 sipe_codec *
197 sipe_backend_codec_new(int id, const char *name, SipeMediaType type, guint clock_rate)
199 return (sipe_codec *)purple_media_codec_new(id, name,
200 sipe_media_to_purple(type), clock_rate);
203 void
204 sipe_backend_codec_free(sipe_codec *codec)
206 if (codec)
207 g_object_unref(codec);
211 sipe_backend_codec_get_id(sipe_codec *codec)
213 return purple_media_codec_get_id((PurpleMediaCodec *)codec);
216 gchar *
217 sipe_backend_codec_get_name(sipe_codec *codec)
219 return purple_media_codec_get_encoding_name((PurpleMediaCodec *)codec);
222 guint
223 sipe_backend_codec_get_clock_rate(sipe_codec *codec)
225 return purple_media_codec_get_clock_rate((PurpleMediaCodec *)codec);
228 void
229 sipe_backend_codec_add_optional_parameter(sipe_codec *codec,
230 const gchar *name, const gchar *value)
232 purple_media_codec_add_optional_parameter((PurpleMediaCodec *)codec, name, value);
235 GList *
236 sipe_backend_codec_get_optional_parameters(sipe_codec *codec)
238 return purple_media_codec_get_optional_parameters((PurpleMediaCodec *)codec);
241 gboolean
242 sipe_backend_set_remote_codecs(sipe_media_call* call, gchar* participant)
244 sipe_purple_media *m = (sipe_purple_media *)call->media;
245 GList *codecs = call->remote_codecs;
247 return purple_media_set_remote_codecs(m->m, "sipe-voice", participant, codecs);
250 GList*
251 sipe_backend_get_local_codecs(sipe_media_call* call)
253 sipe_purple_media *m = (sipe_purple_media *)call->media;
254 return purple_media_get_codecs(m->m, "sipe-voice");
257 sipe_candidate *
258 sipe_backend_candidate_new(const gchar *foundation, SipeComponentType component,
259 SipeCandidateType type, SipeNetworkProtocol proto,
260 const gchar *ip, guint port)
262 return (sipe_candidate *)purple_media_candidate_new(
263 foundation,
264 component,
265 sipe_candidate_type_to_purple(type),
266 sipe_network_protocol_to_purple(proto),
268 port);
271 void
272 sipe_backend_candidate_free(sipe_candidate *candidate)
274 if (candidate)
275 g_object_unref(candidate);
278 gchar *
279 sipe_backend_candidate_get_username(sipe_candidate *candidate)
281 return purple_media_candidate_get_username((PurpleMediaCandidate*)candidate);
284 gchar *
285 sipe_backend_candidate_get_password(sipe_candidate *candidate)
287 return purple_media_candidate_get_password((PurpleMediaCandidate*)candidate);
290 gchar *
291 sipe_backend_candidate_get_foundation(sipe_candidate *candidate)
293 return purple_media_candidate_get_foundation((PurpleMediaCandidate*)candidate);
296 gchar *
297 sipe_backend_candidate_get_ip(sipe_candidate *candidate)
299 return purple_media_candidate_get_ip((PurpleMediaCandidate*)candidate);
302 guint
303 sipe_backend_candidate_get_port(sipe_candidate *candidate)
305 return purple_media_candidate_get_port((PurpleMediaCandidate*)candidate);
308 guint32
309 sipe_backend_candidate_get_priority(sipe_candidate *candidate)
311 return purple_media_candidate_get_priority((PurpleMediaCandidate*)candidate);
314 void
315 sipe_backend_candidate_set_priority(sipe_candidate *candidate, guint32 priority)
317 g_object_set(candidate, "priority", priority, NULL);
320 SipeComponentType
321 sipe_backend_candidate_get_component_type(sipe_candidate *candidate)
323 return purple_media_candidate_get_component_id((PurpleMediaCandidate*)candidate);
326 SipeCandidateType
327 sipe_backend_candidate_get_type(sipe_candidate *candidate)
329 return purple_media_candidate_get_candidate_type((PurpleMediaCandidate*)candidate);
332 SipeNetworkProtocol
333 sipe_backend_candidate_get_protocol(sipe_candidate *candidate)
335 PurpleMediaNetworkProtocol proto =
336 purple_media_candidate_get_protocol((PurpleMediaCandidate*)candidate);
337 return purple_network_protocol_to_sipe(proto);
340 void
341 sipe_backend_candidate_set_username_and_pwd(sipe_candidate *candidate,
342 const gchar *username,
343 const gchar *password)
345 g_object_set(candidate, "username", username, "password", password, NULL);
348 GList*
349 sipe_backend_get_local_candidates(sipe_media_call* call, gchar* participant)
351 sipe_purple_media *m = (sipe_purple_media *)call->media;
352 return purple_media_get_local_candidates(m->m, "sipe-voice", participant);
355 void
356 sipe_backend_media_hold(sipe_media* media, gboolean local)
358 sipe_purple_media *m = (sipe_purple_media *)media;
359 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_HOLD, NULL, NULL, local);
362 void
363 sipe_backend_media_unhold(sipe_media* media, gboolean local)
365 sipe_purple_media *m = (sipe_purple_media *)media;
366 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_UNHOLD, NULL, NULL, local);
369 void
370 sipe_backend_media_hangup(sipe_media* media, gboolean local)
372 sipe_purple_media *m = (sipe_purple_media *)media;
373 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_HANGUP, NULL, NULL, local);
376 void
377 sipe_backend_media_reject(sipe_media* media, gboolean local)
379 sipe_purple_media *m = (sipe_purple_media *)media;
380 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_REJECT, NULL, NULL, local);
383 PurpleMediaSessionType sipe_media_to_purple(SipeMediaType type)
385 switch (type) {
386 case SIPE_MEDIA_AUDIO: return PURPLE_MEDIA_AUDIO;
387 case SIPE_MEDIA_VIDEO: return PURPLE_MEDIA_VIDEO;
388 default: return PURPLE_MEDIA_NONE;
392 /*SipeMediaType purple_media_to_sipe(PurpleMediaSessionType type)
394 switch (type) {
395 case PURPLE_MEDIA_AUDIO: return SIPE_MEDIA_AUDIO;
396 case PURPLE_MEDIA_VIDEO: return SIPE_MEDIA_VIDEO;
397 default: return SIPE_MEDIA_AUDIO;
401 static PurpleMediaCandidateType
402 sipe_candidate_type_to_purple(SipeCandidateType type)
404 switch (type) {
405 case SIPE_CANDIDATE_TYPE_HOST: return PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
406 case SIPE_CANDIDATE_TYPE_RELAY: return PURPLE_MEDIA_CANDIDATE_TYPE_RELAY;
407 case SIPE_CANDIDATE_TYPE_SRFLX: return PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX;
408 default: return PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
412 static PurpleMediaNetworkProtocol
413 sipe_network_protocol_to_purple(SipeNetworkProtocol proto)
415 switch (proto) {
416 case SIPE_NETWORK_PROTOCOL_TCP: return PURPLE_MEDIA_NETWORK_PROTOCOL_TCP;
417 case SIPE_NETWORK_PROTOCOL_UDP: return PURPLE_MEDIA_NETWORK_PROTOCOL_UDP;
418 default: return PURPLE_MEDIA_NETWORK_PROTOCOL_TCP;
422 static SipeNetworkProtocol
423 purple_network_protocol_to_sipe(PurpleMediaNetworkProtocol proto)
425 switch (proto) {
426 case PURPLE_MEDIA_NETWORK_PROTOCOL_TCP: return SIPE_NETWORK_PROTOCOL_TCP;
427 case PURPLE_MEDIA_NETWORK_PROTOCOL_UDP: return SIPE_NETWORK_PROTOCOL_UDP;
428 default: return SIPE_NETWORK_PROTOCOL_UDP;
433 void sipe_media_error_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media, gchar* error, SIPE_UNUSED_PARAMETER struct sipe_account_data *sip)
435 printf("sipe_media_error_cb: %s\n", error);
438 void sipe_media_codecs_changed_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media, gchar* codec, SIPE_UNUSED_PARAMETER struct sipe_account_data *sip)
440 printf("sipe_media_codecs_changed_cb: %s\n", codec);
443 void sipe_media_level_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media, gchar* sessionid, gchar* participant, gdouble percent, SIPE_UNUSED_PARAMETER struct sipe_account_data *sip)
445 printf("sipe_media_level_cb: %s %s %f\n", sessionid, participant, percent);
448 void sipe_media_new_candidate_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media, gchar* sessionid, gchar* cname, PurpleMediaCandidate *candidate, SIPE_UNUSED_PARAMETER struct sipe_account_data *sip)
450 printf("sipe_media_new_candidate_cb: %s cname: %s %s %d\n", sessionid, cname,
451 purple_media_candidate_get_ip(candidate),
452 purple_media_candidate_get_port(candidate));
455 void sipe_media_state_changed_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media, PurpleMediaState state, gchar* sessionid, gchar* participant, SIPE_UNUSED_PARAMETER struct sipe_account_data *sip)
457 printf("sipe_media_state_changed_cb: %d %s %s\n", state, sessionid, participant);
460 g_signal_connect(G_OBJECT(media), "error", G_CALLBACK(sipe_media_error_cb), call);
461 g_signal_connect(G_OBJECT(media), "codecs-changed", G_CALLBACK(sipe_media_codecs_changed_cb), call);
462 g_signal_connect(G_OBJECT(media), "level", G_CALLBACK(sipe_media_level_cb), call);
463 g_signal_connect(G_OBJECT(media), "new-candidate", G_CALLBACK(sipe_media_new_candidate_cb), call);
464 g_signal_connect(G_OBJECT(media), "state-changed", G_CALLBACK(sipe_media_state_changed_cb), call);
469 Local Variables:
470 mode: c
471 c-file-style: "bsd"
472 indent-tabs-mode: t
473 tab-width: 8
474 End: