void friend_add(char_t *name, STRING_IDX length, char_t *msg, STRING_IDX msg_length) { if(!length) { addfriend_status = ADDF_NONAME; return; } #ifdef EMOJI_IDS uint8_t emo_id[TOX_FRIEND_ADDRESS_SIZE]; if (emoji_string_to_bytes(emo_id, TOX_FRIEND_ADDRESS_SIZE, name, length) == TOX_FRIEND_ADDRESS_SIZE) { friend_addid(emo_id, msg, msg_length); } #endif uint8_t name_cleaned[length]; uint16_t length_cleaned = 0; unsigned int i; for (i = 0; i < length; ++i) { if (name[i] != ' ') { name_cleaned[length_cleaned] = name[i]; ++length_cleaned; } } if(!length_cleaned) { addfriend_status = ADDF_NONAME; return; } uint8_t id[TOX_FRIEND_ADDRESS_SIZE]; if(length_cleaned == TOX_FRIEND_ADDRESS_SIZE * 2 && string_to_id(id, name_cleaned)) { friend_addid(id, msg, msg_length); } else { /* not a regular id, try DNS discovery */ addfriend_status = ADDF_DISCOVER; dns_request(name_cleaned, length_cleaned); } }
void friend_add(char_t *name, STRING_IDX length, char_t *msg, STRING_IDX msg_length) { if(!length) { addfriend_status = ADDF_NONAME; return; } uint8_t id[TOX_FRIEND_ADDRESS_SIZE]; if(length == TOX_FRIEND_ADDRESS_SIZE * 2 && string_to_id(id, name)) { friend_addid(id, msg, msg_length); } else { /* not a regular id, try DNS discovery */ addfriend_status = ADDF_DISCOVER; dns_request(name, length); } }
void tox_message(uint8_t tox_message_id, uint16_t param1, uint16_t param2, void *data) { switch(tox_message_id) { case DHT_CONNECTED: { /* param1: connection status (1 = connected, 0 = disconnected) */ tox_connected = param1; redraw(); break; } case DNS_RESULT: { /* param1: result (0 = failure, 1 = success) * data: resolved tox id (if successful) */ if(param1) { friend_addid(data, edit_addmsg.data, edit_addmsg.length); } else { addfriend_status = ADDF_BADNAME; } free(data); redraw(); break; } case OPEN_FILES: { tox_postmessage(TOX_SENDFILES, param1, param2, data); break; } case SAVE_FILE: { tox_postmessage(TOX_ACCEPTFILE, param1, param2, data); break; } case NEW_AUDIO_IN_DEVICE: { if(UI_STRING_ID_INVALID == param1) { list_dropdown_add_hardcoded(&dropdown_audio_in, data, data); } else { list_dropdown_add_localized(&dropdown_audio_in, param1, data); } if (loaded_audio_in_device != 0 && (dropdown_audio_in.dropcount - 1) == loaded_audio_in_device) { toxaudio_postmessage(AUDIO_SET_INPUT, 0, 0, data); dropdown_audio_in.selected = loaded_audio_in_device; loaded_audio_in_device = 0; } break; } case NEW_AUDIO_OUT_DEVICE: { list_dropdown_add_hardcoded(&dropdown_audio_out, data, data); if (loaded_audio_out_device != 0 && (dropdown_audio_out.dropcount - 1) == loaded_audio_out_device) { toxaudio_postmessage(AUDIO_SET_OUTPUT, 0, 0, data); dropdown_audio_out.selected = loaded_audio_out_device; loaded_audio_out_device = 0; } break; } case NEW_VIDEO_DEVICE: { if(UI_STRING_ID_INVALID == param1) { // Device name is a hardcoded string. // data is a pointer to a buffer, that contains device handle pointer, // followed by device name string. list_dropdown_add_hardcoded(&dropdown_video, data + sizeof(void*), *(void**)data); } else { // Device name is localized with param1 containing UI_STRING_ID. // data is device handle pointer. list_dropdown_add_localized(&dropdown_video, param1, data); } //param2 == true, if this device will be chosen by video detecting code. if(param2) { dropdown_video.selected = dropdown_video.over = (dropdown_video.dropcount - 1); } break; } case FRIEND_REQUEST: { /* data: pointer to FRIENDREQ structure */ list_addfriendreq(data); break; } case FRIEND_ADD: { /* confirmation that friend has been added to friend list (add) */ if(param1) { /* friend was not added */ addfriend_status = param2; } else { /* friend was added */ edit_addid.length = 0; edit_addmsg.length = 0; FRIEND *f = &friend[param2]; friends++; f->msg.scroll = 1.0; memcpy(f->cid, data, sizeof(f->cid)); friend_setname(f, NULL, 0); list_addfriend(f); addfriend_status = ADDF_SENT; } free(data); redraw(); break; } case FRIEND_ACCEPT: { /* confirmation that friend has been added to friend list (accept) */ if(!param1) { FRIEND *f = &friend[param2]; FRIENDREQ *req = data; friends++; memcpy(f->cid, req->id, sizeof(f->cid)); friend_setname(f, NULL, 0); list_addfriend2(f, req); redraw(); } free(data); break; } case FRIEND_DEL: { friend_free(data); friends--; break; } case FRIEND_MESSAGE: { friend_addmessage(&friend[param1], data); redraw(); break; } #define updatefriend(fp) redraw();//list_draw(); if(sitem && fp == sitem->data) {ui_drawmain();} #define updategroup(gp) redraw();//list_draw(); if(sitem && gp == sitem->data) {ui_drawmain();} case FRIEND_NAME: { FRIEND *f = &friend[param1]; friend_setname(f, data, param2); updatefriend(f); break; } case FRIEND_STATUS_MESSAGE: { FRIEND *f = &friend[param1]; free(f->status_message); f->status_length = param2; f->status_message = data; updatefriend(f); break; } case FRIEND_STATUS: { FRIEND *f = &friend[param1]; f->status = param2; updatefriend(f); break; } case FRIEND_TYPING: { FRIEND *f = &friend[param1]; friend_set_typing(f, param2); updatefriend(f); break; } case FRIEND_ONLINE: { FRIEND *f = &friend[param1]; f->online = param2; if(!f->online) { friend_set_typing(f, 0); } updatefriend(f); break; } case FRIEND_CALL_STATUS: { /* param1: friend id param2: call id data: integer call status */ FRIEND *f = &friend[param1]; uint8_t status = (size_t)data; if(status == CALL_NONE && (f->calling == CALL_OK || f->calling == CALL_OK_VIDEO)) { toxaudio_postmessage(AUDIO_CALL_END, param2, 0, NULL); if(f->calling == CALL_OK_VIDEO) { toxvideo_postmessage(VIDEO_CALL_END, param2, 0, NULL); } video_end(param1 + 1); } f->calling = status; f->callid = param2; if(status == CALL_OK) { toxaudio_postmessage(AUDIO_CALL_START, param2, 0, NULL); } call_notify(f, status); updatefriend(f); break; } case FRIEND_CALL_VIDEO: { /* param1: friend id param2: call id */ FRIEND *f = &friend[param1]; f->calling = CALL_OK_VIDEO; f->callid = param2; updatefriend(f); toxvideo_postmessage(VIDEO_CALL_START, param2, 0, NULL); toxaudio_postmessage(AUDIO_CALL_START, param2, 0, NULL); f->call_width = 640; f->call_height = 480; video_begin(param1 + 1, f->name, f->name_length, 640, 480); call_notify(f, CALL_OK_VIDEO); break; } case FRIEND_CALL_MEDIACHANGE: { /* param1: friend id param2: call id data: zero = audio, nonzero = audio/video */ FRIEND *f = &friend[param1]; if(!data) { video_end(param1 + 1); } else { f->call_width = 640; f->call_height = 480; video_begin(param1 + 1, f->name, f->name_length, 640, 480); } break; } case FRIEND_CALL_START_VIDEO: { /* param1: friend id param2: call id */ FRIEND *f = &friend[param1]; if(f->calling == CALL_OK) { f->calling = CALL_OK_VIDEO; toxvideo_postmessage(VIDEO_CALL_START, param2, 0, NULL); updatefriend(f); } break; } case FRIEND_CALL_STOP_VIDEO: { /* param1: friend id param2: call id */ FRIEND *f = &friend[param1]; if(f->calling == CALL_OK_VIDEO) { f->calling = CALL_OK; toxvideo_postmessage(VIDEO_CALL_END, param2, 0, NULL); updatefriend(f); } break; } case FRIEND_VIDEO_FRAME: { /* param1: friend id param2: call id data: frame data */ uint16_t *image = data; FRIEND *f = &friend[param1]; _Bool b = (image[0] != f->call_width || image[1] != f->call_height); if(b) { f->call_width = image[0]; f->call_height = image[1]; } video_frame(param1 + 1, (void*)&image[2], image[0], image[1], b); free(image); break; } case PREVIEW_FRAME_NEW: case PREVIEW_FRAME: { if(video_preview) { video_frame(0, data, param1, param2, tox_message_id == PREVIEW_FRAME_NEW); } free(data); break; } case FRIEND_FILE_IN_NEW: case FRIEND_FILE_IN_NEW_INLINE: { FRIEND *f = &friend[param1]; FILE_T *ft = &f->incoming[param2]; _Bool inline_png = (tox_message_id == FRIEND_FILE_IN_NEW_INLINE); MSG_FILE *msg = malloc(sizeof(MSG_FILE)); msg->author = 0; msg->msg_type = MSG_TYPE_FILE; msg->filenumber = param2; msg->status = (inline_png ? FILE_OK : FILE_PENDING); msg->name_length = (ft->name_length > sizeof(msg->name)) ? sizeof(msg->name) : ft->name_length; msg->size = ft->total; msg->progress = 0; msg->speed = 0; msg->inline_png = inline_png; msg->path = NULL; memcpy(msg->name, ft->name, msg->name_length); friend_addmessage(f, msg); ft->chatdata = msg; file_notify(f, msg); updatefriend(f); break; } case FRIEND_FILE_OUT_NEW: case FRIEND_FILE_OUT_NEW_INLINE: { FRIEND *f = &friend[param1]; FILE_T *ft = &f->outgoing[param2]; _Bool inline_png = (tox_message_id == FRIEND_FILE_OUT_NEW_INLINE); MSG_FILE *msg = malloc(sizeof(MSG_FILE)); msg->author = 1; msg->msg_type = MSG_TYPE_FILE; msg->filenumber = param2; msg->status = FILE_PENDING; msg->name_length = (ft->name_length >= sizeof(msg->name)) ? sizeof(msg->name) - 1 : ft->name_length; msg->size = ft->total; msg->progress = 0; msg->speed = 0; msg->inline_png = inline_png; msg->path = NULL; memcpy(msg->name, ft->name, msg->name_length); msg->name[msg->name_length] = 0; friend_addmessage(f, msg); ft->chatdata = msg; updatefriend(f); break; } case FRIEND_FILE_IN_STATUS: { FRIEND *f = &friend[param1]; FILE_T *ft = &f->incoming[param2]; MSG_FILE *msg = ft->chatdata; msg->status = (size_t)data; file_notify(f, msg); updatefriend(f); break; } case FRIEND_FILE_OUT_STATUS: { FRIEND *f = &friend[param1]; FILE_T *ft = &f->outgoing[param2]; MSG_FILE *msg = ft->chatdata; msg->status = (size_t)data; file_notify(f, msg); updatefriend(f); break; } case FRIEND_FILE_IN_DONE: { FRIEND *f = &friend[param1]; FILE_T *ft = &f->incoming[param2]; MSG_FILE *msg = ft->chatdata; msg->status = FILE_DONE; msg->path = data; file_notify(f, msg); updatefriend(f); break; } case FRIEND_FILE_IN_DONE_INLINE: { FRIEND *f = &friend[param1]; FILE_T *ft = &f->incoming[param2]; MSG_FILE *msg = ft->chatdata; msg->status = FILE_DONE; msg->path = data; friend_recvimage(f, data, msg->size); file_notify(f, msg); updatefriend(f); break; } case FRIEND_FILE_OUT_DONE: { FRIEND *f = &friend[param1]; FILE_T *ft = &f->outgoing[param2]; MSG_FILE *msg = ft->chatdata; msg->status = FILE_DONE; msg->path = data; file_notify(f, msg); updatefriend(f); break; } case FRIEND_FILE_IN_PROGRESS: { FRIEND *f = &friend[param1]; FILE_T *ft = &f->incoming[param2]; FILE_PROGRESS *p = data; MSG_FILE *msg = ft->chatdata; msg->progress = p->bytes; msg->speed = p->speed; free(p); updatefriend(f); break; } case FRIEND_FILE_OUT_PROGRESS: { FRIEND *f = &friend[param1]; FILE_T *ft = &f->outgoing[param2]; FILE_PROGRESS *p = data; MSG_FILE *msg = ft->chatdata; msg->progress = p->bytes; msg->speed = p->speed; free(p); updatefriend(f); break; } case GROUP_ADD: { GROUPCHAT *g = &group[param1]; g->name_length = snprintf((char*)g->name, sizeof(g->name), "Groupchat #%u", param1); g->topic_length = sizeof("Drag friends to invite them") - 1; memcpy(g->topic, "Drag friends to invite them", sizeof("Drag friends to invite them") - 1); g->msg.scroll = 1.0; g->type = tox_group_get_type(data, param1); list_addgroup(g); redraw(); break; } case GROUP_MESSAGE: { GROUPCHAT *g = &group[param1]; message_add(&messages_group, data, &g->msg); if(sitem && g == sitem->data) { redraw();//ui_drawmain(); } break; } case GROUP_PEER_DEL: { GROUPCHAT *g = &group[param1]; if (param2 > MAX_GROUP_PEERS) //TODO: dynamic arrays. break; if(g->peername[param2]) { free(g->peername[param2]); g->peername[param2] = NULL; } g->peers--; g->peername[param2] = g->peername[g->peers]; g->peername[g->peers] = NULL; if (g->type == TOX_GROUPCHAT_TYPE_AV) { g->last_recv_audio[param2] = g->last_recv_audio[g->peers]; g->last_recv_audio[g->peers] = 0; group_av_peer_remove(g, param2); g->source[param2] = g->source[g->peers]; } if (g->peers == g->our_peer_number) { g->our_peer_number = param2; } g->topic_length = snprintf((char*)g->topic, sizeof(g->topic), "%u users in chat", g->peers); updategroup(g); break; } case GROUP_PEER_ADD: case GROUP_PEER_NAME: { GROUPCHAT *g = &group[param1]; if (param2 > MAX_GROUP_PEERS) //TODO: dynamic arrays. break; if(g->peername[param2]) { free(g->peername[param2]); } if(tox_message_id == GROUP_PEER_ADD) { if (g->type == TOX_GROUPCHAT_TYPE_AV) { group_av_peer_add(g, param2); } if (tox_group_peernumber_is_ours(data, param1, param2)) { g->our_peer_number = param2; } uint8_t *n = malloc(10); n[0] = 9; memcpy(n + 1, "<unknown>", 9); data = n; g->peers++; } g->peername[param2] = data; g->topic_length = snprintf((char*)g->topic, sizeof(g->topic), "%u users in chat", g->peers); updategroup(g); break; } case GROUP_TITLE: { GROUPCHAT *g = &group[param1]; if (param2 > sizeof(g->name)) { memcpy(g->name, data, sizeof(g->name)); g->name_length = sizeof(g->name); } else { memcpy(g->name, data, param2); g->name_length = param2; } free(data); updategroup(g); break; } case GROUP_AUDIO_START: { GROUPCHAT *g = &group[param1]; if (g->type == TOX_GROUPCHAT_TYPE_AV) { g->audio_calling = 1; toxaudio_postmessage(GROUP_AUDIO_CALL_START, param1, 0, NULL); updategroup(g); } break; } case GROUP_AUDIO_END: { GROUPCHAT *g = &group[param1]; if (g->type == TOX_GROUPCHAT_TYPE_AV) { g->audio_calling = 0; toxaudio_postmessage(GROUP_AUDIO_CALL_END, param1, 0, NULL); updategroup(g); } break; } case GROUP_UPDATE: { GROUPCHAT *g = &group[param1]; updategroup(g); break; } }