~vish/ubuntu/maverick/pidgin/bug25979

« back to all changes in this revision

Viewing changes to pidgin/gtkmedia.c

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-10-09 19:40:26 UTC
  • mfrom: (1.4.1 upstream) (46.1.10 karmic)
  • Revision ID: james.westby@ubuntu.com-20091009194026-wbqqh0bsbz19nx5q
Tags: 1:2.6.2-1ubuntu7
* Don't stick the buddy list window to all desktops as some
  window managers have trouble to properly unstick it (LP: #346840)
  - debian/patches/11_buddy_list_really_show.patch
* Always use default tray icon size on KDE (LP: #209440)
  - debian/patches/62_tray_icon_size_kde.patch
* Use scrollbars in the preferences dialog if the screen height is
  below 700 px instead of 600 px
  - debian/patches/60_1024x600_gtkprefs.c.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file media.c Account API
 
3
 * @ingroup core
 
4
 *
 
5
 * Pidgin
 
6
 *
 
7
 * Pidgin is the legal property of its developers, whose names are too numerous
 
8
 * to list here.  Please refer to the COPYRIGHT file distributed with this
 
9
 * source distribution.
 
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., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
24
 */
 
25
 
 
26
#include <string.h>
 
27
#include "debug.h"
 
28
#include "internal.h"
 
29
#include "connection.h"
 
30
#include "media.h"
 
31
#include "mediamanager.h"
 
32
#include "pidgin.h"
 
33
#include "request.h"
 
34
 
 
35
#include "gtkmedia.h"
 
36
#include "gtkutils.h"
 
37
#include "pidginstock.h"
 
38
 
 
39
#ifdef USE_VV
 
40
#include "media-gst.h"
 
41
 
 
42
#ifdef _WIN32
 
43
#include <gdk/gdkwin32.h>
 
44
#endif
 
45
 
 
46
#include <gst/interfaces/xoverlay.h>
 
47
 
 
48
#define PIDGIN_TYPE_MEDIA            (pidgin_media_get_type())
 
49
#define PIDGIN_MEDIA(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), PIDGIN_TYPE_MEDIA, PidginMedia))
 
50
#define PIDGIN_MEDIA_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), PIDGIN_TYPE_MEDIA, PidginMediaClass))
 
51
#define PIDGIN_IS_MEDIA(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), PIDGIN_TYPE_MEDIA))
 
52
#define PIDGIN_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PIDGIN_TYPE_MEDIA))
 
53
#define PIDGIN_MEDIA_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), PIDGIN_TYPE_MEDIA, PidginMediaClass))
 
54
 
 
55
typedef struct _PidginMedia PidginMedia;
 
56
typedef struct _PidginMediaClass PidginMediaClass;
 
57
typedef struct _PidginMediaPrivate PidginMediaPrivate;
 
58
 
 
59
typedef enum
 
60
{
 
61
        /* Waiting for response */
 
62
        PIDGIN_MEDIA_WAITING = 1,
 
63
        /* Got request */
 
64
        PIDGIN_MEDIA_REQUESTED,
 
65
        /* Accepted call */
 
66
        PIDGIN_MEDIA_ACCEPTED,
 
67
        /* Rejected call */
 
68
        PIDGIN_MEDIA_REJECTED,
 
69
} PidginMediaState;
 
70
 
 
71
struct _PidginMediaClass
 
72
{
 
73
        GtkWindowClass parent_class;
 
74
};
 
75
 
 
76
struct _PidginMedia
 
77
{
 
78
        GtkWindow parent;
 
79
        PidginMediaPrivate *priv;
 
80
};
 
81
 
 
82
struct _PidginMediaPrivate
 
83
{
 
84
        PurpleMedia *media;
 
85
        gchar *screenname;
 
86
        gulong level_handler_id;
 
87
 
 
88
        GtkItemFactory *item_factory;
 
89
        GtkWidget *menubar;
 
90
        GtkWidget *statusbar;
 
91
 
 
92
        GtkWidget *mute;
 
93
        GtkWidget *pause;
 
94
 
 
95
        GtkWidget *send_progress;
 
96
        GtkWidget *recv_progress;
 
97
 
 
98
        PidginMediaState state;
 
99
 
 
100
        GtkWidget *display;
 
101
        GtkWidget *send_widget;
 
102
        GtkWidget *recv_widget;
 
103
        GtkWidget *button_widget;
 
104
        GtkWidget *local_video;
 
105
        GtkWidget *remote_video;
 
106
 
 
107
        guint timeout_id;
 
108
        PurpleMediaSessionType request_type;
 
109
};
 
110
 
 
111
#define PIDGIN_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_MEDIA, PidginMediaPrivate))
 
112
 
 
113
static void pidgin_media_class_init (PidginMediaClass *klass);
 
114
static void pidgin_media_init (PidginMedia *media);
 
115
static void pidgin_media_dispose (GObject *object);
 
116
static void pidgin_media_finalize (GObject *object);
 
117
static void pidgin_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
 
118
static void pidgin_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
 
119
static void pidgin_media_set_state(PidginMedia *gtkmedia, PidginMediaState state);
 
120
 
 
121
static GtkWindowClass *parent_class = NULL;
 
122
 
 
123
 
 
124
#if 0
 
125
enum {
 
126
        LAST_SIGNAL
 
127
};
 
128
static guint pidgin_media_signals[LAST_SIGNAL] = {0};
 
129
#endif
 
130
 
 
131
enum {
 
132
        PROP_0,
 
133
        PROP_MEDIA,
 
134
        PROP_SCREENNAME
 
135
};
 
136
 
 
137
static GType
 
138
pidgin_media_get_type(void)
 
139
{
 
140
        static GType type = 0;
 
141
 
 
142
        if (type == 0) {
 
143
                static const GTypeInfo info = {
 
144
                        sizeof(PidginMediaClass),
 
145
                        NULL,
 
146
                        NULL,
 
147
                        (GClassInitFunc) pidgin_media_class_init,
 
148
                        NULL,
 
149
                        NULL,
 
150
                        sizeof(PidginMedia),
 
151
                        0,
 
152
                        (GInstanceInitFunc) pidgin_media_init,
 
153
                        NULL
 
154
                };
 
155
                type = g_type_register_static(GTK_TYPE_WINDOW, "PidginMedia", &info, 0);
 
156
        }
 
157
        return type;
 
158
}
 
159
 
 
160
 
 
161
static void
 
162
pidgin_media_class_init (PidginMediaClass *klass)
 
163
{
 
164
        GObjectClass *gobject_class = (GObjectClass*)klass;
 
165
/*      GtkContainerClass *container_class = (GtkContainerClass*)klass; */
 
166
        parent_class = g_type_class_peek_parent(klass);
 
167
 
 
168
        gobject_class->dispose = pidgin_media_dispose;
 
169
        gobject_class->finalize = pidgin_media_finalize;
 
170
        gobject_class->set_property = pidgin_media_set_property;
 
171
        gobject_class->get_property = pidgin_media_get_property;
 
172
 
 
173
        g_object_class_install_property(gobject_class, PROP_MEDIA,
 
174
                        g_param_spec_object("media",
 
175
                        "PurpleMedia",
 
176
                        "The PurpleMedia associated with this media.",
 
177
                        PURPLE_TYPE_MEDIA,
 
178
                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
 
179
        g_object_class_install_property(gobject_class, PROP_SCREENNAME,
 
180
                        g_param_spec_string("screenname",
 
181
                        "Screenname",
 
182
                        "The screenname of the user this session is with.",
 
183
                        NULL,
 
184
                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
 
185
 
 
186
        g_type_class_add_private(klass, sizeof(PidginMediaPrivate));
 
187
}
 
188
 
 
189
static void
 
190
pidgin_media_mute_toggled(GtkToggleButton *toggle, PidginMedia *media)
 
191
{
 
192
        purple_media_stream_info(media->priv->media,
 
193
                        gtk_toggle_button_get_active(toggle) ?
 
194
                        PURPLE_MEDIA_INFO_MUTE : PURPLE_MEDIA_INFO_UNMUTE,
 
195
                        NULL, NULL, TRUE);
 
196
}
 
197
 
 
198
static void
 
199
pidgin_media_pause_toggled(GtkToggleButton *toggle, PidginMedia *media)
 
200
{
 
201
        purple_media_stream_info(media->priv->media,
 
202
                        gtk_toggle_button_get_active(toggle) ?
 
203
                        PURPLE_MEDIA_INFO_PAUSE : PURPLE_MEDIA_INFO_UNPAUSE,
 
204
                        NULL, NULL, TRUE);
 
205
}
 
206
 
 
207
static gboolean
 
208
pidgin_media_delete_event_cb(GtkWidget *widget,
 
209
                GdkEvent *event, PidginMedia *media)
 
210
{
 
211
        if (media->priv->media)
 
212
                purple_media_stream_info(media->priv->media,
 
213
                                PURPLE_MEDIA_INFO_HANGUP, NULL, NULL, TRUE);
 
214
        return FALSE;
 
215
}
 
216
 
 
217
#ifdef HAVE_X11
 
218
static int
 
219
pidgin_x_error_handler(Display *display, XErrorEvent *event)
 
220
{
 
221
        const gchar *error_type;
 
222
        switch (event->error_code) {
 
223
#define XERRORCASE(type) case type: error_type = #type; break
 
224
                XERRORCASE(BadAccess);
 
225
                XERRORCASE(BadAlloc);
 
226
                XERRORCASE(BadAtom);
 
227
                XERRORCASE(BadColor);
 
228
                XERRORCASE(BadCursor);
 
229
                XERRORCASE(BadDrawable);
 
230
                XERRORCASE(BadFont);
 
231
                XERRORCASE(BadGC);
 
232
                XERRORCASE(BadIDChoice);
 
233
                XERRORCASE(BadImplementation);
 
234
                XERRORCASE(BadLength);
 
235
                XERRORCASE(BadMatch);
 
236
                XERRORCASE(BadName);
 
237
                XERRORCASE(BadPixmap);
 
238
                XERRORCASE(BadRequest);
 
239
                XERRORCASE(BadValue);
 
240
                XERRORCASE(BadWindow);
 
241
#undef XERRORCASE
 
242
                default:
 
243
                        error_type = "unknown";
 
244
                        break;
 
245
        }
 
246
        purple_debug_error("media", "A %s Xlib error has occurred. "
 
247
                        "The program would normally crash now.\n",
 
248
                        error_type);
 
249
        return 0;
 
250
}
 
251
#endif
 
252
 
 
253
static void
 
254
menu_hangup(gpointer data, guint action, GtkWidget *item)
 
255
{
 
256
        PidginMedia *gtkmedia = PIDGIN_MEDIA(data);
 
257
        purple_media_stream_info(gtkmedia->priv->media,
 
258
                        PURPLE_MEDIA_INFO_HANGUP, NULL, NULL, TRUE);
 
259
}
 
260
 
 
261
static GtkItemFactoryEntry menu_items[] = {
 
262
        { N_("/_Media"), NULL, NULL, 0, "<Branch>", NULL },
 
263
        { N_("/Media/_Hangup"), NULL, menu_hangup, 0, "<Item>", NULL },
 
264
};
 
265
 
 
266
static gint menu_item_count = sizeof(menu_items) / sizeof(menu_items[0]);
 
267
 
 
268
static const char *
 
269
item_factory_translate_func (const char *path, gpointer func_data)
 
270
{
 
271
        return _(path);
 
272
}
 
273
 
 
274
static GtkWidget *
 
275
setup_menubar(PidginMedia *window)
 
276
{
 
277
        GtkAccelGroup *accel_group;
 
278
        GtkWidget *menu;
 
279
 
 
280
        accel_group = gtk_accel_group_new ();
 
281
        gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
 
282
        g_object_unref(accel_group);
 
283
 
 
284
        window->priv->item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR,
 
285
                        "<main>", accel_group);
 
286
 
 
287
        gtk_item_factory_set_translate_func(window->priv->item_factory,
 
288
                        (GtkTranslateFunc)item_factory_translate_func,
 
289
                        NULL, NULL);
 
290
 
 
291
        gtk_item_factory_create_items(window->priv->item_factory,
 
292
                        menu_item_count, menu_items, window);
 
293
        g_signal_connect(G_OBJECT(accel_group), "accel-changed",
 
294
                        G_CALLBACK(pidgin_save_accels_cb), NULL);
 
295
 
 
296
        menu = gtk_item_factory_get_widget(
 
297
                        window->priv->item_factory, "<main>");
 
298
 
 
299
        gtk_widget_show(menu);
 
300
        return menu;
 
301
}
 
302
 
 
303
static void
 
304
pidgin_media_init (PidginMedia *media)
 
305
{
 
306
        GtkWidget *vbox;
 
307
        media->priv = PIDGIN_MEDIA_GET_PRIVATE(media);
 
308
 
 
309
#ifdef HAVE_X11
 
310
        XSetErrorHandler(pidgin_x_error_handler);
 
311
#endif
 
312
 
 
313
        vbox = gtk_vbox_new(FALSE, 0);
 
314
        gtk_container_add(GTK_CONTAINER(media), vbox);
 
315
 
 
316
        media->priv->statusbar = gtk_statusbar_new();
 
317
        gtk_box_pack_end(GTK_BOX(vbox), media->priv->statusbar,
 
318
                        FALSE, FALSE, 0);
 
319
        gtk_statusbar_push(GTK_STATUSBAR(media->priv->statusbar),
 
320
                        0, _("Calling..."));
 
321
        gtk_widget_show(media->priv->statusbar);
 
322
 
 
323
        media->priv->menubar = setup_menubar(media);
 
324
        gtk_box_pack_start(GTK_BOX(vbox), media->priv->menubar,
 
325
                        FALSE, TRUE, 0);
 
326
 
 
327
        media->priv->display = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 
328
        gtk_container_set_border_width(GTK_CONTAINER(media->priv->display),
 
329
                        PIDGIN_HIG_BOX_SPACE);
 
330
        gtk_box_pack_start(GTK_BOX(vbox), media->priv->display,
 
331
                        TRUE, TRUE, PIDGIN_HIG_BOX_SPACE);
 
332
        gtk_widget_show(vbox);
 
333
 
 
334
        g_signal_connect(G_OBJECT(media), "delete-event",
 
335
                        G_CALLBACK(pidgin_media_delete_event_cb), media);
 
336
}
 
337
 
 
338
static void
 
339
level_message_cb(PurpleMedia *media, gchar *session_id, gchar *participant,
 
340
                double level, PidginMedia *gtkmedia)
 
341
{
 
342
        GtkWidget *progress;
 
343
        if (participant == NULL)
 
344
                progress = gtkmedia->priv->send_progress;
 
345
        else
 
346
                progress = gtkmedia->priv->recv_progress;
 
347
        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level);
 
348
}
 
349
 
 
350
 
 
351
static void
 
352
pidgin_media_disconnect_levels(PurpleMedia *media, PidginMedia *gtkmedia)
 
353
{
 
354
        PurpleMediaManager *manager = purple_media_get_manager(media);
 
355
        GstElement *element = purple_media_manager_get_pipeline(manager);
 
356
        gulong handler_id = g_signal_handler_find(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))),
 
357
                                                  G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, 
 
358
                                                  NULL, G_CALLBACK(level_message_cb), gtkmedia);
 
359
        if (handler_id)
 
360
                g_signal_handler_disconnect(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))),
 
