| 1 | #include "iface.h" |
|---|
| 2 | |
|---|
| 3 | #include <licq_icqd.h> |
|---|
| 4 | #include <licq_translate.h> |
|---|
| 5 | |
|---|
| 6 | #include "conf.h" |
|---|
| 7 | |
|---|
| 8 | using namespace std; |
|---|
| 9 | |
|---|
| 10 | Iface::Iface() |
|---|
| 11 | { |
|---|
| 12 | g_type_init(); |
|---|
| 13 | |
|---|
| 14 | aosd = aosd_new(); |
|---|
| 15 | aosd_set_transparency(aosd, TRANSPARENCY_COMPOSITE); |
|---|
| 16 | aosd_set_renderer(aosd, aosd_text_renderer, &trd); |
|---|
| 17 | aosd_set_names(aosd, "OSD Plugin", "Licq"); |
|---|
| 18 | |
|---|
| 19 | memset(&trd, 0, sizeof(TextRenderData)); |
|---|
| 20 | trd.lay = pango_layout_new_aosd(); |
|---|
| 21 | pango_layout_set_wrap(trd.lay, PANGO_WRAP_WORD_CHAR); |
|---|
| 22 | |
|---|
| 23 | conf = new Conf(); |
|---|
| 24 | |
|---|
| 25 | updateTextRenderData(); |
|---|
| 26 | |
|---|
| 27 | FOR_EACH_OWNER_START(LOCK_R) |
|---|
| 28 | { |
|---|
| 29 | ppidTimers[pOwner->PPID()] = time(NULL); |
|---|
| 30 | } |
|---|
| 31 | FOR_EACH_OWNER_END; |
|---|
| 32 | |
|---|
| 33 | string init = "Licq newosd plugin is initialized."; |
|---|
| 34 | displayLayout(init, false); |
|---|
| 35 | } |
|---|
| 36 | |
|---|
| 37 | Iface::~Iface() |
|---|
| 38 | { |
|---|
| 39 | delete conf; |
|---|
| 40 | ppidTimers.clear(); |
|---|
| 41 | aosd_destroy(aosd); |
|---|
| 42 | pango_layout_unref_aosd(trd.lay); |
|---|
| 43 | } |
|---|
| 44 | |
|---|
| 45 | void Iface::processSignal(CICQSignal* sig) |
|---|
| 46 | { |
|---|
| 47 | string msg = ""; |
|---|
| 48 | bool control = true; |
|---|
| 49 | |
|---|
| 50 | switch (sig->Signal()) |
|---|
| 51 | { |
|---|
| 52 | case SIGNAL_UPDATExUSER: |
|---|
| 53 | { |
|---|
| 54 | if (filterSignal(sig)) |
|---|
| 55 | break; |
|---|
| 56 | |
|---|
| 57 | ICQUser* u = gUserManager.FetchUser(sig->Id(), sig->PPID(), LOCK_R); |
|---|
| 58 | if (u == NULL) |
|---|
| 59 | break; |
|---|
| 60 | |
|---|
| 61 | msg = u->GetAlias(); |
|---|
| 62 | |
|---|
| 63 | switch (sig->SubSignal()) |
|---|
| 64 | { |
|---|
| 65 | case USER_STATUS: |
|---|
| 66 | msg += " changed status to: "; |
|---|
| 67 | msg += u->StatusStr(); |
|---|
| 68 | if (sig->Argument() > 0) |
|---|
| 69 | msg += " [logged on]"; |
|---|
| 70 | break; |
|---|
| 71 | |
|---|
| 72 | case USER_EVENTS: |
|---|
| 73 | if (sig->Argument() == 0) |
|---|
| 74 | { |
|---|
| 75 | msg += " checked your auto-response"; |
|---|
| 76 | break; |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | control = false; |
|---|
| 80 | |
|---|
| 81 | if (conf->notifyOnly) |
|---|
| 82 | { |
|---|
| 83 | msg = "Message from "; |
|---|
| 84 | msg += u->GetAlias(); |
|---|
| 85 | if (conf->markSecure && u->Secure()) |
|---|
| 86 | msg += " [secured]"; |
|---|
| 87 | msg += "."; |
|---|
| 88 | } |
|---|
| 89 | else |
|---|
| 90 | { |
|---|
| 91 | CUserEvent* ue = u->EventPeekId(sig->Argument()); |
|---|
| 92 | if (ue == NULL) |
|---|
| 93 | { |
|---|
| 94 | msg.clear(); |
|---|
| 95 | break; |
|---|
| 96 | } |
|---|
| 97 | if (conf->markSecure && u->Secure()) |
|---|
| 98 | msg += " (S)"; |
|---|
| 99 | msg += ": "; |
|---|
| 100 | char* trans = gTranslator.ToUnicode(const_cast<char*>(ue->Text()), |
|---|
| 101 | u->UserEncoding()); |
|---|
| 102 | msg += trans; |
|---|
| 103 | delete[] trans; |
|---|
| 104 | } |
|---|
| 105 | break; |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | gUserManager.DropUser(u); |
|---|
| 109 | break; |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | case SIGNAL_LOGON: |
|---|
| 113 | case SIGNAL_LOGOFF: |
|---|
| 114 | ppidTimers[sig->PPID()] = time(NULL) + conf->quietTimeout; |
|---|
| 115 | break; |
|---|
| 116 | } |
|---|
| 117 | |
|---|
| 118 | if (!msg.empty()) |
|---|
| 119 | displayLayout(msg, control); |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | void Iface::updateTextRenderData() |
|---|
| 123 | { |
|---|
| 124 | conf->loadConfig(); |
|---|
| 125 | |
|---|
| 126 | aosd_set_hide_upon_mouse_event(aosd, conf->mouseActive); |
|---|
| 127 | pango_layout_set_font_aosd(trd.lay, conf->font); |
|---|
| 128 | |
|---|
| 129 | trd.geom.x_offset = conf->marginHorizontal; |
|---|
| 130 | trd.geom.y_offset = conf->marginVertical; |
|---|
| 131 | |
|---|
| 132 | trd.back.color = conf->backColor; |
|---|
| 133 | trd.back.opacity = conf->backOpacity; |
|---|
| 134 | |
|---|
| 135 | trd.shadow.x_offset = conf->shadowOffset; |
|---|
| 136 | trd.shadow.y_offset = conf->shadowOffset; |
|---|
| 137 | trd.shadow.color = conf->shadowColor; |
|---|
| 138 | trd.shadow.opacity = conf->shadowOpacity; |
|---|
| 139 | |
|---|
| 140 | trd.fore.opacity = conf->textOpacity; |
|---|
| 141 | |
|---|
| 142 | int width = aosd_text_get_screen_wrap_width(aosd, &trd); |
|---|
| 143 | if (conf->wrapWidth == 0 || width < 0) |
|---|
| 144 | pango_layout_set_width(trd.lay, -1); |
|---|
| 145 | else |
|---|
| 146 | pango_layout_set_width(trd.lay, |
|---|
| 147 | (width > conf->wrapWidth ? conf->wrapWidth : width) * PANGO_SCALE); |
|---|
| 148 | } |
|---|
| 149 | |
|---|
| 150 | bool Iface::filterSignal(CICQSignal* sig) |
|---|
| 151 | { |
|---|
| 152 | switch (sig->SubSignal()) |
|---|
| 153 | { |
|---|
| 154 | case USER_STATUS: |
|---|
| 155 | case USER_EVENTS: |
|---|
| 156 | break; |
|---|
| 157 | |
|---|
| 158 | default: |
|---|
| 159 | return true; |
|---|
| 160 | } |
|---|
| 161 | |
|---|
| 162 | bool isMessage = (sig->SubSignal() == USER_EVENTS && sig->Argument() > 0); |
|---|
| 163 | |
|---|
| 164 | if (!isMessage && (ppidTimers[sig->PPID()] > time(NULL))) |
|---|
| 165 | return true; |
|---|
| 166 | |
|---|
| 167 | ICQOwner* o = gUserManager.FetchOwner(sig->PPID(), LOCK_R); |
|---|
| 168 | if (o == NULL) |
|---|
| 169 | return true; |
|---|
| 170 | |
|---|
| 171 | bool isOwner = (strcmp(o->IdString(), sig->Id()) == 0); |
|---|
| 172 | unsigned short ourStatus = o->Status(); |
|---|
| 173 | |
|---|
| 174 | gUserManager.DropOwner(o); |
|---|
| 175 | |
|---|
| 176 | // TODO status check |
|---|
| 177 | |
|---|
| 178 | if (isOwner) |
|---|
| 179 | { |
|---|
| 180 | if (isMessage && conf->showMessage != GROUP_TYPE_NONE) |
|---|
| 181 | return false; |
|---|
| 182 | |
|---|
| 183 | return true; |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | ICQUser* u = gUserManager.FetchUser(sig->Id(), sig->PPID(), LOCK_R); |
|---|
| 187 | if (u == NULL) |
|---|
| 188 | return true; |
|---|
| 189 | |
|---|
| 190 | bool ign = u->IgnoreList(); |
|---|
| 191 | bool on = u->OnlineNotify(); |
|---|
| 192 | |
|---|
| 193 | gUserManager.DropUser(u); |
|---|
| 194 | |
|---|
| 195 | if (ign) |
|---|
| 196 | return true; |
|---|
| 197 | |
|---|
| 198 | #define GROUP_DISABLED(type) \ |
|---|
| 199 | (conf->type == GROUP_TYPE_NONE || \ |
|---|
| 200 | (conf->type == GROUP_TYPE_ONLINE_NOTIFY && !on)) |
|---|
| 201 | |
|---|
| 202 | if (sig->SubSignal() == USER_STATUS) |
|---|
| 203 | { |
|---|
| 204 | if (sig->Argument() == 0 && GROUP_DISABLED(statusChange)) |
|---|
| 205 | return true; |
|---|
| 206 | |
|---|
| 207 | if (GROUP_DISABLED(logonLogoff)) |
|---|
| 208 | return true; |
|---|
| 209 | } |
|---|
| 210 | |
|---|
| 211 | if (sig->SubSignal() == USER_EVENTS) |
|---|
| 212 | { |
|---|
| 213 | if (sig->Argument() < 0) |
|---|
| 214 | return true; |
|---|
| 215 | |
|---|
| 216 | if (sig->Argument() == 0 && GROUP_DISABLED(autoResponse)) |
|---|
| 217 | return true; |
|---|
| 218 | |
|---|
| 219 | if (GROUP_DISABLED(showMessage)) |
|---|
| 220 | return true; |
|---|
| 221 | } |
|---|
| 222 | #undef GROUP_DISABLED |
|---|
| 223 | |
|---|
| 224 | return false; |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | void Iface::displayLayout(string& msg, bool control) |
|---|
| 228 | { |
|---|
| 229 | trd.fore.color = control ? conf->textControlColor : conf->textColor; |
|---|
| 230 | |
|---|
| 231 | pango_layout_set_text(trd.lay, const_cast<char*>(msg.c_str()), -1); |
|---|
| 232 | |
|---|
| 233 | if (conf->maxLines != 0 && |
|---|
| 234 | pango_layout_get_line_count(trd.lay) > conf->maxLines) |
|---|
| 235 | { |
|---|
| 236 | PangoLayoutLine* line = |
|---|
| 237 | pango_layout_get_line_readonly(trd.lay, conf->maxLines); |
|---|
| 238 | pango_layout_set_text(trd.lay, const_cast<char*>(msg.c_str()), |
|---|
| 239 | line->start_index); |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | unsigned width, height; |
|---|
| 243 | |
|---|
| 244 | aosd_text_get_size(&trd, &width, &height); |
|---|
| 245 | |
|---|
| 246 | aosd_set_position_with_offset(aosd, |
|---|
| 247 | conf->posHorizontal, conf->posVertical, |
|---|
| 248 | width, height, conf->offsetHorizontal, conf->offsetVertical); |
|---|
| 249 | |
|---|
| 250 | // TODO implement non-waiting mechanism |
|---|
| 251 | |
|---|
| 252 | aosd_flash(aosd, conf->fadeIn, |
|---|
| 253 | conf->fadeFull + msg.size() * conf->delayPerChar, conf->fadeOut); |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | /* vim: set ts=2 sw=2 et : */ |
|---|