// Function called once the user changes its status in the MessagingMenu static void status_changed(MessagingMenuApp *mmapp_, gint status, gpointer user_data) { switch(status) { case MESSAGING_MENU_STATUS_AVAILABLE: self.status = 0; tox_postmessage(TOX_SETSTATUS, 0, 0, NULL); break; case MESSAGING_MENU_STATUS_AWAY: self.status = 1; tox_postmessage(TOX_SETSTATUS, 1, 0, NULL); break; case MESSAGING_MENU_STATUS_BUSY: self.status = 2; tox_postmessage(TOX_SETSTATUS, 2, 0, NULL); break; default: self.status = 1; tox_postmessage(TOX_SETSTATUS, 1, 0, NULL); break; } drawalpha(BM_ONLINE + status, SELF_STATUS_X + BM_STATUSAREA_WIDTH / 2 - BM_STATUS_WIDTH / 2, SELF_STATUS_Y + BM_STATUSAREA_HEIGHT / 2 - BM_STATUS_WIDTH / 2, BM_STATUS_WIDTH, BM_STATUS_WIDTH, status_color[status]); }
_Bool doevent(void) { XEvent event; XNextEvent(display, &event); if(event.xany.window && event.xany.window != window) { if(event.type == ClientMessage) { XClientMessageEvent *ev = &event.xclient; if((Atom)event.xclient.data.l[0] == wm_delete_window) { if(ev->window == video_win[0]) { video_end(0); video_preview = 0; toxvideo_postmessage(VIDEO_PREVIEW_END, 0, 0, NULL); return 1; } int i; for(i = 0; i != countof(friend); i++) { if(video_win[i + 1] == ev->window) { FRIEND *f = &friend[i]; tox_postmessage(TOX_HANGUP, f->callid, 0, NULL); break; } } if(i == countof(friend)) { debug("this should not happen\n"); } } }
static void gtk_opensendthread(void *args) { uint16_t fid = (size_t)args; void *dialog = gtk_file_chooser_dialog_new((const char *)S(SEND_FILE), NULL, 0, "gtk-cancel", -6, "gtk-open", -3, NULL); gtk_file_chooser_set_select_multiple(dialog, 1); int result = gtk_dialog_run(dialog); if(result == -3) { char *out = malloc(65536), *outp = out; g_list *list = gtk_file_chooser_get_filenames(dialog), *p = list; while(p) { outp = stpcpy(outp, p->data); *outp++ = '\n'; g_free_utox(p->data); p = p->next; } *outp = 0; g_slist_free_utox(list); debug("files: %s\n", out); //dont call this from this thread tox_postmessage(TOX_FILE_SEND_NEW, fid, 0xFFFF, out); } gtk_widget_destroy(dialog); while(gtk_events_pending()) { gtk_main_iteration(); } gtk_open = 0; }
void self_remove_avatar() { unset_avatar(&self.avatar); uint8_t hex_id[TOX_FRIEND_ADDRESS_SIZE * 2]; id_to_string(hex_id, self.id_binary); delete_saved_avatar(hex_id); tox_postmessage(TOX_AVATAR_UNSET, 0, 0, NULL); }
void friend_addid(uint8_t *id, char_t *msg, STRING_IDX msg_length) { void *data = malloc(TOX_FRIEND_ADDRESS_SIZE + msg_length * sizeof(char_t)); memcpy(data, id, TOX_FRIEND_ADDRESS_SIZE); memcpy(data + TOX_FRIEND_ADDRESS_SIZE, msg, msg_length * sizeof(char_t)); tox_postmessage(TOX_ADDFRIEND, msg_length, 0, data); }
/* sets self avatar, see self_set_and_save_avatar */ int self_set_avatar(const uint8_t *data, uint32_t size) { if (!set_avatar(&self.avatar, data, size)) { return 0; } uint8_t *png_data = malloc(size); memcpy(png_data, data, size); tox_postmessage(TOX_AVATAR_SET, UTOX_AVATAR_FORMAT_PNG, size, png_data); return 1; }
void tox_settingschanged(void) { //free everything tox_connected = 0; list_freeall(); list_dropdown_clear(&dropdown_audio_in); list_dropdown_clear(&dropdown_audio_out); list_dropdown_clear(&dropdown_video); tox_thread_init = 0; toxaudio_postmessage(AUDIO_KILL, 0, 0, NULL); toxvideo_postmessage(VIDEO_KILL, 0, 0, NULL); toxav_postmessage(TOXAV_KILL, 0, 0, NULL); tox_postmessage(0, 1, 0, NULL); while(!tox_thread_init) { yieldcpu(1); } list_start(); }
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; } }
_Bool messages_mdown(MESSAGES *m) { m->idown = MSG_IDX_MAX; if(m->iover != MSG_IDX_MAX) { MESSAGE *msg = m->data->data[m->iover]; switch(msg->msg_type) { case MSG_TYPE_TEXT: case MSG_TYPE_ACTION_TEXT: { if(m->urlover != STRING_IDX_MAX) { m->urlmdown = 1; } m->data->istart = m->data->iend = m->idown = m->iover; m->data->start = m->data->end = m->down = m->over; m->select = 1; break; } case MSG_TYPE_IMAGE: { MSG_IMG *img = (void*)msg; if(m->over) { if(!img->zoom) { img->zoom = 1; message_updateheight(m, msg, m->data); } else { m->idown = m->iover; } } break; } case MSG_TYPE_FILE: { MSG_FILE *file = (void*)msg; if(m->over == 0) { break; } switch(file->status) { case FILE_TRANSFER_STATUS_NONE: { if(!msg->author) { if(m->over == 2) { savefilerecv(m->data->id, file); } else if(m->over == 1) { //decline tox_postmessage(TOX_FILE_INCOMING_CANCEL, m->data->id, file->filenumber, NULL); } } else if(m->over == 1) { //cancel tox_postmessage(TOX_FILE_OUTGOING_CANCEL, m->data->id, file->filenumber, NULL); } break; } case FILE_TRANSFER_STATUS_ACTIVE: { if(m->over == 2) { //pause tox_postmessage((msg->author ? TOX_FILE_OUTGOING_PAUSE : TOX_FILE_INCOMING_PAUSE), m->data->id, file->filenumber, NULL); } else if(m->over == 1) { //cancel tox_postmessage((msg->author ? TOX_FILE_OUTGOING_CANCEL : TOX_FILE_INCOMING_CANCEL), m->data->id, file->filenumber, NULL); } break; } case FILE_TRANSFER_STATUS_PAUSED_US: { if(m->over == 2) { //resume tox_postmessage((msg->author ? TOX_FILE_OUTGOING_RESUME : TOX_FILE_INCOMING_RESUME), m->data->id, file->filenumber, NULL); } else if(m->over == 1) { //cancel tox_postmessage((msg->author ? TOX_FILE_OUTGOING_CANCEL : TOX_FILE_INCOMING_CANCEL), m->data->id, file->filenumber, NULL); } break; } case FILE_TRANSFER_STATUS_PAUSED_THEM: case FILE_TRANSFER_STATUS_BROKEN: { //cancel if(m->over == 1) { tox_postmessage((msg->author ? TOX_FILE_OUTGOING_CANCEL : TOX_FILE_INCOMING_CANCEL), m->data->id, file->filenumber, NULL); } break; } case FILE_TRANSFER_STATUS_COMPLETED: { if(m->over) { if(file->inline_png) { savefiledata(file); } else { openurl(file->path); } } break; } } break; } } return 1; } else { if(m->data->istart != m->data->iend || m->data->start != m->data->end) { m->data->istart = 0; m->data->iend = 0; m->data->start = 0; m->data->end = 0; return 1; } } return 0; }