361
                                            handler_id);
 
362
}
 
363
 
 
364
static void
 
365
pidgin_media_dispose(GObject *media)
 
366
{
 
367
        PidginMedia *gtkmedia = PIDGIN_MEDIA(media);
 
368
        purple_debug_info("gtkmedia", "pidgin_media_dispose\n");
 
369
 
 
370
        if (gtkmedia->priv->media) {
 
371
                purple_request_close_with_handle(gtkmedia);
 
372
                purple_media_remove_output_windows(gtkmedia->priv->media);
 
373
                pidgin_media_disconnect_levels(gtkmedia->priv->media, gtkmedia);
 
374
                g_object_unref(gtkmedia->priv->media);
 
375
                gtkmedia->priv->media = NULL;
 
376
        }
 
377
 
 
378
        if (gtkmedia->priv->item_factory) {
 
379
                g_object_unref(gtkmedia->priv->item_factory);
 
380
                gtkmedia->priv->item_factory = NULL;
 
381
        }
 
382
 
 
383
        G_OBJECT_CLASS(parent_class)->dispose(media);
 
384
}
 
385
 
 
386
static void
 
387
pidgin_media_finalize(GObject *media)
 
388
{
 
389
        /* PidginMedia *gtkmedia = PIDGIN_MEDIA(media); */
 
390
        purple_debug_info("gtkmedia", "pidgin_media_finalize\n");
 
391
 
 
392
        G_OBJECT_CLASS(parent_class)->finalize(media);
 
393
}
 
