audio: fixes after git rebase
[siplcs.git] / src / purple / purple-media.c
blob9387d6ba36bc42b7d80d149d7eb04b00acd32e15
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 #include "glib.h"
25 #include "sipe-core.h"
27 //TODO: these two includes should be eliminated
28 #include "../core/sipe.h"
29 #include "../core/sipe-core-private.h"
31 #include "sipe-common.h"
32 #include "sipe-media.h"
33 #include "mediamanager.h"
34 #include <nice/agent.h>
36 #include "request.h"
37 #include "core-depurple.h"
39 typedef struct _sipe_purple_media {
40 PurpleMedia *m;
41 // Prevent infinite recursion in on_stream_info_cb
42 gboolean in_recursion;
43 } sipe_purple_media;
45 gboolean sipe_initiate_media(PurpleAccount *account, const char *who,
46 SIPE_UNUSED_PARAMETER PurpleMediaSessionType type)
48 struct sipe_core_private *sipe_private = PURPLE_ACCOUNT_TO_SIPE_CORE_PRIVATE;
49 sipe_media_initiate_call(sipe_private, who);
50 return TRUE;
53 PurpleMediaCaps sipe_get_media_caps(SIPE_UNUSED_PARAMETER PurpleAccount *account,
54 SIPE_UNUSED_PARAMETER const char *who)
56 return PURPLE_MEDIA_CAPS_AUDIO;
59 static PurpleMediaSessionType sipe_media_to_purple(SipeMediaType type);
60 static PurpleMediaCandidateType sipe_candidate_type_to_purple(SipeCandidateType type);
61 static PurpleMediaNetworkProtocol sipe_network_protocol_to_purple(SipeNetworkProtocol proto);
62 static SipeNetworkProtocol purple_network_protocol_to_sipe(PurpleMediaNetworkProtocol proto);
64 static void
65 on_candidates_prepared_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,
66 SIPE_UNUSED_PARAMETER gchar *sessionid,
67 SIPE_UNUSED_PARAMETER gchar *participant,
68 sipe_media_call *call)
70 if (call->candidates_prepared_cb)
71 call->candidates_prepared_cb(call);
74 static void
75 on_state_changed_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,
76 PurpleMediaState state,
77 gchar *sessionid,
78 gchar *participant,
79 sipe_media_call *call)
81 printf("sipe_media_state_changed_cb: %d %s %s\n", state, sessionid, participant);
82 if (state == PURPLE_MEDIA_STATE_CONNECTED && call->media_connected_cb)
83 call->media_connected_cb(call);
86 static void
87 on_stream_info_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media,
88 PurpleMediaInfoType type,
89 SIPE_UNUSED_PARAMETER gchar *sessionid,
90 SIPE_UNUSED_PARAMETER gchar *participant,
91 gboolean local, sipe_media_call *call)
93 sipe_purple_media *m = call->media;
94 if (m->in_recursion) {
95 m->in_recursion = FALSE;
96 return;
99 if (type == PURPLE_MEDIA_INFO_ACCEPT && call->call_accept_cb)
100 call->call_accept_cb(call, local);
101 else if (type == PURPLE_MEDIA_INFO_REJECT && call->call_reject_cb)
102 call->call_reject_cb(call, local);
103 else if (type == PURPLE_MEDIA_INFO_HOLD && call->call_hold_cb) {
104 call->call_hold_cb(call, local, TRUE);
105 if (!local) {
106 m->in_recursion = TRUE;
107 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_HOLD, NULL, NULL, TRUE);
109 } else if (type == PURPLE_MEDIA_INFO_UNHOLD && call->call_hold_cb) {
110 call->call_hold_cb(call, local, FALSE);
111 m->in_recursion = TRUE;
112 if (!call->local_on_hold && !call->remote_on_hold) {
113 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_UNHOLD, NULL, NULL, TRUE);
114 } else {
115 /* Remote side is still on hold, keep local also held to prevent sending
116 * unnecessary media over network */
117 purple_media_stream_info(m->m, PURPLE_MEDIA_INFO_HOLD, NULL, NULL, TRUE);
119 } else if (type == PURPLE_MEDIA_INFO_HANGUP && call->call_hangup_cb)
120 call->call_hangup_cb(call, local);
123 sipe_media *
124 sipe_backend_media_new(sipe_media_call *call, const gchar* participant, gboolean initiator)
126 sipe_purple_media *m = g_new0(sipe_purple_media, 1);
127 struct sipe_core_private *sipe_private = call->sipe_private;
128 struct sipe_account_data *sip = SIPE_ACCOUNT_DATA_PRIVATE;
129 PurpleAccount *acc = sip->account;
130 PurpleMediaManager *manager = purple_media_manager_get();
132 m->m = purple_media_manager_create_media(manager, acc, "fsrtpconference",
133 participant, initiator);
135 g_signal_connect(G_OBJECT(m->m), "candidates-prepared",
136 G_CALLBACK(on_candidates_prepared_cb), call);
137 g_signal_connect(G_OBJECT(m->m), "stream-info",
138 G_CALLBACK(on_stream_info_cb), call);
139 g_signal_connect(G_OBJECT(m->m), "state-changed",
140 G_CALLBACK(on_state_changed_cb), call);
142 return (sipe_media *)m;
145 void
146 sipe_backend_media_free(sipe_media *media)
148 sipe_purple_media *m = (sipe_purple_media *)media;
149 purple_media_manager_remove_media(purple_media_manager_get(), m->m);
150 g_free(m);
153 gboolean
154 sipe_backend_media_add_stream(sipe_media *media, const gchar* participant,
155 SipeMediaType type, gboolean use_nice,
156 gboolean initiator)
158 sipe_purple_media *m = (sipe_purple_media *)media;
159 PurpleMediaSessionType prpl_type = sipe_media_to_purple(type);
160 GParameter *params = NULL;
161 guint params_cnt = 0;
162 gchar *transmitter;
164 if (use_nice) {
165 transmitter = "nice";
166 params_cnt = 2;
168 params = g_new0(GParameter, params_cnt);
169 params[0].name = "controlling-mode";
170 g_value_init(&params[0].value, G_TYPE_BOOLEAN);
171 g_value_set_boolean(&params[0].value, initiator);
172 params[1].name = "compatibility-mode";
173 g_value_init(&params[1].value, G_TYPE_UINT);
174 g_value_set_uint(&params[1].value, NICE_COMPATIBILITY_OC2007R2);
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: