finch: Mark unused variable.
[pidgin-git.git] / finch / gntmedia.c
blobdbbf7a1c7b7332aea74f912d9ad2fc63044ee7af
1 /*
2 * finch
4 * Finch is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 #include <internal.h>
24 #include "finch.h"
25 #include "gntconv.h"
26 #include "gntmedia.h"
28 #include "gnt.h"
29 #include "gntbutton.h"
30 #include "gntbox.h"
31 #include "gntlabel.h"
33 #include "cmds.h"
34 #include "conversation.h"
35 #include "debug.h"
36 #include "mediamanager.h"
38 /* An incredibly large part of the following is from gtkmedia.c */
39 #ifdef USE_VV
40 #include "media-gst.h"
42 #undef hangup
44 #define FINCH_TYPE_MEDIA (finch_media_get_type())
45 #define FINCH_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FINCH_TYPE_MEDIA, FinchMedia))
46 #define FINCH_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FINCH_TYPE_MEDIA, FinchMediaClass))
47 #define FINCH_IS_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), FINCH_TYPE_MEDIA))
48 #define FINCH_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FINCH_TYPE_MEDIA))
49 #define FINCH_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FINCH_TYPE_MEDIA, FinchMediaClass))
51 typedef struct _FinchMedia FinchMedia;
52 typedef struct _FinchMediaClass FinchMediaClass;
53 typedef struct _FinchMediaPrivate FinchMediaPrivate;
54 typedef enum _FinchMediaState FinchMediaState;
56 struct _FinchMediaClass
58 GntBoxClass parent_class;
61 struct _FinchMedia
63 GntBox parent;
64 FinchMediaPrivate *priv;
67 struct _FinchMediaPrivate
69 PurpleMedia *media;
71 GntWidget *accept;
72 GntWidget *reject;
73 GntWidget *hangup;
74 GntWidget *calling;
76 PurpleConversation *conv;
79 static GType finch_media_get_type (void);
80 static void finch_media_class_init (FinchMediaClass *klass);
81 static void finch_media_init (FinchMedia *media);
82 static void finch_media_finalize (GObject *object);
83 static void finch_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
84 static void finch_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
86 enum {
87 MESSAGE,
88 LAST_SIGNAL
90 static guint finch_media_signals[LAST_SIGNAL] = {0};
92 enum {
93 PROP_0,
94 PROP_MEDIA,
97 G_DEFINE_TYPE_WITH_PRIVATE(FinchMedia, finch_media, GNT_TYPE_BOX);
99 static void
100 finch_media_class_init (FinchMediaClass *klass)
102 GObjectClass *gobject_class = (GObjectClass*)klass;
104 gobject_class->finalize = finch_media_finalize;
105 gobject_class->set_property = finch_media_set_property;
106 gobject_class->get_property = finch_media_get_property;
108 g_object_class_install_property(gobject_class, PROP_MEDIA,
109 g_param_spec_object("media",
110 "PurpleMedia",
111 "The PurpleMedia associated with this media.",
112 PURPLE_TYPE_MEDIA,
113 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
115 finch_media_signals[MESSAGE] = g_signal_new("message", G_TYPE_FROM_CLASS(klass),
116 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
117 g_cclosure_marshal_VOID__STRING,
118 G_TYPE_NONE, 1, G_TYPE_STRING);
122 static void
123 finch_media_init (FinchMedia *media)
125 media->priv = finch_media_get_instance_private(media);
127 media->priv->calling = gnt_label_new(_("Calling..."));
128 media->priv->hangup = gnt_button_new(_("Hangup"));
129 media->priv->accept = gnt_button_new(_("Accept"));
130 media->priv->reject = gnt_button_new(_("Reject"));
132 gnt_box_set_alignment(GNT_BOX(media), GNT_ALIGN_MID);
134 gnt_box_add_widget(GNT_BOX(media), media->priv->accept);
135 gnt_box_add_widget(GNT_BOX(media), media->priv->reject);
138 static void
139 finch_media_finalize (GObject *media)
141 FinchMedia *gntmedia = FINCH_MEDIA(media);
142 purple_debug_info("gntmedia", "finch_media_finalize\n");
143 if (gntmedia->priv->media)
144 g_object_unref(gntmedia->priv->media);
147 static void
148 finch_media_emit_message(FinchMedia *gntmedia, const char *msg)
150 g_signal_emit(gntmedia, finch_media_signals[MESSAGE], 0, msg);
153 static void
154 finch_media_connected_cb(PurpleMedia *media, FinchMedia *gntmedia)
156 GntWidget *parent;
158 finch_media_emit_message(gntmedia, _("Call in progress."));
160 gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->accept);
161 gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->reject);
162 gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->hangup);
163 gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->calling);
165 gnt_box_add_widget(GNT_BOX(gntmedia), gntmedia->priv->hangup);
167 gnt_widget_destroy(gntmedia->priv->accept);
168 gnt_widget_destroy(gntmedia->priv->reject);
169 gnt_widget_destroy(gntmedia->priv->calling);
170 gntmedia->priv->accept = NULL;
171 gntmedia->priv->reject = NULL;
172 gntmedia->priv->calling = NULL;
174 parent = gnt_widget_get_toplevel(GNT_WIDGET(gntmedia));
175 gnt_box_readjust(GNT_BOX(parent));
176 gnt_widget_draw(parent);
179 static void
180 finch_media_wait_cb(PurpleMedia *media, FinchMedia *gntmedia)
182 GntWidget *parent;
184 gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->accept);
185 gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->reject);
186 gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->hangup);
187 gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->calling);
189 gnt_box_add_widget(GNT_BOX(gntmedia), gntmedia->priv->calling);
190 gnt_box_add_widget(GNT_BOX(gntmedia), gntmedia->priv->hangup);
192 parent = gnt_widget_get_toplevel(GNT_WIDGET(gntmedia));
193 gnt_box_readjust(GNT_BOX(parent));
194 gnt_widget_draw(parent);
197 static void
198 finch_media_state_changed_cb(PurpleMedia *media, PurpleMediaState state,
199 gchar *sid, gchar *name, FinchMedia *gntmedia)
201 purple_debug_info("gntmedia", "state: %d sid: %s name: %s\n",
202 state, sid, name);
203 if (sid == NULL && name == NULL) {
204 if (state == PURPLE_MEDIA_STATE_END) {
205 finch_media_emit_message(gntmedia,
206 _("The call has been terminated."));
207 finch_conversation_set_info_widget(
208 gntmedia->priv->conv, NULL);
209 gnt_widget_destroy(GNT_WIDGET(gntmedia));
211 * XXX: This shouldn't have to be here
212 * to free the FinchMedia widget.
214 g_object_unref(gntmedia);
216 } else if (state == PURPLE_MEDIA_STATE_CONNECTED) {
217 finch_media_connected_cb(media, gntmedia);
218 } else if (state == PURPLE_MEDIA_STATE_NEW &&
219 sid != NULL && name != NULL &&
220 purple_media_is_initiator(media, sid, name) == FALSE) {
221 PurpleAccount *account;
222 PurpleBuddy *buddy;
223 const gchar *alias;
224 PurpleMediaSessionType type =
225 purple_media_get_session_type(media, sid);
226 gchar *message = NULL;
228 account = purple_media_get_account(gntmedia->priv->media);
229 buddy = purple_blist_find_buddy(account, name);
230 alias = buddy ? purple_buddy_get_contact_alias(buddy) : name;
232 if (type & PURPLE_MEDIA_AUDIO) {
233 message = g_strdup_printf(
234 _("%s wishes to start an audio session with you."),
235 alias);
236 } else {
237 message = g_strdup_printf(
238 _("%s is trying to start an unsupported media session type with you."),
239 alias);
241 finch_media_emit_message(gntmedia, message);
242 g_free(message);
246 static void
247 finch_media_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
248 gchar *sid, gchar *name, gboolean local, FinchMedia *gntmedia)
250 if (type == PURPLE_MEDIA_INFO_REJECT) {
251 finch_media_emit_message(gntmedia,
252 _("You have rejected the call."));
256 static void
257 finch_media_accept_cb(PurpleMedia *media, GntWidget *widget)
259 purple_media_stream_info(media, PURPLE_MEDIA_INFO_ACCEPT,
260 NULL, NULL, TRUE);
263 static void
264 finch_media_hangup_cb(PurpleMedia *media, GntWidget *widget)
266 purple_media_stream_info(media, PURPLE_MEDIA_INFO_HANGUP,
267 NULL, NULL, TRUE);
270 static void
271 finch_media_reject_cb(PurpleMedia *media, GntWidget *widget)
273 purple_media_stream_info(media, PURPLE_MEDIA_INFO_REJECT,
274 NULL, NULL, TRUE);
277 static void
278 finch_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
280 FinchMedia *media;
281 g_return_if_fail(FINCH_IS_MEDIA(object));
283 media = FINCH_MEDIA(object);
284 switch (prop_id) {
285 case PROP_MEDIA:
287 if (media->priv->media)
288 g_object_unref(media->priv->media);
289 media->priv->media = g_value_dup_object(value);
290 g_signal_connect_swapped(G_OBJECT(media->priv->accept), "activate",
291 G_CALLBACK(finch_media_accept_cb), media->priv->media);
292 g_signal_connect_swapped(G_OBJECT(media->priv->reject), "activate",
293 G_CALLBACK(finch_media_reject_cb), media->priv->media);
294 g_signal_connect_swapped(G_OBJECT(media->priv->hangup), "activate",
295 G_CALLBACK(finch_media_hangup_cb), media->priv->media);
297 if (purple_media_is_initiator(media->priv->media,
298 NULL, NULL) == TRUE) {
299 finch_media_wait_cb(media->priv->media, media);
301 g_signal_connect(G_OBJECT(media->priv->media), "state-changed",
302 G_CALLBACK(finch_media_state_changed_cb), media);
303 g_signal_connect(G_OBJECT(media->priv->media), "stream-info",
304 G_CALLBACK(finch_media_stream_info_cb), media);
305 break;
307 default:
308 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
309 break;
313 static void
314 finch_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
316 FinchMedia *media;
317 g_return_if_fail(FINCH_IS_MEDIA(object));
319 media = FINCH_MEDIA(object);
321 switch (prop_id) {
322 case PROP_MEDIA:
323 g_value_set_object(value, media->priv->media);
324 break;
325 default:
326 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
327 break;
331 static GntWidget *
332 finch_media_new(PurpleMedia *media)
334 return GNT_WIDGET(g_object_new(finch_media_get_type(),
335 "media", media,
336 "vertical", FALSE,
337 "homogeneous", FALSE,
338 NULL));
341 static void
342 gntmedia_message_cb(FinchMedia *gntmedia, const char *msg, PurpleConversation *conv)
344 if (PURPLE_IS_IM_CONVERSATION(conv)) {
345 purple_conversation_write_system_message(conv, msg, 0);
349 static gboolean
350 finch_new_media(PurpleMediaManager *manager, PurpleMedia *media,
351 PurpleAccount *account, gchar *name, gpointer null)
353 GntWidget *gntmedia;
354 PurpleConversation *conv;
356 conv = PURPLE_CONVERSATION(purple_im_conversation_new(account, name));
358 gntmedia = finch_media_new(media);
359 g_signal_connect(G_OBJECT(gntmedia), "message", G_CALLBACK(gntmedia_message_cb), conv);
360 FINCH_MEDIA(gntmedia)->priv->conv = conv;
361 finch_conversation_set_info_widget(conv, gntmedia);
362 return TRUE;
365 static PurpleCmdRet
366 call_cmd_cb(PurpleConversation *conv, const char *cmd, char **args,
367 char **eror, gpointer data)
369 PurpleAccount *account = purple_conversation_get_account(conv);
371 if (!purple_protocol_initiate_media(account,
372 purple_conversation_get_name(conv),
373 PURPLE_MEDIA_AUDIO))
374 return PURPLE_CMD_RET_FAILED;
376 return PURPLE_CMD_RET_OK;
379 #endif /* USE_VV */
381 void finch_media_manager_init(void)
383 #ifdef USE_VV
384 PurpleMediaManager *manager = purple_media_manager_get();
385 PurpleMediaElementInfo *audio_src = NULL;
386 PurpleMediaElementInfo *audio_sink = NULL;
387 const char *pref;
389 pref = purple_prefs_get_string(
390 FINCH_PREFS_ROOT "/vvconfig/audio/src/device");
391 if (pref)
392 audio_src = purple_media_manager_get_element_info(manager, pref);
393 if (!audio_src) {
394 pref = "autoaudiosrc";
395 purple_prefs_set_string(
396 FINCH_PREFS_ROOT "/vvconfig/audio/src/device", pref);
397 audio_src = purple_media_manager_get_element_info(manager,
398 pref);
401 pref = purple_prefs_get_string(
402 FINCH_PREFS_ROOT "/vvconfig/audio/sink/device");
403 if (pref)
404 audio_sink = purple_media_manager_get_element_info(manager, pref);
405 if (!audio_sink) {
406 pref = "autoaudiosink";
407 purple_prefs_set_string(
408 FINCH_PREFS_ROOT "/vvconfig/audio/sink/device", pref);
409 audio_sink = purple_media_manager_get_element_info(manager,
410 pref);
413 g_signal_connect(G_OBJECT(manager), "init-media", G_CALLBACK(finch_new_media), NULL);
414 purple_cmd_register("call", "", PURPLE_CMD_P_DEFAULT,
415 PURPLE_CMD_FLAG_IM, NULL,
416 call_cmd_cb, _("call: Make an audio call."), NULL);
418 purple_media_manager_set_ui_caps(manager,
419 PURPLE_MEDIA_CAPS_AUDIO |
420 PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION);
422 purple_debug_info("gntmedia", "Registering media element types\n");
423 purple_media_manager_set_active_element(manager, audio_src);
424 purple_media_manager_set_active_element(manager, audio_sink);
425 #endif
428 void finch_media_manager_uninit(void)
430 #ifdef USE_VV
431 PurpleMediaManager *manager = purple_media_manager_get();
432 g_signal_handlers_disconnect_by_func(G_OBJECT(manager),
433 G_CALLBACK(finch_new_media), NULL);
434 #endif