394
 
 
395
static void
 
396
pidgin_media_emit_message(PidginMedia *gtkmedia, const char *msg)
 
397
{
 
398
        PurpleConversation *conv = purple_find_conversation_with_account(
 
399
                        PURPLE_CONV_TYPE_ANY, gtkmedia->priv->screenname,
 
400
                        purple_media_get_account(gtkmedia->priv->media));
 
401
        if (conv != NULL)
 
402
                purple_conversation_write(conv, NULL, msg,
 
403
                                PURPLE_MESSAGE_SYSTEM, time(NULL));
 
404
}
 
405
 
 
406
typedef struct
 
407
{
 
408
        PidginMedia *gtkmedia;
 
409
        gchar *session_id;
 
410
        gchar *participant;
 
411
} PidginMediaRealizeData;
 
412
 
 
413
static gboolean
 
414
realize_cb_cb(PidginMediaRealizeData *data)
 
415
{
 
416
        PidginMediaPrivate *priv = data->gtkmedia->priv;
 
417
        gulong window_id;
 
418
 
 
419
#ifdef _WIN32
 
420
        if (data->participant == NULL)
 
421
                window_id = GDK_WINDOW_HWND(priv->local_video->window);
 
422
        else
 
423
                window_id = GDK_WINDOW_HWND(priv->remote_video->window);
 
424
#elif defined(HAVE_X11)
 
425
        if (data->participant == NULL)
 
426
                window_id = GDK_WINDOW_XWINDOW(priv->local_video->window);
 
427
        else
 
428
                window_id = GDK_WINDOW_XWINDOW(priv->remote_video->window);
 
429
#else
 
430
#       error "Unsupported windowing system"
 
431
#endif
 
432
 
 
433
        purple_media_set_output_window(priv->media, data->session_id,
 
434
                        data->participant, window_id);
 
435
 
 
436
        g_free(data->session_id);
 
437
        g_free(data->participant);
 
438
        g_free(data);
 
439
        return FALSE;
 
440
}
 
441
 
 
442
static void
 
443
realize_cb(GtkWidget *widget, PidginMediaRealizeData *data)
 
444
{
 
445
        g_timeout_add(0, (GSourceFunc)realize_cb_cb, data);
 
446
}
 
447
 
 
448
static void
 
449
pidgin_media_error_cb(PidginMedia *media, const char *error, PidginMedia *gtkmedia)
 
450
{
 
451
        PurpleConversation *conv = purple_find_conversation_with_account(
 
452
                        PURPLE_CONV_TYPE_ANY, gtkmedia->priv->screenname,
 
453
                        purple_media_get_account(gtkmedia->priv->media));
 
454
        if (conv != NULL)
 
455
                purple_conversation_write(conv, NULL, error,
 
456
                                PURPLE_MESSAGE_ERROR, time(NULL));
 
457
        gtk_statusbar_push(GTK_STATUSBAR(gtkmedia->priv->statusbar),
 
458
                        0, error);
 
459
}
 
460
 
 
461
static void
 
462
pidgin_media_accept_cb(PurpleMedia *media, int index)
 
463
{
 
464
        purple_media_stream_info(media, PURPLE_MEDIA_INFO_ACCEPT,
 
465
                        NULL, NULL, TRUE);
 
466
}
 
467
 
 
468
static void
 
469
pidgin_media_reject_cb(PurpleMedia *media, int index)
 
470
{
 
471
        purple_media_stream_info(media, PURPLE_MEDIA_INFO_REJECT,
 
472
                        NULL, NULL, TRUE);
 
473
}
 
474
 
 
475
static gboolean
 
476
pidgin_request_timeout_cb(PidginMedia *gtkmedia)
 
477
{
 
478
        PurpleAccount *account;
 
479
        PurpleBuddy *buddy;
 
480
        const gchar *alias;
 
481
        PurpleMediaSessionType type;
 
482
        gchar *message = NULL;
 
483
 
 
484
        account = purple_media_get_account(gtkmedia->priv->media);
 
485
        buddy = purple_find_buddy(account, gtkmedia->priv->screenname);
 
486
        alias = buddy ? purple_buddy_get_contact_alias(buddy) :
 
487
                        gtkmedia->priv->screenname;
 
488
        type = gtkmedia->priv->request_type;
 
489
        gtkmedia->priv->timeout_id = 0;
 
490
 
 
491
        if (type & PURPLE_MEDIA_AUDIO && type & PURPLE_MEDIA_VIDEO) {
 
492
                message = g_strdup_printf(_("%s wishes to start an audio/video session with you."),
 
493
                                alias);
 
494
        } else if (type & PURPLE_MEDIA_AUDIO) {
 
495
                message = g_strdup_printf(_("%s wishes to start an audio session with you."),
 
496
                                alias);
 
497
        } else if (type & PURPLE_MEDIA_VIDEO) {
 
498
                message = g_strdup_printf(_("%s wishes to start a video session with you."),
 
499
                                alias);
 
500
        }
 
501
 
 
502
        gtkmedia->priv->request_type = PURPLE_MEDIA_NONE;
 
503
        if (!purple_media_accepted(gtkmedia->priv->media, NULL, NULL)) {
 
504
                purple_request_accept_cancel(gtkmedia, _("Incoming Call"),
 
505
                                message, NULL, PURPLE_DEFAULT_ACTION_NONE,
 
506
                                (void*)account, gtkmedia->priv->screenname,
 
507
                                NULL, gtkmedia->priv->media,
 
508
                                pidgin_media_accept_cb,
 
509
                                pidgin_media_reject_cb);
 
510
        }
 
511
        pidgin_media_emit_message(gtkmedia, message);
 
512
        g_free(message);
 
513
        return FALSE;
 
514
}
 
515
 
 
516
static void
 
517
#if GTK_CHECK_VERSION(2,12,0)
 
518
pidgin_media_input_volume_changed(GtkScaleButton *range, double value,
 
519
                PurpleMedia *media)
 
520
{
 
521
        double val = (double)value * 100.0;
 
522
#else
 
523
pidgin_media_input_volume_changed(GtkRange *range, PurpleMedia *media)
 
524
{
 
525
        double val = (double)gtk_range_get_value(GTK_RANGE(range));
 
526
#endif
 
527
        purple_media_set_input_volume(media, NULL, val);
 
528
}
 
529
 
 
530
static void
 
531
#if GTK_CHECK_VERSION(2,12,0)
 
532
pidgin_media_output_volume_changed(GtkScaleButton *range, double value,
 
533
                PurpleMedia *media)
 
534
{
 
535
        double val = (double)value * 100.0;
 
536
#else
 
537
pidgin_media_output_volume_changed(GtkRange *range, PurpleMedia *media)
 
538
{
 
539
        double val = (double)gtk_range_get_value(GTK_RANGE(range));
 
540
#endif
 
541
        purple_media_set_output_volume(media, NULL, NULL, val);
 
542
}
 
543
 
 
544
static GtkWidget *
 
545
pidgin_media_add_audio_widget(PidginMedia *gtkmedia,
 
546
                PurpleMediaSessionType type)
 
547
{
 
548
        GtkWidget *volume_widget, *progress_parent, *volume, *progress;
 
549
        double value;
 
550
 
 
551
        if (type & PURPLE_MEDIA_SEND_AUDIO) {
 
552
                value = purple_prefs_get_int(
 
553
                        "/purple/media/audio/volume/input");
 
554
        } else if (type & PURPLE_MEDIA_RECV_AUDIO) {
 
555
                value = purple_prefs_get_int(
 
556
                        "/purple/media/audio/volume/output");
 
557
        } else
 
558
                g_return_val_if_reached(NULL);
 
559
 
 
560
#if GTK_CHECK_VERSION(2,12,0)
 
561
        /* Setup widget structure */
 
562
        volume_widget = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 
563
        progress_parent = gtk_vbox_new(FALSE, 0);
 
564
        gtk_box_pack_start(GTK_BOX(volume_widget),
 
565
                        progress_parent, TRUE, TRUE, 0);
 
566
 
 
567
        /* Volume button */
 
568
        volume = gtk_volume_button_new();
 
569
        gtk_scale_button_set_value(GTK_SCALE_BUTTON(volume), value/100.0);
 
570
        gtk_box_pack_end(GTK_BOX(volume_widget),
 
571
                        volume, FALSE, FALSE, 0);
 
572
#else
 
573
        /* Setup widget structure */
 
574
        volume_widget = gtk_vbox_new(FALSE, 0);
 
575
        progress_parent = volume_widget;
 
576
 
 
577
        /* Volume slider */
 
578
        volume = gtk_hscale_new_with_range(0.0, 100.0, 5.0);
 
579
        gtk_range_set_increments(GTK_RANGE(volume), 5.0, 25.0);
 
580
        gtk_range_set_value(GTK_RANGE(volume), value);
 
581
        gtk_scale_set_draw_value(GTK_SCALE(volume), FALSE);
 
582
        gtk_box_pack_end(GTK_BOX(volume_widget),
 
583
                        volume, TRUE, FALSE, 0);
 
584
#endif
 
585
 
 
586
        /* Volume level indicator */
 
587
        progress = gtk_progress_bar_new();
 
588
        gtk_widget_set_size_request(progress, 250, 10);
 
589
        gtk_box_pack_end(GTK_BOX(progress_parent), progress, TRUE, FALSE, 0);
 
590
 
 
591
        if (type & PURPLE_MEDIA_SEND_AUDIO) {
 
592
                g_signal_connect (G_OBJECT(volume), "value-changed",
 
593
                                G_CALLBACK(pidgin_media_input_volume_changed),
 
594
                                gtkmedia->priv->media);
 
595
                gtkmedia->priv->send_progress = progress;
 
596
        } else if (type & PURPLE_MEDIA_RECV_AUDIO) {
 
597
                g_signal_connect (G_OBJECT(volume), "value-changed",
 
598
                                G_CALLBACK(pidgin_media_output_volume_changed),
 
599
                                gtkmedia->priv->media);
 
600
                gtkmedia->priv->recv_progress = progress;
 
601
        }
 
602
 
 
603
        gtk_widget_show_all(volume_widget);
 
604
 
 
605
        return volume_widget;
 
606
}
 
607
 
 
608
static void
 
609
pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia, const gchar *sid)
 
610
{
 
611
        GtkWidget *send_widget = NULL, *recv_widget = NULL, *button_widget = NULL;
 
612
        PurpleMediaSessionType type =
 
613
                        purple_media_get_session_type(media, sid);
 
614
        GdkPixbuf *icon = NULL;
 
615
 
 
616
        if (gtkmedia->priv->recv_widget == NULL
 
617
                        && type & (PURPLE_MEDIA_RECV_VIDEO |
 
618
                        PURPLE_MEDIA_RECV_AUDIO)) {
 
619
                recv_widget = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);        
 
620
                gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display),
 
621
                                recv_widget, TRUE, TRUE, 0);
 
622
                gtk_widget_show(recv_widget);
 
623
        } else
 
624
                recv_widget = gtkmedia->priv->recv_widget;
 
625
        if (gtkmedia->priv->send_widget == NULL
 
626
                        && type & (PURPLE_MEDIA_SEND_VIDEO |
 
627
                        PURPLE_MEDIA_SEND_AUDIO)) {
 
628
                send_widget = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 
629
                gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display),
 
630
                                send_widget, TRUE, TRUE, 0);
 
631
                button_widget = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 
632
                gtk_box_pack_end(GTK_BOX(send_widget), button_widget,
 
633
                                FALSE, FALSE, 0);
 
634
                gtk_widget_show(GTK_WIDGET(button_widget));
 
635
                gtk_widget_show(send_widget);
 
636
        } else {
 
637
                send_widget = gtkmedia->priv->send_widget;
 
638
                button_widget = gtkmedia->priv->button_widget;
 
639
        }
 
640
 
 
641
        if (type & PURPLE_MEDIA_RECV_VIDEO) {
 
642
                PidginMediaRealizeData *data;
 
643
                GtkWidget *aspect;
 
644
                GtkWidget *remote_video;
 
645
                GdkColor color = {0, 0, 0, 0};
 
646
 
 
647
                aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE);
 
648
                gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
 
649
                gtk_box_pack_start(GTK_BOX(recv_widget), aspect, TRUE, TRUE, 0);
 
650
 
 
651
                data = g_new0(PidginMediaRealizeData, 1);
 
652
                data->gtkmedia = gtkmedia;
 
653
                data->session_id = g_strdup(sid);
 
654
                data->participant = g_strdup(gtkmedia->priv->screenname);
 
655
 
 
656
                remote_video = gtk_drawing_area_new();
 
657
                gtk_widget_modify_bg(remote_video, GTK_STATE_NORMAL, &color);
 
658
                g_signal_connect(G_OBJECT(remote_video), "realize",
 
659
                                G_CALLBACK(realize_cb), data);
 
660
                gtk_container_add(GTK_CONTAINER(aspect), remote_video);
 
661
                gtk_widget_set_size_request (GTK_WIDGET(remote_video), 320, 240);
 
662
                gtk_widget_show(remote_video);
 
663
                gtk_widget_show(aspect);
 
664
 
 
665
                gtkmedia->priv->remote_video = remote_video;
 
666
        }
 
667
        if (type & PURPLE_MEDIA_SEND_VIDEO) {
 
668
                PidginMediaRealizeData *data;
 
669
                GtkWidget *aspect;
 
670
                GtkWidget *local_video;
 
671
                GdkColor color = {0, 0, 0, 0};
 
672
 
 
673
                aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE);
 
674
                gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
 
675
                gtk_box_pack_start(GTK_BOX(send_widget), aspect, TRUE, TRUE, 0);
 
676
 
 
677
                data = g_new0(PidginMediaRealizeData, 1);
 
678
                data->gtkmedia = gtkmedia;
 
679
                data->session_id = g_strdup(sid);
 
680
                data->participant = NULL;
 
681
 
 
682
                local_video = gtk_drawing_area_new();
 
683
                gtk_widget_modify_bg(local_video, GTK_STATE_NORMAL, &color);
 
684
                g_signal_connect(G_OBJECT(local_video), "realize",
 
685
                                G_CALLBACK(realize_cb), data);
 
686
                gtk_container_add(GTK_CONTAINER(aspect), local_video);
 
