| |
1 /* |
| |
2 * pidgin |
| |
3 * |
| |
4 * Pidgin is the legal property of its developers, whose names are too numerous |
| |
5 * to list here. Please refer to the COPYRIGHT file distributed with this |
| |
6 * source distribution. |
| |
7 * |
| |
8 * This program is free software; you can redistribute it and/or modify |
| |
9 * it under the terms of the GNU General Public License as published by |
| |
10 * the Free Software Foundation; either version 2 of the License, or |
| |
11 * (at your option) any later version. |
| |
12 * |
| |
13 * This program is distributed in the hope that it will be useful, |
| |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| |
16 * GNU General Public License for more details. |
| |
17 * |
| |
18 * You should have received a copy of the GNU General Public License |
| |
19 * along with this program; if not, write to the Free Software |
| |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| |
21 * |
| |
22 */ |
| |
23 #include "account.h" |
| |
24 #include "conversation.h" |
| |
25 #include "core.h" |
| |
26 #include "debug.h" |
| |
27 #include "eventloop.h" |
| |
28 #include "ft.h" |
| |
29 #include "log.h" |
| |
30 #include "notify.h" |
| |
31 #include "prefix.h" |
| |
32 #include "prefs.h" |
| |
33 #include "prpl.h" |
| |
34 #include "pounce.h" |
| |
35 #include "savedstatuses.h" |
| |
36 #include "sound.h" |
| |
37 #include "status.h" |
| |
38 #include "util.h" |
| |
39 #include "whiteboard.h" |
| |
40 |
| |
41 #include <glib.h> |
| |
42 |
| |
43 #include <string.h> |
| |
44 #include <unistd.h> |
| |
45 |
| |
46 #include "defines.h" |
| |
47 |
| |
48 /** |
| |
49 * The following eventloop functions are used in both pidgin and gaim-text. If your |
| |
50 * application uses glib mainloop, you can safely use this verbatim. |
| |
51 */ |
| |
52 #define GAIM_GLIB_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) |
| |
53 #define GAIM_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) |
| |
54 |
| |
55 typedef struct _GaimGLibIOClosure { |
| |
56 GaimInputFunction function; |
| |
57 guint result; |
| |
58 gpointer data; |
| |
59 } GaimGLibIOClosure; |
| |
60 |
| |
61 static void gaim_glib_io_destroy(gpointer data) |
| |
62 { |
| |
63 g_free(data); |
| |
64 } |
| |
65 |
| |
66 static gboolean gaim_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) |
| |
67 { |
| |
68 GaimGLibIOClosure *closure = data; |
| |
69 GaimInputCondition gaim_cond = 0; |
| |
70 |
| |
71 if (condition & GAIM_GLIB_READ_COND) |
| |
72 gaim_cond |= GAIM_INPUT_READ; |
| |
73 if (condition & GAIM_GLIB_WRITE_COND) |
| |
74 gaim_cond |= GAIM_INPUT_WRITE; |
| |
75 |
| |
76 closure->function(closure->data, g_io_channel_unix_get_fd(source), |
| |
77 gaim_cond); |
| |
78 |
| |
79 return TRUE; |
| |
80 } |
| |
81 |
| |
82 static guint glib_input_add(gint fd, GaimInputCondition condition, GaimInputFunction function, |
| |
83 gpointer data) |
| |
84 { |
| |
85 GaimGLibIOClosure *closure = g_new0(GaimGLibIOClosure, 1); |
| |
86 GIOChannel *channel; |
| |
87 GIOCondition cond = 0; |
| |
88 |
| |
89 closure->function = function; |
| |
90 closure->data = data; |
| |
91 |
| |
92 if (condition & GAIM_INPUT_READ) |
| |
93 cond |= GAIM_GLIB_READ_COND; |
| |
94 if (condition & GAIM_INPUT_WRITE) |
| |
95 cond |= GAIM_GLIB_WRITE_COND; |
| |
96 |
| |
97 channel = g_io_channel_unix_new(fd); |
| |
98 closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, |
| |
99 gaim_glib_io_invoke, closure, gaim_glib_io_destroy); |
| |
100 |
| |
101 g_io_channel_unref(channel); |
| |
102 return closure->result; |
| |
103 } |
| |
104 |
| |
105 static GaimEventLoopUiOps glib_eventloops = |
| |
106 { |
| |
107 g_timeout_add, |
| |
108 g_source_remove, |
| |
109 glib_input_add, |
| |
110 g_source_remove |
| |
111 }; |
| |
112 /*** End of the eventloop functions. ***/ |
| |
113 |
| |
114 /*** Conversation uiops ***/ |
| |
115 static void |
| |
116 null_write_conv(GaimConversation *conv, const char *who, const char *alias, |
| |
117 const char *message, GaimMessageFlags flags, time_t mtime) |
| |
118 { |
| |
119 const char *name; |
| |
120 if (alias && *alias) |
| |
121 name = alias; |
| |
122 else if (who && *who) |
| |
123 name = who; |
| |
124 else |
| |
125 name = NULL; |
| |
126 |
| |
127 printf("(%s) %s %s: %s\n", gaim_conversation_get_name(conv), |
| |
128 gaim_utf8_strftime("(%H:%M:%S)", localtime(&mtime)), |
| |
129 name, message); |
| |
130 } |
| |
131 |
| |
132 static GaimConversationUiOps null_conv_uiops = |
| |
133 { |
| |
134 .write_conv = null_write_conv |
| |
135 }; |
| |
136 |
| |
137 static void |
| |
138 null_ui_init() |
| |
139 { |
| |
140 /** |
| |
141 * This should initialize the UI components for all the modules. Here we |
| |
142 * just initialize the UI for conversations. |
| |
143 */ |
| |
144 gaim_conversations_set_ui_ops(&null_conv_uiops); |
| |
145 } |
| |
146 |
| |
147 static GaimCoreUiOps null_core_uiops = |
| |
148 { |
| |
149 NULL, |
| |
150 NULL, |
| |
151 null_ui_init, |
| |
152 NULL |
| |
153 }; |
| |
154 |
| |
155 static void |
| |
156 init_libpurple() |
| |
157 { |
| |
158 /* Set a custom user directory (optional) */ |
| |
159 gaim_util_set_user_dir(CUSTOM_USER_DIRECTORY); |
| |
160 |
| |
161 /* We do not want any debugging for now to keep the noise to a minimum. */ |
| |
162 gaim_debug_set_enabled(FALSE); |
| |
163 |
| |
164 /* Set the core-uiops, which is used to |
| |
165 * - initialize the ui specific preferences. |
| |
166 * - initialize the debug ui. |
| |
167 * - initialize the ui components for all the modules. |
| |
168 * - uninitialize the ui components for all the modules when the core terminates. |
| |
169 */ |
| |
170 gaim_core_set_ui_ops(&null_core_uiops); |
| |
171 |
| |
172 /* Set the uiops for the eventloop. If your client is glib-based, you can safely |
| |
173 * copy this verbatim. */ |
| |
174 gaim_eventloop_set_ui_ops(&glib_eventloops); |
| |
175 |
| |
176 /* Set path to search for plugins. The core (libpurple) takes care of loading the |
| |
177 * core-plugins, which includes the protocol-plugins. So it is not essential to add |
| |
178 * any path here, but it might be desired, especially for ui-specific plugins. */ |
| |
179 gaim_plugins_add_search_path(CUSTOM_PLUGIN_PATH); |
| |
180 |
| |
181 /* Now that all the essential stuff has been set, let's try to init the core. It's |
| |
182 * necessary to provide a non-NULL name for the current ui to the core. This name |
| |
183 * is used by stuff that depends on this ui, for example the ui-specific plugins. */ |
| |
184 if (!gaim_core_init(UI_ID)) { |
| |
185 /* Initializing the core failed. Terminate. */ |
| |
186 fprintf(stderr, |
| |
187 "libpurple initialization failed. Dumping core.\n" |
| |
188 "Please report this!\n"); |
| |
189 abort(); |
| |
190 } |
| |
191 |
| |
192 /* Create and load the buddylist. */ |
| |
193 gaim_set_blist(gaim_blist_new()); |
| |
194 gaim_blist_load(); |
| |
195 |
| |
196 /* Load the preferences. */ |
| |
197 gaim_prefs_load(); |
| |
198 |
| |
199 /* Load the desired plugins. The client should save the list of loaded plugins in |
| |
200 * the preferences using gaim_plugins_save_loaded(PLUGIN_SAVE_PREF) */ |
| |
201 gaim_plugins_load_saved(PLUGIN_SAVE_PREF); |
| |
202 |
| |
203 /* Load the pounces. */ |
| |
204 gaim_pounces_load(); |
| |
205 } |
| |
206 |
| |
207 static void |
| |
208 signed_on(GaimConnection *gc, gpointer null) |
| |
209 { |
| |
210 GaimAccount *account = gaim_connection_get_account(gc); |
| |
211 printf("Account connected: %s %s\n", account->username, account->protocol_id); |
| |
212 } |
| |
213 |
| |
214 static void |
| |
215 connect_to_signals_for_demonstration_purposes_only() |
| |
216 { |
| |
217 static int handle; |
| |
218 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", &handle, |
| |
219 GAIM_CALLBACK(signed_on), NULL); |
| |
220 } |
| |
221 |
| |
222 int main() |
| |
223 { |
| |
224 GList *iter; |
| |
225 int i, num; |
| |
226 GList *names = NULL; |
| |
227 const char *prpl; |
| |
228 char name[128]; |
| |
229 char *password; |
| |
230 GMainLoop *loop = g_main_loop_new(NULL, FALSE); |
| |
231 GaimAccount *account; |
| |
232 GaimSavedStatus *status; |
| |
233 |
| |
234 init_libpurple(); |
| |
235 |
| |
236 printf("libpurple initialized.\n"); |
| |
237 |
| |
238 iter = gaim_plugins_get_protocols(); |
| |
239 for (i = 0; iter; iter = iter->next) { |
| |
240 GaimPlugin *plugin = iter->data; |
| |
241 GaimPluginInfo *info = plugin->info; |
| |
242 if (info && info->name) { |
| |
243 printf("\t%d: %s\n", i++, info->name); |
| |
244 names = g_list_append(names, info->id); |
| |
245 } |
| |
246 } |
| |
247 printf("Select the protocol [0-%d]: ", i-1); |
| |
248 fgets(name, sizeof(name), stdin); |
| |
249 sscanf(name, "%d", &num); |
| |
250 prpl = g_list_nth_data(names, num); |
| |
251 |
| |
252 printf("Username: "); |
| |
253 fgets(name, sizeof(name), stdin); |
| |
254 name[strlen(name) - 1] = 0; /* strip the \n at the end */ |
| |
255 |
| |
256 /* Create the account */ |
| |
257 account = gaim_account_new(name, prpl); |
| |
258 |
| |
259 /* Get the password for the account */ |
| |
260 password = getpass("Password: "); |
| |
261 gaim_account_set_password(account, password); |
| |
262 |
| |
263 /* It's necessary to enable the account first. */ |
| |
264 gaim_account_set_enabled(account, UI_ID, TRUE); |
| |
265 |
| |
266 /* Now, to connect the account(s), create a status and activate it. */ |
| |
267 status = gaim_savedstatus_new(NULL, GAIM_STATUS_AVAILABLE); |
| |
268 gaim_savedstatus_activate(status); |
| |
269 |
| |
270 connect_to_signals_for_demonstration_purposes_only(); |
| |
271 |
| |
272 g_main_loop_run(loop); |
| |
273 |
| |
274 return 0; |
| |
275 } |
| |
276 |