1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
using Gdk;
using Gee;
using Xmpp;
using Dino.Entities;
namespace Dino {
public class AvatarManager : StreamInteractionModule, Object {
public static ModuleIdentity<AvatarManager> IDENTITY = new ModuleIdentity<AvatarManager>("avatar_manager");
public string id { get { return IDENTITY.id; } }
public signal void received_avatar(Pixbuf avatar, Jid jid, Account account);
private enum Source {
USER_AVATARS,
VCARD
}
private StreamInteractor stream_interactor;
private Database db;
private HashMap<Jid, string> user_avatars = new HashMap<Jid, string>(Jid.hash_func, Jid.equals_func);
private HashMap<Jid, string> vcard_avatars = new HashMap<Jid, string>(Jid.hash_func, Jid.equals_func);
private AvatarStorage avatar_storage = new AvatarStorage(get_storage_dir());
private const int MAX_PIXEL = 192;
public static void start(StreamInteractor stream_interactor, Database db) {
AvatarManager m = new AvatarManager(stream_interactor, db);
stream_interactor.add_module(m);
}
public static string get_storage_dir() {
return Path.build_filename(Application.get_storage_dir(), "avatars");
}
private AvatarManager(StreamInteractor stream_interactor, Database db) {
this.stream_interactor = stream_interactor;
this.db = db;
stream_interactor.account_added.connect(on_account_added);
stream_interactor.module_manager.initialize_account_modules.connect(initialize_avatar_modules);
}
private void initialize_avatar_modules(Account account, ArrayList<Core.XmppStreamModule> modules) {
modules.add(new Xep.UserAvatars.Module(avatar_storage));
modules.add(new Xep.VCard.Module(avatar_storage));
}
public Pixbuf? get_avatar(Account account, Jid jid) {
Jid jid_ = jid;
if (!stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid, account)) {
jid_ = jid.bare_jid;
}
string? user_avatars_id = user_avatars[jid_];
if (user_avatars_id != null) {
return avatar_storage.get_image(user_avatars_id);
}
string? vcard_avatars_id = vcard_avatars[jid_];
if (vcard_avatars_id != null) {
return avatar_storage.get_image(vcard_avatars_id);
}
return null;
}
public void publish(Account account, string file) {
try {
Pixbuf pixbuf = new Pixbuf.from_file(file);
if (pixbuf.width >= pixbuf.height && pixbuf.width > MAX_PIXEL) {
int dest_height = (int) ((float) MAX_PIXEL / pixbuf.width * pixbuf.height);
pixbuf = pixbuf.scale_simple(MAX_PIXEL, dest_height, InterpType.BILINEAR);
} else if (pixbuf.height > pixbuf.width && pixbuf.width > MAX_PIXEL) {
int dest_width = (int) ((float) MAX_PIXEL / pixbuf.height * pixbuf.width);
pixbuf = pixbuf.scale_simple(dest_width, MAX_PIXEL, InterpType.BILINEAR);
}
uint8[] buffer;
pixbuf.save_to_buffer(out buffer, "png");
Core.XmppStream stream = stream_interactor.get_stream(account);
if (stream != null) {
stream.get_module(Xep.UserAvatars.Module.IDENTITY).publish_png(stream, buffer, pixbuf.width, pixbuf.height);
on_user_avatar_received(account, account.bare_jid, Base64.encode(buffer));
}
} catch (Error e) {
print("error " + e.message + "\n");
}
}
private void on_account_added(Account account) {
stream_interactor.module_manager.get_module(account, Xep.UserAvatars.Module.IDENTITY).received_avatar.connect((stream, jid, id) =>
on_user_avatar_received(account, new Jid(jid), id)
);
stream_interactor.module_manager.get_module(account, Xep.VCard.Module.IDENTITY).received_avatar.connect((stream, jid, id) =>
on_vcard_avatar_received(account, new Jid(jid), id)
);
user_avatars = db.get_avatar_hashes(Source.USER_AVATARS);
foreach (Jid jid in user_avatars.keys) {
on_user_avatar_received(account, jid, user_avatars[jid]);
}
vcard_avatars = db.get_avatar_hashes(Source.VCARD);
foreach (Jid jid in vcard_avatars.keys) {
on_vcard_avatar_received(account, jid, vcard_avatars[jid]);
}
}
private void on_user_avatar_received(Account account, Jid jid, string id) {
if (!user_avatars.has_key(jid) || user_avatars[jid] != id) {
user_avatars[jid] = id;
db.set_avatar_hash(jid, id, Source.USER_AVATARS);
}
Pixbuf? avatar = avatar_storage.get_image(id);
if (avatar != null) {
received_avatar(avatar, jid, account);
}
}
private void on_vcard_avatar_received(Account account, Jid jid, string id) {
if (!vcard_avatars.has_key(jid) || vcard_avatars[jid] != id) {
vcard_avatars[jid] = id;
if (!jid.is_full()) { // don't save muc avatars
db.set_avatar_hash(jid, id, Source.VCARD);
}
}
Pixbuf? avatar = avatar_storage.get_image(id);
if (avatar != null) {
received_avatar(avatar, jid, account);
}
}
}
}
|