687
                gtk_widget_set_size_request (GTK_WIDGET(local_video), 160, 120);
 
688
 
 
689
                gtk_widget_show(local_video);
 
690
                gtk_widget_show(aspect);
 
691
 
 
692
                gtkmedia->priv->pause =
 
693
                                gtk_toggle_button_new_with_mnemonic(_("_Pause"));
 
694
                g_signal_connect(gtkmedia->priv->pause, "toggled",
 
695
                                G_CALLBACK(pidgin_media_pause_toggled),
 
696
                                gtkmedia);
 
697
                gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->pause,
 
698
                                FALSE, FALSE, 0);
 
699
                gtk_widget_show(gtkmedia->priv->pause);
 
700
 
 
701
                gtkmedia->priv->local_video = local_video;
 
702
        }
 
703
 
 
704
        if (type & PURPLE_MEDIA_RECV_AUDIO) {
 
705
                gtk_box_pack_end(GTK_BOX(recv_widget),
 
706
                                pidgin_media_add_audio_widget(gtkmedia,
 
707
                                PURPLE_MEDIA_RECV_AUDIO), FALSE, FALSE, 0);
 
708
        }
 
709
        if (type & PURPLE_MEDIA_SEND_AUDIO) {
 
710
                gtkmedia->priv->mute =
 
711
                                gtk_toggle_button_new_with_mnemonic("_Mute");
 
712
                g_signal_connect(gtkmedia->priv->mute, "toggled",
 
713
                                G_CALLBACK(pidgin_media_mute_toggled),
 
714
                                gtkmedia);
 
715
                gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->mute,
 
716
                                FALSE, FALSE, 0);
 
717
                gtk_widget_show(gtkmedia->priv->mute);
 
718
 
 
719
                gtk_box_pack_end(GTK_BOX(send_widget),
 
720
                                pidgin_media_add_audio_widget(gtkmedia,
 
721
                                PURPLE_MEDIA_SEND_AUDIO), FALSE, FALSE, 0);
 
722
        }
 
723
 
 
724
 
 
725
        if (type & PURPLE_MEDIA_AUDIO &&
 
726
                        gtkmedia->priv->level_handler_id == 0) {
 
727
                gtkmedia->priv->level_handler_id = g_signal_connect(
 
728
                                media, "level", G_CALLBACK(level_message_cb),
 
729
                                gtkmedia);
 
730
        }
 
731
 
 
732
        if (send_widget != NULL)
 
733
                gtkmedia->priv->send_widget = send_widget;
 
734
        if (recv_widget != NULL)
 
735
                gtkmedia->priv->recv_widget = recv_widget;
 
736
        if (button_widget != NULL)
 
737
                gtkmedia->priv->button_widget = button_widget;
 
738
 
 
739
        if (purple_media_is_initiator(media, sid, NULL) == FALSE) {
 
740
                if (gtkmedia->priv->timeout_id != 0)
 
741
                        g_source_remove(gtkmedia->priv->timeout_id);
 
742
                gtkmedia->priv->request_type |= type;
 
743
                gtkmedia->priv->timeout_id = g_timeout_add(500,
 
744
                                (GSourceFunc)pidgin_request_timeout_cb,
 
745
                                gtkmedia);
 
746
        }
 
747
 
 
748
        /* set the window icon according to the type */
 
749
        if (type & PURPLE_MEDIA_VIDEO) {
 
750
                icon = gtk_widget_render_icon(GTK_WIDGET(gtkmedia),
 
751
                        PIDGIN_STOCK_TOOLBAR_VIDEO_CALL,
 
752
                        gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE), NULL);
 
753
        } else if (type & PURPLE_MEDIA_AUDIO) {
 
754
                icon = gtk_widget_render_icon(GTK_WIDGET(gtkmedia),
 
755
                        PIDGIN_STOCK_TOOLBAR_AUDIO_CALL,
 
756
                        gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE), NULL);
 
757
        }
 
758
 
 
759
        if (icon) {
 
760
                gtk_window_set_icon(GTK_WINDOW(gtkmedia), icon);
 
761
                g_object_unref(icon);
 
762
        }
 
763
        
 
764
        gtk_widget_show(gtkmedia->priv->display);
 
765
}
 
766
 
 
767
static void
 
768
pidgin_media_state_changed_cb(PurpleMedia *media, PurpleMediaState state,
 
769
                gchar *sid, gchar *name, PidginMedia *gtkmedia)
 
770
{
 
771
        purple_debug_info("gtkmedia", "state: %d sid: %s name: %s\n",
 
772
                        state, sid ? sid : "(null)", name ? name : "(null)");
 
773
        if (sid == NULL && name == NULL) {
 
774
                if (state == PURPLE_MEDIA_STATE_END) {
 
775
                        pidgin_media_emit_message(gtkmedia,
 
776
                                        _("The call has been terminated."));
 
777
                        gtk_widget_destroy(GTK_WIDGET(gtkmedia));
 
778
                }
 
779
        } else if (state == PURPLE_MEDIA_STATE_NEW &&
 
780
                        sid != NULL && name != NULL) {
 
781
                pidgin_media_ready_cb(media, gtkmedia, sid);
 
782
        }
 
783
}
 
784
 
 
785
static void
 
786
pidgin_media_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
 
787
                gchar *sid, gchar *name, gboolean local,
 
788
                PidginMedia *gtkmedia)
 
789
{
 
790
        if (type == PURPLE_MEDIA_INFO_REJECT) {
 
791
                pidgin_media_emit_message(gtkmedia,
 
792
                                _("You have rejected the call."));
 
793
        } else if (type == PURPLE_MEDIA_INFO_ACCEPT) {
 
794
                if (local == TRUE)
 
795
                        purple_request_close_with_handle(gtkmedia);
 
796
                pidgin_media_set_state(gtkmedia, PIDGIN_MEDIA_ACCEPTED);
 
797
                pidgin_media_emit_message(gtkmedia, _("Call in progress."));
 
798
                gtk_statusbar_push(GTK_STATUSBAR(gtkmedia->priv->statusbar),
 
799
                                0, _("Call in progress."));
 
800
                gtk_widget_show(GTK_WIDGET(gtkmedia));
 
801
        }
 
802
}
 
803
 
 
804
static void
 
