comparison src/protocols/oscar/oscar.c @ 2191:657dbe515608

[gaim-migrate @ 2201] genericize buddy icon stuff committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Wed, 29 Aug 2001 23:41:43 +0000
parents cdf43acb5b83
children 177397ceac57
comparison
equal deleted inserted replaced
2190:24d947eff811 2191:657dbe515608
24 #include <config.h> 24 #include <config.h>
25 #endif 25 #endif
26 26
27 27
28 #include <netdb.h> 28 #include <netdb.h>
29 #include <gtk/gtk.h>
30 #include <unistd.h> 29 #include <unistd.h>
31 #include <errno.h> 30 #include <errno.h>
32 #include <netinet/in.h> 31 #include <netinet/in.h>
33 #include <arpa/inet.h> 32 #include <arpa/inet.h>
34 #include <string.h> 33 #include <string.h>
41 #include "prpl.h" 40 #include "prpl.h"
42 #include "gaim.h" 41 #include "gaim.h"
43 #include "aim.h" 42 #include "aim.h"
44 #include "proxy.h" 43 #include "proxy.h"
45 44
46 #if USE_PIXBUF
47 #include <gdk-pixbuf/gdk-pixbuf.h>
48 #include <gdk-pixbuf/gdk-pixbuf-loader.h>
49 #define SCALE 48
50 #endif
51
52 /*#include "pixmaps/cancel.xpm"*/ 45 /*#include "pixmaps/cancel.xpm"*/
53 #include "pixmaps/admin_icon.xpm" 46 #include "pixmaps/admin_icon.xpm"
54 #include "pixmaps/aol_icon.xpm" 47 #include "pixmaps/aol_icon.xpm"
55 #include "pixmaps/away_icon.xpm" 48 #include "pixmaps/away_icon.xpm"
56 #include "pixmaps/dt_icon.xpm" 49 #include "pixmaps/dt_icon.xpm"
120 struct gaim_connection *gc; 113 struct gaim_connection *gc;
121 char *sn; 114 char *sn;
122 struct aim_directim_priv *priv; 115 struct aim_directim_priv *priv;
123 }; 116 };
124 117
125 #if USE_PIXBUF
126 struct icon_req { 118 struct icon_req {
127 char *user; 119 char *user;
128 time_t timestamp; 120 time_t timestamp;
129 unsigned long length; 121 unsigned long checksum;
130 gpointer data;
131 gboolean request; 122 gboolean request;
132 GdkPixbufAnimation *anim;
133 GdkPixbuf *unanim;
134 struct conversation *cnv;
135 GtkWidget *pix;
136 int curframe;
137 int timer;
138 }; 123 };
139 #endif
140 124
141 static struct direct_im *find_direct_im(struct oscar_data *od, char *who) { 125 static struct direct_im *find_direct_im(struct oscar_data *od, char *who) {
142 GSList *d = od->direct_ims; 126 GSList *d = od->direct_ims;
143 char *n = g_strdup(normalize(who)); 127 char *n = g_strdup(normalize(who));
144 struct direct_im *m = NULL; 128 struct direct_im *m = NULL;
475 g_free(n); 459 g_free(n);
476 } 460 }
477 #if USE_PIXBUF 461 #if USE_PIXBUF
478 while (odata->hasicons) { 462 while (odata->hasicons) {
479 struct icon_req *n = odata->hasicons->data; 463 struct icon_req *n = odata->hasicons->data;
480 if (n->anim)
481 gdk_pixbuf_animation_unref(n->anim);
482 if (n->unanim)
483 gdk_pixbuf_unref(n->unanim);
484 if (n->timer)
485 g_source_remove(n->timer);
486 if (n->cnv && n->pix)
487 gtk_container_remove(GTK_CONTAINER(n->cnv->bbox), n->pix);
488 g_free(n->user); 464 g_free(n->user);
489 if (n->data)
490 g_free(n->data);
491 odata->hasicons = g_slist_remove(odata->hasicons, n); 465 odata->hasicons = g_slist_remove(odata->hasicons, n);
492 g_free(n); 466 g_free(n);
493 } 467 }
494 #endif 468 #endif
495 if (gc->inpa > 0) 469 if (gc->inpa > 0)
1264 cancel_direct_im(w, d); 1238 cancel_direct_im(w, d);
1265 1239
1266 return TRUE; 1240 return TRUE;
1267 } 1241 }
1268 1242
1269 #if USE_PIXBUF
1270 static gboolean redraw_anim(gpointer data)
1271 {
1272 int delay;
1273 struct icon_req *ir = data;
1274 GList *frames;
1275 GdkPixbufFrame *frame;
1276 GdkPixbuf *buf;
1277 GdkPixbuf *scale;
1278 GdkPixmap *pm; GdkBitmap *bm;
1279 GdkPixmap *src;
1280 GdkGC *gc;
1281
1282 if (!ir->cnv || !g_list_find(conversations, ir->cnv)) {
1283 debug_printf("I think this is a bug.\n");
1284 return FALSE;
1285 }
1286
1287 frames = gdk_pixbuf_animation_get_frames(ir->anim);
1288 frame = g_list_nth_data(frames, ir->curframe);
1289 switch (gdk_pixbuf_frame_get_action(frame)) {
1290 case GDK_PIXBUF_FRAME_RETAIN:
1291 buf = gdk_pixbuf_frame_get_pixbuf(frame);
1292 scale = gdk_pixbuf_scale_simple(buf,
1293 MAX(gdk_pixbuf_get_width(buf) * SCALE /
1294 gdk_pixbuf_animation_get_width(ir->anim), 1),
1295 MAX(gdk_pixbuf_get_height(buf) * SCALE /
1296 gdk_pixbuf_animation_get_height(ir->anim), 1),
1297 GDK_INTERP_NEAREST);
1298 gdk_pixbuf_render_pixmap_and_mask(scale, &src, NULL, 0);
1299 gdk_pixbuf_unref(scale);
1300 gtk_pixmap_get(GTK_PIXMAP(ir->pix), &pm, &bm);
1301 gc = gdk_gc_new(pm);
1302 gdk_draw_pixmap(pm, gc, src, 0, 0,
1303 MAX(gdk_pixbuf_frame_get_x_offset(frame) * SCALE /
1304 gdk_pixbuf_animation_get_width(ir->anim), 1),
1305 MAX(gdk_pixbuf_frame_get_y_offset(frame) * SCALE /
1306 gdk_pixbuf_animation_get_height(ir->anim), 1),
1307 -1, -1);
1308 gdk_pixmap_unref(src);
1309 gtk_widget_queue_draw(ir->pix);
1310 gdk_gc_unref(gc);
1311 break;
1312 case GDK_PIXBUF_FRAME_DISPOSE:
1313 buf = gdk_pixbuf_frame_get_pixbuf(frame);
1314 scale = gdk_pixbuf_scale_simple(buf,
1315 MAX(gdk_pixbuf_get_width(buf) * SCALE /
1316 gdk_pixbuf_animation_get_width(ir->anim), 1),
1317 MAX(gdk_pixbuf_get_height(buf) * SCALE /
1318 gdk_pixbuf_animation_get_height(ir->anim), 1),
1319 GDK_INTERP_NEAREST);
1320 gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 0);
1321 gdk_pixbuf_unref(scale);
1322 gtk_pixmap_set(GTK_PIXMAP(ir->pix), pm, bm);
1323 gdk_pixmap_unref(pm);
1324 if (bm)
1325 gdk_bitmap_unref(bm);
1326 break;
1327 case GDK_PIXBUF_FRAME_REVERT:
1328 frame = frames->data;
1329 buf = gdk_pixbuf_frame_get_pixbuf(frame);
1330 scale = gdk_pixbuf_scale_simple(buf,
1331 MAX(gdk_pixbuf_get_width(buf) * SCALE /
1332 gdk_pixbuf_animation_get_width(ir->anim), 1),
1333 MAX(gdk_pixbuf_get_height(buf) * SCALE /
1334 gdk_pixbuf_animation_get_height(ir->anim), 1),
1335 GDK_INTERP_NEAREST);
1336 gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 0);
1337 gdk_pixbuf_unref(scale);
1338 gtk_pixmap_set(GTK_PIXMAP(ir->pix), pm, bm);
1339 gdk_pixmap_unref(pm);
1340 if (bm)
1341 gdk_bitmap_unref(bm);
1342 break;
1343 }
1344 ir->curframe = (ir->curframe + 1) % g_list_length(frames);
1345 delay = MAX(gdk_pixbuf_frame_get_delay_time(frame), 13);
1346 ir->timer = g_timeout_add(delay * 10, redraw_anim, ir);
1347 return FALSE;
1348 }
1349 #endif
1350
1351 int gaim_parse_incoming_im(struct aim_session_t *sess, 1243 int gaim_parse_incoming_im(struct aim_session_t *sess,
1352 struct command_rx_struct *command, ...) { 1244 struct command_rx_struct *command, ...) {
1353 int channel; 1245 int channel;
1354 struct aim_userinfo_s *userinfo; 1246 struct aim_userinfo_s *userinfo;
1355 va_list ap; 1247 va_list ap;
1365 struct aim_incomingim_ch1_args *args; 1257 struct aim_incomingim_ch1_args *args;
1366 1258
1367 args = va_arg(ap, struct aim_incomingim_ch1_args *); 1259 args = va_arg(ap, struct aim_incomingim_ch1_args *);
1368 va_end(ap); 1260 va_end(ap);
1369 1261
1370 #if USE_PIXBUF
1371 if (args->icbmflags & AIM_IMFLAGS_HASICON) { 1262 if (args->icbmflags & AIM_IMFLAGS_HASICON) {
1372 struct oscar_data *od = gc->proto_data; 1263 struct oscar_data *od = gc->proto_data;
1373 struct icon_req *ir = NULL; 1264 struct icon_req *ir = NULL;
1374 GSList *h = od->hasicons; 1265 GSList *h = od->hasicons;
1375 char *who = normalize(userinfo->sn); 1266 char *who = normalize(userinfo->sn);
1387 } 1278 }
1388 if (args->iconstamp > ir->timestamp) 1279 if (args->iconstamp > ir->timestamp)
1389 ir->request = TRUE; 1280 ir->request = TRUE;
1390 ir->timestamp = args->iconstamp; 1281 ir->timestamp = args->iconstamp;
1391 } 1282 }
1392 #endif
1393 1283
1394 /* 1284 /*
1395 * Quickly convert it to eight bit format, replacing 1285 * Quickly convert it to eight bit format, replacing
1396 * non-ASCII UNICODE characters with their equivelent 1286 * non-ASCII UNICODE characters with their equivelent
1397 * HTML entity. 1287 * HTML entity.
1432 g_free(name); 1322 g_free(name);
1433 } else if (args->reqclass & AIM_CAPS_SENDFILE) { 1323 } else if (args->reqclass & AIM_CAPS_SENDFILE) {
1434 } else if (args->reqclass & AIM_CAPS_GETFILE) { 1324 } else if (args->reqclass & AIM_CAPS_GETFILE) {
1435 } else if (args->reqclass & AIM_CAPS_VOICE) { 1325 } else if (args->reqclass & AIM_CAPS_VOICE) {
1436 } else if (args->reqclass & AIM_CAPS_BUDDYICON) { 1326 } else if (args->reqclass & AIM_CAPS_BUDDYICON) {
1437 #if USE_PIXBUF 1327 set_icon_data(gc, normalize(userinfo->sn), args->info.icon.icon,
1438 struct oscar_data *od = gc->proto_data; 1328 args->info.icon.length);
1439 GSList *h = od->hasicons;
1440 struct icon_req *ir = NULL;
1441 char *who;
1442 struct conversation *c;
1443
1444 GdkPixbufLoader *load;
1445 GList *frames;
1446 GdkPixbuf *buf;
1447 GdkPixbuf *scale;
1448 GdkPixmap *pm;
1449 GdkBitmap *bm;
1450
1451 who = normalize(userinfo->sn);
1452
1453 while (h) {
1454 ir = h->data;
1455 if (!strcmp(who, ir->user))
1456 break;
1457 h = h->next;
1458
1459 }
1460
1461 if (!h || ((c = find_conversation(userinfo->sn)) == NULL) || (c->gc != gc)) {
1462 debug_printf("got buddy icon for %s but didn't want it\n", userinfo->sn);
1463 return 1;
1464 }
1465
1466 if (ir->pix && ir->cnv)
1467 gtk_container_remove(GTK_CONTAINER(ir->cnv->bbox), ir->pix);
1468 ir->pix = NULL;
1469 ir->cnv = NULL;
1470 if (ir->data)
1471 g_free(ir->data);
1472 if (ir->anim)
1473 gdk_pixbuf_animation_unref(ir->anim);
1474 ir->anim = NULL;
1475 if (ir->unanim)
1476 gdk_pixbuf_unref(ir->unanim);
1477 ir->unanim = NULL;
1478 if (ir->timer)
1479 g_source_remove(ir->timer);
1480 ir->timer = 0;
1481
1482 ir->length = args->info.icon.length;
1483
1484 if (!ir->length)
1485 return 1;
1486
1487 ir->data = g_memdup(args->info.icon.icon, args->info.icon.length);
1488
1489 load = gdk_pixbuf_loader_new();
1490 gdk_pixbuf_loader_write(load, ir->data, ir->length);
1491 ir->anim = gdk_pixbuf_loader_get_animation(load);
1492
1493 if (ir->anim) {
1494 frames = gdk_pixbuf_animation_get_frames(ir->anim);
1495 buf = gdk_pixbuf_frame_get_pixbuf(frames->data);
1496 scale = gdk_pixbuf_scale_simple(buf,
1497 MAX(gdk_pixbuf_get_width(buf) * SCALE /
1498 gdk_pixbuf_animation_get_width(ir->anim), 1),
1499 MAX(gdk_pixbuf_get_height(buf) * SCALE /
1500 gdk_pixbuf_animation_get_height(ir->anim), 1),
1501 GDK_INTERP_NEAREST);
1502 gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 0);
1503 gdk_pixbuf_unref(scale);
1504
1505 if (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1) {
1506 int delay =
1507 MAX(gdk_pixbuf_frame_get_delay_time(frames->data), 13);
1508 ir->curframe = 1;
1509 ir->timer = g_timeout_add(delay * 10, redraw_anim, ir);
1510 }
1511 } else {
1512 ir->unanim = gdk_pixbuf_loader_get_pixbuf(load);
1513 if (!ir->unanim) {
1514 gdk_pixbuf_loader_close(load);
1515 return 1;
1516 }
1517 scale = gdk_pixbuf_scale_simple(ir->unanim, SCALE, SCALE,
1518 GDK_INTERP_NEAREST);
1519 gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 0);
1520 gdk_pixbuf_unref(scale);
1521 }
1522
1523 ir->cnv = c;
1524 ir->pix = gtk_pixmap_new(pm, bm);
1525 gtk_box_pack_start(GTK_BOX(c->bbox), ir->pix, FALSE, FALSE, 5);
1526 if (ir->anim && (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1))
1527 gtk_widget_set_usize(ir->pix, SCALE, SCALE);
1528 gtk_widget_show(ir->pix);
1529 gdk_pixmap_unref(pm);
1530 if (bm)
1531 gdk_bitmap_unref(bm);
1532
1533 gdk_pixbuf_loader_close(load);
1534
1535 #endif
1536 } else if (args->reqclass & AIM_CAPS_IMIMAGE) { 1329 } else if (args->reqclass & AIM_CAPS_IMIMAGE) {
1537 struct ask_direct *d = g_new0(struct ask_direct, 1); 1330 struct ask_direct *d = g_new0(struct ask_direct, 1);
1538 char buf[256]; 1331 char buf[256];
1539 1332
1540 debug_printf("%s received direct im request from %s (%s)\n", 1333 debug_printf("%s received direct im request from %s (%s)\n",
2883 aim_auth_changepasswd(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH), 2676 aim_auth_changepasswd(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH),
2884 new, old); 2677 new, old);
2885 } 2678 }
2886 } 2679 }
2887 2680
2888 static void oscar_insert_convo(struct gaim_connection *gc, struct conversation *c)
2889 {
2890 #if USE_PIXBUF
2891 struct oscar_data *od = gc->proto_data;
2892 GSList *h = od->hasicons;
2893 struct icon_req *ir = NULL;
2894 char *who = normalize(c->name);
2895
2896 GdkPixbufLoader *load;
2897 GList *frames;
2898 GdkPixbuf *buf;
2899 GdkPixbuf *scale;
2900 GdkPixmap *pm;
2901 GdkBitmap *bm;
2902
2903 while (h) {
2904 ir = h->data;
2905 if (!strcmp(who, ir->user))
2906 break;
2907 h = h->next;
2908 }
2909 if (!h || !ir->data)
2910 return;
2911
2912 ir->cnv = c;
2913
2914 load = gdk_pixbuf_loader_new();
2915 gdk_pixbuf_loader_write(load, ir->data, ir->length);
2916 ir->anim = gdk_pixbuf_loader_get_animation(load);
2917
2918 if (ir->anim) {
2919 frames = gdk_pixbuf_animation_get_frames(ir->anim);
2920 buf = gdk_pixbuf_frame_get_pixbuf(frames->data);
2921 scale = gdk_pixbuf_scale_simple(buf,
2922 MAX(gdk_pixbuf_get_width(buf) * SCALE /
2923 gdk_pixbuf_animation_get_width(ir->anim), 1),
2924 MAX(gdk_pixbuf_get_height(buf) * SCALE /
2925 gdk_pixbuf_animation_get_height(ir->anim), 1),
2926 GDK_INTERP_NEAREST);
2927 gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 0);
2928 gdk_pixbuf_unref(scale);
2929
2930 if (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1) {
2931 int delay = MAX(gdk_pixbuf_frame_get_delay_time(frames->data), 13);
2932 ir->curframe = 1;
2933 ir->timer = g_timeout_add(delay * 10, redraw_anim, ir);
2934 }
2935 } else {
2936 ir->unanim = gdk_pixbuf_loader_get_pixbuf(load);
2937 if (!ir->unanim) {
2938 gdk_pixbuf_loader_close(load);
2939 return;
2940 }
2941 scale = gdk_pixbuf_scale_simple(ir->unanim, SCALE, SCALE,
2942 GDK_INTERP_NEAREST);
2943 gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 0);
2944 gdk_pixbuf_unref(scale);
2945 }
2946
2947 ir->pix = gtk_pixmap_new(pm, bm);
2948 gtk_box_pack_start(GTK_BOX(c->bbox), ir->pix, FALSE, FALSE, 5);
2949 if (ir->anim && (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1))
2950 gtk_widget_set_usize(ir->pix, gdk_pixbuf_animation_get_width(ir->anim),
2951 gdk_pixbuf_animation_get_height(ir->anim));
2952 gtk_widget_show(ir->pix);
2953 gdk_pixmap_unref(pm);
2954 if (bm)
2955 gdk_bitmap_unref(bm);
2956
2957 gdk_pixbuf_loader_close(load);
2958 #endif
2959 }
2960
2961 static void oscar_remove_convo(struct gaim_connection *gc, struct conversation *c)
2962 {
2963 #if USE_PIXBUF
2964 struct oscar_data *od = gc->proto_data;
2965 GSList *h = od->hasicons;
2966 struct icon_req *ir = NULL;
2967 char *who = normalize(c->name);
2968
2969 while (h) {
2970 ir = h->data;
2971 if (!strcmp(who, ir->user))
2972 break;
2973 h = h->next;
2974 }
2975 if (!h || !ir->data)
2976 return;
2977
2978 if (ir->cnv && ir->pix) {
2979 gtk_container_remove(GTK_CONTAINER(ir->cnv->bbox), ir->pix);
2980 ir->pix = NULL;
2981 ir->cnv = NULL;
2982 }
2983
2984 if (ir->anim) {
2985 gdk_pixbuf_animation_unref(ir->anim);
2986 ir->anim = NULL;
2987 } else if (ir->unanim) {
2988 gdk_pixbuf_unref(ir->unanim);
2989 ir->unanim = NULL;
2990 }
2991
2992 ir->curframe = 0;
2993
2994 if (ir->timer)
2995 g_source_remove(ir->timer);
2996 ir->timer = 0;
2997 #endif
2998 }
2999
3000 static struct prpl *my_protocol = NULL; 2681 static struct prpl *my_protocol = NULL;
3001 2682
3002 void oscar_init(struct prpl *ret) { 2683 void oscar_init(struct prpl *ret) {
3003 ret->protocol = PROTO_OSCAR; 2684 ret->protocol = PROTO_OSCAR;
3004 ret->options = OPT_PROTO_HTML | OPT_PROTO_CORRECT_TIME; 2685 ret->options = OPT_PROTO_HTML | OPT_PROTO_CORRECT_TIME;
3009 ret->do_action = oscar_do_action; 2690 ret->do_action = oscar_do_action;
3010 ret->buddy_menu = oscar_buddy_menu; 2691 ret->buddy_menu = oscar_buddy_menu;
3011 ret->user_opts = oscar_user_opts; 2692 ret->user_opts = oscar_user_opts;
3012 ret->draw_new_user = oscar_draw_new_user; 2693 ret->draw_new_user = oscar_draw_new_user;
3013 ret->do_new_user = oscar_do_new_user; 2694 ret->do_new_user = oscar_do_new_user;
3014 ret->insert_convo = oscar_insert_convo;
3015 ret->remove_convo = oscar_remove_convo;
3016 ret->login = oscar_login; 2695 ret->login = oscar_login;
3017 ret->close = oscar_close; 2696 ret->close = oscar_close;
3018 ret->send_im = oscar_send_im; 2697 ret->send_im = oscar_send_im;
3019 ret->set_info = oscar_set_info; 2698 ret->set_info = oscar_set_info;
3020 ret->get_info = oscar_get_info; 2699 ret->get_info = oscar_get_info;