Mercurial > pidgin
diff libpurple/protocols/yahoo/yahoo_doodle.c @ 15373:5fe8042783c1
Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sat, 20 Jan 2007 02:32:10 +0000 |
parents | |
children | cf999f8e8a56 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/yahoo/yahoo_doodle.c Sat Jan 20 02:32:10 2007 +0000 @@ -0,0 +1,605 @@ +/* + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/****************************************************************************** + * INCLUDES + *****************************************************************************/ +#include "internal.h" + +#include "account.h" +#include "accountopt.h" +#include "blist.h" +#include "cipher.h" +#include "cmds.h" +#include "debug.h" +#include "notify.h" +#include "privacy.h" +#include "prpl.h" +#include "proxy.h" +#include "request.h" +#include "server.h" +#include "util.h" +#include "version.h" + +#include "yahoo.h" +#include "yahoo_packet.h" +#include "yahoo_friend.h" +#include "yahoochat.h" +#include "ycht.h" +#include "yahoo_auth.h" +#include "yahoo_filexfer.h" +#include "yahoo_picture.h" + +#include "whiteboard.h" +#include "yahoo_doodle.h" + +/****************************************************************************** + * Globals + *****************************************************************************/ +#if 0 +const int DefaultColorRGB24[] = +{ + DOODLE_COLOR_RED, + DOODLE_COLOR_ORANGE, + DOODLE_COLOR_YELLOW, + DOODLE_COLOR_GREEN, + DOODLE_COLOR_CYAN, + DOODLE_COLOR_BLUE, + DOODLE_COLOR_VIOLET, + DOODLE_COLOR_PURPLE, + DOODLE_COLOR_TAN, + DOODLE_COLOR_BROWN, + DOODLE_COLOR_BLACK, + DOODLE_COLOR_GREY, + DOODLE_COLOR_WHITE +}; +#endif + +/****************************************************************************** + * Functions + *****************************************************************************/ +GaimCmdRet yahoo_doodle_gaim_cmd_start(GaimConversation *conv, const char *cmd, char **args, char **error, void *data) +{ + GaimAccount *account; + GaimConnection *gc; + const gchar *name; + + if(*args && args[0]) + return GAIM_CMD_RET_FAILED; + + account = gaim_conversation_get_account(conv); + gc = gaim_account_get_connection(account); + name = gaim_conversation_get_name(conv); + yahoo_doodle_initiate(gc, name); + + /* Write a local message to this conversation showing that a request for a + * Doodle session has been made + */ + gaim_conv_im_write(GAIM_CONV_IM(conv), "", _("Sent Doodle request."), + GAIM_MESSAGE_NICK | GAIM_MESSAGE_RECV, time(NULL)); + + return GAIM_CMD_RET_OK; +} + +void yahoo_doodle_initiate(GaimConnection *gc, const char *name) +{ + GaimAccount *account; + char *to = (char*)name; + GaimWhiteboard *wb; + + g_return_if_fail(gc); + g_return_if_fail(name); + + account = gaim_connection_get_account(gc); + wb = gaim_whiteboard_get_session(account, to); + + if(wb == NULL) + { + /* Insert this 'session' in the list. At this point, it's only a + * requested session. + */ + gaim_whiteboard_create(account, to, DOODLE_STATE_REQUESTING); + } + + /* NOTE Perhaps some careful handling of remote assumed established + * sessions + */ + + yahoo_doodle_command_send_request(gc, to); + yahoo_doodle_command_send_ready(gc, to); + +} + +void yahoo_doodle_process(GaimConnection *gc, const char *me, const char *from, + const char *command, const char *message) +{ + if(!command) + return; + + /* Now check to see what sort of Doodle message it is */ + switch(atoi(command)) + { + case DOODLE_CMD_REQUEST: + yahoo_doodle_command_got_request(gc, from); + break; + + case DOODLE_CMD_READY: + yahoo_doodle_command_got_ready(gc, from); + break; + + case DOODLE_CMD_CLEAR: + yahoo_doodle_command_got_clear(gc, from); + break; + + case DOODLE_CMD_DRAW: + yahoo_doodle_command_got_draw(gc, from, message); + break; + + case DOODLE_CMD_EXTRA: + yahoo_doodle_command_got_extra(gc, from, message); + break; + + case DOODLE_CMD_CONFIRM: + yahoo_doodle_command_got_confirm(gc, from); + break; + } +} + +void yahoo_doodle_command_got_request(GaimConnection *gc, const char *from) +{ + GaimAccount *account; + GaimWhiteboard *wb; + + gaim_debug_info("yahoo", "doodle: Got Request (%s)\n", from); + + account = gaim_connection_get_account(gc); + + /* Only handle this if local client requested Doodle session (else local + * client would have sent one) + */ + wb = gaim_whiteboard_get_session(account, from); + + /* If a session with the remote user doesn't exist */ + if(wb == NULL) + { + /* Ask user if they wish to accept the request for a doodle session */ + /* TODO Ask local user to start Doodle session with remote user */ + /* NOTE This if/else statement won't work right--must use dialog + * results + */ + + /* char dialog_message[64]; + g_sprintf(dialog_message, "%s is requesting to start a Doodle session with you.", from); + + gaim_notify_message(NULL, GAIM_NOTIFY_MSG_INFO, "Doodle", + dialog_message, NULL, NULL, NULL); + */ + + gaim_whiteboard_create(account, from, DOODLE_STATE_REQUESTED); + + yahoo_doodle_command_send_request(gc, from); + } + + /* TODO Might be required to clear the canvas of an existing doodle + * session at this point + */ +} + +void yahoo_doodle_command_got_ready(GaimConnection *gc, const char *from) +{ + GaimAccount *account; + GaimWhiteboard *wb; + + gaim_debug_info("yahoo", "doodle: Got Ready (%s)\n", from); + + account = gaim_connection_get_account(gc); + + /* Only handle this if local client requested Doodle session (else local + * client would have sent one) + */ + wb = gaim_whiteboard_get_session(account, from); + + if(wb == NULL) + return; + + if(wb->state == DOODLE_STATE_REQUESTING) + { + gaim_whiteboard_start(wb); + + wb->state = DOODLE_STATE_ESTABLISHED; + + yahoo_doodle_command_send_confirm(gc, from); + } + + if(wb->state == DOODLE_STATE_ESTABLISHED) + { + /* TODO Ask whether to save picture too */ + gaim_whiteboard_clear(wb); + } + + /* NOTE Not sure about this... I am trying to handle if the remote user + * already thinks we're in a session with them (when their chat message + * contains the doodle;11 imv key) + */ + if(wb->state == DOODLE_STATE_REQUESTED) + { + /* gaim_whiteboard_start(wb); */ + yahoo_doodle_command_send_request(gc, from); + } +} + +void yahoo_doodle_command_got_draw(GaimConnection *gc, const char *from, const char *message) +{ + GaimAccount *account; + GaimWhiteboard *wb; + char **tokens; + int i; + GList *d_list = NULL; /* a local list of drawing info */ + + g_return_if_fail(message != NULL); + + gaim_debug_info("yahoo", "doodle: Got Draw (%s)\n", from); + gaim_debug_info("yahoo", "doodle: Draw message: %s\n", message); + + account = gaim_connection_get_account(gc); + + /* Only handle this if local client requested Doodle session (else local + * client would have sent one) + */ + wb = gaim_whiteboard_get_session(account, from); + + if(wb == NULL) + return; + + /* TODO Functionalize + * Convert drawing packet message to an integer list + */ + + /* Check to see if the message begans and ends with quotes */ + if((message[0] != '\"') || (message[strlen(message) - 1] != '\"')) + return; + + /* Ignore the inital quotation mark. */ + message += 1; + + tokens = g_strsplit(message, ",", 0); + + /* Traverse and extract all integers divided by commas */ + for (i = 0; tokens[i] != NULL; i++) + { + int last = strlen(tokens[i]) - 1; + if (tokens[i][last] == '"') + tokens[i][last] = '\0'; + + d_list = g_list_prepend(d_list, GINT_TO_POINTER(atoi(tokens[i]))); + } + d_list = g_list_reverse(d_list); + + g_strfreev(tokens); + + yahoo_doodle_draw_stroke(wb, d_list); + + /* goodle_doodle_session_set_canvas_as_icon(ds); */ + + g_list_free(d_list); +} + +void yahoo_doodle_command_got_clear(GaimConnection *gc, const char *from) +{ + GaimAccount *account; + GaimWhiteboard *wb; + + gaim_debug_info("yahoo", "doodle: Got Clear (%s)\n", from); + + account = gaim_connection_get_account(gc); + + /* Only handle this if local client requested Doodle session (else local + * client would have sent one) + */ + wb = gaim_whiteboard_get_session(account, from); + + if(wb == NULL) + return; + + if(wb->state == DOODLE_STATE_ESTABLISHED) + { + /* TODO Ask user whether to save the image before clearing it */ + + gaim_whiteboard_clear(wb); + } +} + +void +yahoo_doodle_command_got_extra(GaimConnection *gc, const char *from, const char *message) +{ + gaim_debug_info("yahoo", "doodle: Got Extra (%s)\n", from); + + /* I do not like these 'extra' features, so I'll only handle them in one + * way, which is returning them with the command/packet to turn them off + */ + yahoo_doodle_command_send_extra(gc, from, DOODLE_EXTRA_NONE); +} + +void yahoo_doodle_command_got_confirm(GaimConnection *gc, const char *from) +{ + GaimAccount *account; + GaimWhiteboard *wb; + + gaim_debug_info("yahoo", "doodle: Got Confirm (%s)\n", from); + + /* Get the doodle session */ + account = gaim_connection_get_account(gc); + + /* Only handle this if local client requested Doodle session (else local + * client would have sent one) + */ + wb = gaim_whiteboard_get_session(account, from); + + if(wb == NULL) + return; + + /* TODO Combine the following IF's? */ + + /* Check if we requested a doodle session */ + if(wb->state == DOODLE_STATE_REQUESTING) + { + wb->state = DOODLE_STATE_ESTABLISHED; + + gaim_whiteboard_start(wb); + + yahoo_doodle_command_send_confirm(gc, from); + } + + /* Check if we accepted a request for a doodle session */ + if(wb->state == DOODLE_STATE_REQUESTED) + { + wb->state = DOODLE_STATE_ESTABLISHED; + + gaim_whiteboard_start(wb); + } +} + +void yahoo_doodle_command_got_shutdown(GaimConnection *gc, const char *from) +{ + GaimAccount *account; + GaimWhiteboard *wb; + + g_return_if_fail(from != NULL); + + gaim_debug_info("yahoo", "doodle: Got Shutdown (%s)\n", from); + + account = gaim_connection_get_account(gc); + + /* Only handle this if local client requested Doodle session (else local + * client would have sent one) + */ + wb = gaim_whiteboard_get_session(account, from); + + /* TODO Ask if user wants to save picture before the session is closed */ + + /* If this session doesn't exist, don't try and kill it */ + if(wb == NULL) + return; + else + { + gaim_whiteboard_destroy(wb); + + /* yahoo_doodle_command_send_shutdown(gc, from); */ + } +} + +static void yahoo_doodle_command_send_generic(const char *type, + GaimConnection *gc, + const char *to, + const char *message, + const char *thirteen, + const char *sixtythree, + const char *sixtyfour) +{ + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + gaim_debug_info("yahoo", "doodle: Sent %s (%s)\n", type, to); + + yd = gc->proto_data; + + /* Make and send an acknowledge (ready) Doodle packet */ + pkt = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash_str(pkt, 49, "IMVIRONMENT"); + yahoo_packet_hash_str(pkt, 1, gaim_account_get_username(gc->account)); + yahoo_packet_hash_str(pkt, 14, message); + yahoo_packet_hash_str(pkt, 13, thirteen); + yahoo_packet_hash_str(pkt, 5, to); + yahoo_packet_hash_str(pkt, 63, sixtythree ? sixtythree : "doodle;11"); + yahoo_packet_hash_str(pkt, 64, sixtyfour); + yahoo_packet_hash_str(pkt, 1002, "1"); + + yahoo_packet_send_and_free(pkt, yd); +} + +void yahoo_doodle_command_send_request(GaimConnection *gc, const char *to) +{ + yahoo_doodle_command_send_generic("Request", gc, to, "1", "1", NULL, "1"); +} + +void yahoo_doodle_command_send_ready(GaimConnection *gc, const char *to) +{ + yahoo_doodle_command_send_generic("Ready", gc, to, "", "0", NULL, "0"); +} + +void yahoo_doodle_command_send_draw(GaimConnection *gc, const char *to, const char *message) +{ + yahoo_doodle_command_send_generic("Draw", gc, to, message, "3", NULL, "1"); +} + +void yahoo_doodle_command_send_clear(GaimConnection *gc, const char *to) +{ + yahoo_doodle_command_send_generic("Clear", gc, to, " ", "2", NULL, "1"); +} + +void yahoo_doodle_command_send_extra(GaimConnection *gc, const char *to, const char *message) +{ + yahoo_doodle_command_send_generic("Extra", gc, to, message, "4", NULL, "1"); +} + +void yahoo_doodle_command_send_confirm(GaimConnection *gc, const char *to) +{ + yahoo_doodle_command_send_generic("Confirm", gc, to, "1", "5", NULL, "1"); +} + +void yahoo_doodle_command_send_shutdown(GaimConnection *gc, const char *to) +{ + yahoo_doodle_command_send_generic("Shutdown", gc, to, "", "0", ";0", "0"); +} + +void yahoo_doodle_start(GaimWhiteboard *wb) +{ + doodle_session *ds = g_new0(doodle_session, 1); + + /* gaim_debug_debug("yahoo", "doodle: yahoo_doodle_start()\n"); */ + + /* Set default brush size and color */ + ds->brush_size = DOODLE_BRUSH_SMALL; + ds->brush_color = DOODLE_COLOR_RED; + + wb->proto_data = ds; +} + +void yahoo_doodle_end(GaimWhiteboard *wb) +{ + GaimConnection *gc = gaim_account_get_connection(wb->account); + + /* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */ + + yahoo_doodle_command_send_shutdown(gc, wb->who); + + g_free(wb->proto_data); +} + +void yahoo_doodle_get_dimensions(GaimWhiteboard *wb, int *width, int *height) +{ + /* standard Doodle canvases are of one size: 368x256 */ + *width = DOODLE_CANVAS_WIDTH; + *height = DOODLE_CANVAS_HEIGHT; +} + +static char *yahoo_doodle_build_draw_string(doodle_session *ds, GList *draw_list) +{ + GString *message; + + g_return_val_if_fail(draw_list != NULL, NULL); + + message = g_string_new(""); + g_string_printf(message, "\"%d,%d", ds->brush_color, ds->brush_size); + + for(; draw_list != NULL; draw_list = draw_list->next) + { + g_string_append_printf(message, ",%d", GPOINTER_TO_INT(draw_list->data)); + } + g_string_append_c(message, '"'); + + return g_string_free(message, FALSE); +} + +void yahoo_doodle_send_draw_list(GaimWhiteboard *wb, GList *draw_list) +{ + doodle_session *ds = wb->proto_data; + char *message; + + g_return_if_fail(draw_list != NULL); + + message = yahoo_doodle_build_draw_string(ds, draw_list); + yahoo_doodle_command_send_draw(wb->account->gc, wb->who, message); + g_free(message); +} + +void yahoo_doodle_clear(GaimWhiteboard *wb) +{ + yahoo_doodle_command_send_clear(wb->account->gc, wb->who); +} + + +/* Traverse through the list and draw the points and lines */ +void yahoo_doodle_draw_stroke(GaimWhiteboard *wb, GList *draw_list) +{ + int brush_color; + int brush_size; + int x; + int y; + + g_return_if_fail(draw_list != NULL); + + brush_color = GPOINTER_TO_INT(draw_list->data); + draw_list = draw_list->next; + g_return_if_fail(draw_list != NULL); + + brush_size = GPOINTER_TO_INT(draw_list->data); + draw_list = draw_list->next; + g_return_if_fail(draw_list != NULL); + + x = GPOINTER_TO_INT(draw_list->data); + draw_list = draw_list->next; + g_return_if_fail(draw_list != NULL); + + y = GPOINTER_TO_INT(draw_list->data); + draw_list = draw_list->next; + g_return_if_fail(draw_list != NULL); + + /* + gaim_debug_debug("yahoo", "doodle: Drawing: color=%d, size=%d, (%d,%d)\n", brush_color, brush_size, x, y); + */ + + while(draw_list != NULL && draw_list->next != NULL) + { + int dx = GPOINTER_TO_INT(draw_list->data); + int dy = GPOINTER_TO_INT(draw_list->next->data); + + gaim_whiteboard_draw_line(wb, + x, y, + x + dx, y + dy, + brush_color, brush_size); + + x += dx; + y += dy; + + draw_list = draw_list->next->next; + } +} + +void yahoo_doodle_get_brush(GaimWhiteboard *wb, int *size, int *color) +{ + doodle_session *ds = (doodle_session *)wb->proto_data; + *size = ds->brush_size; + *color = ds->brush_color; +} + +void yahoo_doodle_set_brush(GaimWhiteboard *wb, int size, int color) +{ + doodle_session *ds = (doodle_session *)wb->proto_data; + ds->brush_size = size; + ds->brush_color = color; + + /* Notify the core about the changes */ + gaim_whiteboard_set_brush(wb, size, color); +} +