805
pidgin_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 
806
{
 
807
        PidginMedia *media;
 
808
        g_return_if_fail(PIDGIN_IS_MEDIA(object));
 
809
 
 
810
        media = PIDGIN_MEDIA(object);
 
811
        switch (prop_id) {
 
812
                case PROP_MEDIA:
 
813
                {
 
814
                        if (media->priv->media)
 
815
                                g_object_unref(media->priv->media);
 
816
                        media->priv->media = g_value_get_object(value);
 
817
                        g_object_ref(media->priv->media);
 
818
 
 
819
                        if (purple_media_is_initiator(media->priv->media,
 
820
                                         NULL, NULL) == TRUE)
 
821
                                pidgin_media_set_state(media, PIDGIN_MEDIA_WAITING);
 
822
                        else
 
823
                                pidgin_media_set_state(media, PIDGIN_MEDIA_REQUESTED);
 
824
 
 
825
                        g_signal_connect(G_OBJECT(media->priv->media), "error",
 
826
                                G_CALLBACK(pidgin_media_error_cb), media);
 
827
                        g_signal_connect(G_OBJECT(media->priv->media), "state-changed",
 
828
                                G_CALLBACK(pidgin_media_state_changed_cb), media);
 
829
                        g_signal_connect(G_OBJECT(media->priv->media), "stream-info",
 
830
                                G_CALLBACK(pidgin_media_stream_info_cb), media);
 
831
                        break;
 
832
                }
 
833
                case PROP_SCREENNAME:
 
834
                        if (media->priv->screenname)
 
835
                                g_free(media->priv->screenname);
 
836
                        media->priv->screenname = g_value_dup_string(value);
 
837
                        break;
 
838
                default:
 
839
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
840
                        break;
 
841
        }
 
842
}
 
843
 
 
844
static void
 
845
pidgin_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 
846
{
 
847
        PidginMedia *media;
 
848
        g_return_if_fail(PIDGIN_IS_MEDIA(object));
 
849
 
 
850
        media = PIDGIN_MEDIA(object);
 
851
 
 
852
        switch (prop_id) {
 
853
                case PROP_MEDIA:
 
854
                        g_value_set_object(value, media->priv->media);
 
855
                        break;
 
856
                case PROP_SCREENNAME:
 
857
                        g_value_set_string(value, media->priv->screenname);
 
858
                        break;
 
859
                default:
 
860
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
861
                        break;
 
862
        }
 
863
}
 
864
 
 
865
static GtkWidget *
 
866
pidgin_media_new(PurpleMedia *media, const gchar *screenname)
 
867
{
 
868
        PidginMedia *gtkmedia = g_object_new(pidgin_media_get_type(),
 
869
                                             "media", media,
 
870
                                             "screenname", screenname, NULL);
 
871
        return GTK_WIDGET(gtkmedia);
 
872
}
 
873
 
 
874
static void
 
875
pidgin_media_set_state(PidginMedia *gtkmedia, PidginMediaState state)
 
876
{
 
877
        gtkmedia->priv->state = state;
 
878
}
 
879
 
 
880
static gboolean
 
881
pidgin_media_new_cb(PurpleMediaManager *manager, PurpleMedia *media,
 
882
                PurpleAccount *account, gchar *screenname, gpointer nul)
 
883
{
 
884
        PidginMedia *gtkmedia = PIDGIN_MEDIA(
 
885
                        pidgin_media_new(media, screenname));
 
886
        PurpleBuddy *buddy = purple_find_buddy(account, screenname);
 
887
        const gchar *alias = buddy ? 
 
888
                        purple_buddy_get_contact_alias(buddy) : screenname; 
 
889
        gtk_window_set_title(GTK_WINDOW(gtkmedia), alias);
 
890
 
 
891
        if (purple_media_is_initiator(media, NULL, NULL) == TRUE)
 
892
                gtk_widget_show(GTK_WIDGET(gtkmedia));
 
893
 
 
894
        return TRUE;
 
895
}
 
896
 
 
897
static GstElement *
 
898
create_default_video_src(PurpleMedia *media,
 
899
                const gchar *session_id, const gchar *participant)
 
900
{
 
901
        GstElement *sendbin, *src, *videoscale, *capsfilter;
 
902
        GstPad *pad;
 
903
        GstPad *ghost;
 
904
        GstCaps *caps;
 
905
 
 
906
#ifdef _WIN32
 
907
        /* autovideosrc doesn't pick ksvideosrc for some reason */
 
908
        src = gst_element_factory_make("ksvideosrc", NULL);
 
909
        if (src == NULL)
 
910
                src = gst_element_factory_make("dshowvideosrc", NULL);
 
911
        if (src == NULL)
 
912
                src = gst_element_factory_make("autovideosrc", NULL);
 
913
#else
 
914
        src = gst_element_factory_make("gconfvideosrc", NULL);
 
915
        if (src == NULL)
 
916
                src = gst_element_factory_make("autovideosrc", NULL);
 
917
        if (src == NULL)
 
918
                src = gst_element_factory_make("v4l2src", NULL);
 
919
        if (src == NULL)
 
920
                src = gst_element_factory_make("v4lsrc", NULL);
 
921
#endif
 
922
        if (src == NULL) {
 
923
                purple_debug_error("gtkmedia", "Unable to find a suitable "
 
924
                                "element for the default video source.\n");
 
925
                return NULL;
 
926
        }
 
927
 
 
928
        sendbin = gst_bin_new("pidgindefaultvideosrc");
 
929
        videoscale = gst_element_factory_make("videoscale", NULL);
 
930
        capsfilter = gst_element_factory_make("capsfilter", NULL);
 
931
 
 
932
        /* It was recommended to set the size <= 352x288 and framerate <= 20 */
 
933
        caps = gst_caps_from_string("video/x-raw-yuv , width=[250,352] , "
 
934
                        "height=[200,288] , framerate=[1/1,20/1]");
 
935
        g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
 
936
 
 
937
        gst_bin_add_many(GST_BIN(sendbin), src,
 
938
                        videoscale, capsfilter, NULL);
 
939
        gst_element_link_many(src, videoscale, capsfilter, NULL);
 
940
 
 
941
        pad = gst_element_get_static_pad(capsfilter, "src");
 
942
        ghost = gst_ghost_pad_new("ghostsrc", pad);
 
943
        gst_object_unref(pad);
 
944
        gst_element_add_pad(sendbin, ghost);
 
945
 
 
946
        return sendbin;
 
947
}
 
948
 
 
949
static GstElement *
 
950
create_default_video_sink(PurpleMedia *media,
 
951
                const gchar *session_id, const gchar *participant)
 
952
{
 
953
        GstElement *sink = gst_element_factory_make("gconfvideosink", NULL);
 
954
        if (sink == NULL)
 
955
                sink = gst_element_factory_make("autovideosink", NULL);
 
956
        if (sink == NULL)
 
957
                purple_debug_error("gtkmedia", "Unable to find a suitable "
 
958
                                "element for the default video sink.\n");
 
959
        return sink;
 
960
}
 
961
 
 
962
static GstElement *
 
963
create_default_audio_src(PurpleMedia *media,
 
964
                const gchar *session_id, const gchar *participant)
 
965
{
 
966
        GstElement *src;
 
967
        src = gst_element_factory_make("gconfaudiosrc", NULL);
 
968
        if (src == NULL)
 
969
                src = gst_element_factory_make("autoaudiosrc", NULL);
 
970
        if (src == NULL)
 
971
                src = gst_element_factory_make("alsasrc", NULL);
 
972
        if (src == NULL)
 
973
                src = gst_element_factory_make("osssrc", NULL);
 
974
        if (src == NULL)
 
975
                src = gst_element_factory_make("dshowaudiosrc", NULL);
 
976
        if (src == NULL) {
 
977
                purple_debug_error("gtkmedia", "Unable to find a suitable "
 
978
                                "element for the default audio source.\n");
 
979
                return NULL;
 
980
        }
 
981
        gst_element_set_name(src, "pidgindefaultaudiosrc");
 
982
        return src;
 
983
}
 
984
 
 
985
static GstElement *
 
986
create_default_audio_sink(PurpleMedia *media,
 
987
                const gchar *session_id, const gchar *participant)
 
988
{
 
989
        GstElement *sink;
 
990
        sink = gst_element_factory_make("gconfaudiosink", NULL);
 
991
        if (sink == NULL)
 
992
                sink = gst_element_factory_make("autoaudiosink",NULL);
 
993
        if (sink == NULL) {
 
994
                purple_debug_error("gtkmedia", "Unable to find a suitable "
 
995
                                "element for the default audio sink.\n");
 
996
                return NULL;
 
997
        }
 
998
        return sink;
 
999
}
 
1000
#endif  /* USE_VV */
 
1001
 
 
1002
void
 
1003
pidgin_medias_init(void)
 
1004
{
 
1005
#ifdef USE_VV
 
1006
        PurpleMediaManager *manager = purple_media_manager_get();
 
1007
        PurpleMediaElementInfo *default_video_src =
 
1008
                        g_object_new(PURPLE_TYPE_MEDIA_ELEMENT_INFO,
 
1009
                        "id", "pidgindefaultvideosrc",
 
1010
                        "name", "Pidgin Default Video Source",
 
1011
                        "type", PURPLE_MEDIA_ELEMENT_VIDEO
 
1012
                                        | PURPLE_MEDIA_ELEMENT_SRC
 
1013
                                        | PURPLE_MEDIA_ELEMENT_ONE_SRC
 
1014
                                        | PURPLE_MEDIA_ELEMENT_UNIQUE,
 
1015
                        "create-cb", create_default_video_src, NULL);
 
1016
        PurpleMediaElementInfo *default_video_sink =
 
1017
                        g_object_new(PURPLE_TYPE_MEDIA_ELEMENT_INFO,
 
1018
                        "id", "pidgindefaultvideosink",
 
1019
                        "name", "Pidgin Default Video Sink",
 
1020
                        "type", PURPLE_MEDIA_ELEMENT_VIDEO
 
1021
                                        | PURPLE_MEDIA_ELEMENT_SINK
 
1022
                                        | PURPLE_MEDIA_ELEMENT_ONE_SINK,
 
1023
                        "create-cb", create_default_video_sink, NULL);
 
1024
        PurpleMediaElementInfo *default_audio_src =
 
1025
                        g_object_new(PURPLE_TYPE_MEDIA_ELEMENT_INFO,
 
1026
                        "id", "pidgindefaultaudiosrc",
 
1027
                        "name", "Pidgin Default Audio Source",
 
1028
                        "type", PURPLE_MEDIA_ELEMENT_AUDIO
 
1029
                                        | PURPLE_MEDIA_ELEMENT_SRC
 
1030
                                        | PURPLE_MEDIA_ELEMENT_ONE_SRC
 
1031
                                        | PURPLE_MEDIA_ELEMENT_UNIQUE,
 
1032
                        "create-cb", create_default_audio_src, NULL);
 
1033
        PurpleMediaElementInfo *default_audio_sink =
 
1034
                        g_object_new(PURPLE_TYPE_MEDIA_ELEMENT_INFO,
 
1035
                        "id", "pidgindefaultaudiosink",
 
1036
                        "name", "Pidgin Default Audio Sink",
 
1037
                        "type", PURPLE_MEDIA_ELEMENT_AUDIO
 
1038
                                        | PURPLE_MEDIA_ELEMENT_SINK
 
1039
                                        | PURPLE_MEDIA_ELEMENT_ONE_SINK,
 
1040
                        "create-cb", create_default_audio_sink, NULL);
 
1041
 
 
1042
        g_signal_connect(G_OBJECT(manager), "init-media",
 
1043
                         G_CALLBACK(pidgin_media_new_cb), NULL);
 
1044
 
 
1045
        purple_media_manager_set_ui_caps(manager, 
 
1046
                        PURPLE_MEDIA_CAPS_AUDIO |
 
1047
                        PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION |
 
1048
                        PURPLE_MEDIA_CAPS_VIDEO |
 
1049
                        PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION |
 
1050
                        PURPLE_MEDIA_CAPS_AUDIO_VIDEO);
 
1051
 
 
1052
        purple_debug_info("gtkmedia", "Registering media element types\n");
 
1053
        purple_media_manager_set_active_element(manager, default_video_src);
 
1054
        purple_media_manager_set_active_element(manager, default_video_sink);
 
1055
        purple_media_manager_set_active_element(manager, default_audio_src);
 
1056
        purple_media_manager_set_active_element(manager, default_audio_sink);
 
1057
#endif
 
1058
}
 
1059