f0066bd8ec65ca097411b1f3745eb457a690a395
[platform/upstream/ibus.git] / src / ibusfactory.c
1 /* vim:set et sts=4: */
2 /* ibus - The Input Bus
3  * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "ibusfactory.h"
22 #include "ibusengine.h"
23 #include "ibusshare.h"
24 #include "ibusinternal.h"
25
26 #define IBUS_FACTORY_GET_PRIVATE(o)  \
27    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FACTORY, IBusFactoryPrivate))
28
29 enum {
30     LAST_SIGNAL,
31 };
32
33 /* IBusFactoryPriv */
34 struct _IBusFactoryPrivate {
35     guint id;
36     IBusConnection *connection;
37     GList          *engine_list;
38     GHashTable     *engine_table;
39 };
40 typedef struct _IBusFactoryPrivate IBusFactoryPrivate;
41
42 /* functions prototype */
43 static void     ibus_factory_class_init     (IBusFactoryClass   *klass);
44 static void     ibus_factory_init           (IBusFactory        *factory);
45 static void     ibus_factory_destroy        (IBusFactory        *factory);
46 static gboolean ibus_factory_ibus_message   (IBusFactory        *factory,
47                                              IBusConnection     *connection,
48                                              IBusMessage        *message);
49
50 static void     _engine_destroy_cb          (IBusEngine         *engine,
51                                              IBusFactory        *factory);
52 static void     ibus_factory_info_class_init(IBusFactoryInfoClass   *klass);
53 static void     ibus_factory_info_init      (IBusFactoryInfo        *info);
54 static void     ibus_factory_info_destroy   (IBusFactoryInfo        *info);
55 static gboolean ibus_factory_info_serialize (IBusFactoryInfo        *info,
56                                              IBusMessageIter        *iter);
57 static gboolean ibus_factory_info_deserialize
58                                             (IBusFactoryInfo        *info,
59                                              IBusMessageIter        *iter);
60 static gboolean ibus_factory_info_copy      (IBusFactoryInfo        *dest,
61                                              const IBusFactoryInfo  *src);
62
63 static IBusServiceClass *factory_parent_class = NULL;
64 static IBusSerializableClass *factory_info_parent_class = NULL;
65
66 GType
67 ibus_factory_get_type (void)
68 {
69     static GType type = 0;
70
71     static const GTypeInfo type_info = {
72         sizeof (IBusFactoryClass),
73         (GBaseInitFunc)     NULL,
74         (GBaseFinalizeFunc) NULL,
75         (GClassInitFunc)    ibus_factory_class_init,
76         NULL,               /* class finalize */
77         NULL,               /* class data */
78         sizeof (IBusFactory),
79         0,
80         (GInstanceInitFunc) ibus_factory_init,
81     };
82
83     if (type == 0) {
84         type = g_type_register_static (IBUS_TYPE_SERVICE,
85                     "IBusFactory",
86                     &type_info,
87                     (GTypeFlags) 0);
88     }
89     return type;
90 }
91
92 IBusFactory *
93 ibus_factory_new (IBusConnection *connection)
94 {
95     g_assert (IBUS_IS_CONNECTION (connection));
96
97     IBusFactory *factory;
98     IBusFactoryPrivate *priv;
99
100     factory = (IBusFactory *) g_object_new (IBUS_TYPE_FACTORY,
101                                             "path", IBUS_PATH_FACTORY,
102                                             NULL);
103     priv = IBUS_FACTORY_GET_PRIVATE (factory);
104
105     priv->connection = g_object_ref (connection);
106     ibus_service_add_to_connection ((IBusService *)factory, connection);
107
108     return factory;
109 }
110
111 static void
112 ibus_factory_class_init (IBusFactoryClass *klass)
113 {
114     // GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
115     IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
116
117     factory_parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass);
118
119     g_type_class_add_private (klass, sizeof (IBusFactoryPrivate));
120
121     ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_destroy;
122
123     IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_factory_ibus_message;
124
125 }
126
127 static void
128 ibus_factory_init (IBusFactory *factory)
129 {
130     IBusFactoryPrivate *priv;
131     priv = IBUS_FACTORY_GET_PRIVATE (factory);
132
133     priv->id = 0;
134     priv->connection = NULL;
135     priv->engine_table = g_hash_table_new_full (g_str_hash,
136                                                 g_str_equal,
137                                                 g_free,
138                                                 NULL);
139     priv->engine_list =  NULL;
140 }
141
142 static void
143 ibus_factory_destroy (IBusFactory *factory)
144 {
145     GList *list;
146     IBusFactoryPrivate *priv;
147     priv = IBUS_FACTORY_GET_PRIVATE (factory);
148
149     list = g_list_copy (priv->engine_list);
150     g_list_foreach (list, (GFunc) ibus_object_destroy, NULL);
151     g_list_free (priv->engine_list);
152     g_list_free (list);
153     priv->engine_list = NULL;
154
155     if (priv->engine_table) {
156         g_hash_table_destroy (priv->engine_table);
157     }
158
159     if (priv->connection) {
160         ibus_service_remove_from_connection ((IBusService *)factory,
161                                              priv->connection);
162         g_object_unref (priv->connection);
163     }
164
165     IBUS_OBJECT_CLASS(factory_parent_class)->destroy (IBUS_OBJECT (factory));
166 }
167
168 static void
169 _engine_destroy_cb (IBusEngine  *engine,
170                     IBusFactory *factory)
171 {
172     IBusFactoryPrivate *priv;
173     priv = IBUS_FACTORY_GET_PRIVATE (factory);
174
175     priv->engine_list = g_list_remove (priv->engine_list, engine);
176     g_object_unref (engine);
177 }
178
179 static gboolean
180 ibus_factory_ibus_message (IBusFactory    *factory,
181                            IBusConnection *connection,
182                            IBusMessage    *message)
183 {
184     g_assert (IBUS_IS_FACTORY (factory));
185     g_assert (IBUS_IS_CONNECTION (connection));
186     g_assert (message != NULL);
187
188     IBusMessage *reply_message;
189     IBusFactoryPrivate *priv;
190     priv = IBUS_FACTORY_GET_PRIVATE (factory);
191
192     g_assert (priv->connection == connection);
193
194     if (ibus_message_is_method_call (message,
195                                      IBUS_INTERFACE_FACTORY,
196                                      "CreateEngine")) {
197         gchar *engine_name;
198         gchar *path;
199         IBusError *error;
200         IBusEngine *engine;
201         gboolean retval;
202         GType engine_type;
203
204         retval = ibus_message_get_args (message,
205                                         &error,
206                                         G_TYPE_STRING, &engine_name,
207                                         G_TYPE_INVALID);
208
209         if (!retval) {
210             reply_message = ibus_message_new_error_printf (message,
211                                         DBUS_ERROR_INVALID_ARGS,
212                                         "The 1st arg should be engine name");
213             ibus_connection_send (connection, reply_message);
214             ibus_message_unref (reply_message);
215             return TRUE;
216         }
217
218         engine_type = (GType )g_hash_table_lookup (priv->engine_table, engine_name);
219
220         if (engine_type == G_TYPE_INVALID) {
221              reply_message = ibus_message_new_error_printf (message,
222                                         DBUS_ERROR_FAILED,
223                                         "Can not create engine %s", engine_name);
224             ibus_connection_send (connection, reply_message);
225             ibus_message_unref (reply_message);
226             return TRUE;
227
228         }
229
230         path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d", ++priv->id);
231
232         engine = g_object_new (engine_type,
233                                "name", engine_name,
234                                "path", path,
235                                "connection", priv->connection,
236                                NULL);
237
238         priv->engine_list = g_list_append (priv->engine_list, engine);
239         g_signal_connect (engine,
240                           "destroy",
241                           G_CALLBACK (_engine_destroy_cb),
242                           factory);
243
244         reply_message = ibus_message_new_method_return (message);
245         ibus_message_append_args (reply_message,
246                                   IBUS_TYPE_OBJECT_PATH, &path,
247                                   G_TYPE_INVALID);
248         g_free (path);
249         ibus_connection_send (connection, reply_message);
250         ibus_message_unref (reply_message);
251         return TRUE;
252     }
253
254     return factory_parent_class->ibus_message ((IBusService *)factory,
255                                                connection,
256                                                message);
257 }
258
259 void
260 ibus_factory_add_engine (IBusFactory *factory,
261                          const gchar *engine_name,
262                          GType        engine_type)
263 {
264     g_assert (IBUS_IS_FACTORY (factory));
265     g_assert (engine_name);
266     g_assert (g_type_is_a (engine_type, IBUS_TYPE_ENGINE));
267
268     IBusFactoryPrivate *priv;
269     priv = IBUS_FACTORY_GET_PRIVATE (factory);
270
271     g_hash_table_insert (priv->engine_table, g_strdup (engine_name), (gpointer) engine_type);
272 }
273
274 #if 0
275 IBusFactoryInfo *
276 ibus_factory_get_info (IBusFactory *factory)
277 {
278     IBusFactoryPrivate *priv;
279     priv = IBUS_FACTORY_GET_PRIVATE (factory);
280
281     return priv->info;
282 }
283 #endif
284
285 GType
286 ibus_factory_info_get_type (void)
287 {
288     static GType type = 0;
289
290     static const GTypeInfo type_info = {
291         sizeof (IBusFactoryInfoClass),
292         (GBaseInitFunc)     NULL,
293         (GBaseFinalizeFunc) NULL,
294         (GClassInitFunc)    ibus_factory_info_class_init,
295         NULL,               /* class finialize */
296         NULL,               /* class data */
297         sizeof (IBusFactoryInfo),
298         0,
299         (GInstanceInitFunc) ibus_factory_info_init,
300     };
301
302     if (type == 0) {
303         type = g_type_register_static (IBUS_TYPE_SERIALIZABLE,
304                                        "IBusFactoryInfo",
305                                        &type_info,
306                                        0);
307     }
308
309     return type;
310 }
311
312 static void
313 ibus_factory_info_class_init (IBusFactoryInfoClass *klass)
314 {
315     IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass);
316     IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass);
317
318     factory_info_parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass);
319
320     object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_info_destroy;
321
322     serializable_class->serialize   = (IBusSerializableSerializeFunc) ibus_factory_info_serialize;
323     serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_factory_info_deserialize;
324     serializable_class->copy        = (IBusSerializableCopyFunc) ibus_factory_info_copy;
325
326     g_string_append (serializable_class->signature, "osssss");
327 }
328
329 static void
330 ibus_factory_info_init (IBusFactoryInfo *info)
331 {
332     info->path = NULL;
333     info->name = NULL;
334     info->lang = NULL;
335     info->icon = NULL;
336     info->authors = NULL;
337     info->credits = NULL;
338 }
339
340 static void
341 ibus_factory_info_destroy (IBusFactoryInfo *info)
342 {
343     g_free (info->path);
344     g_free (info->name);
345     g_free (info->lang);
346     g_free (info->icon);
347     g_free (info->authors);
348     g_free (info->credits);
349
350     info->path = NULL;
351     info->lang = NULL;
352     info->name = NULL;
353     info->icon = NULL;
354     info->authors = NULL;
355     info->credits = NULL;
356
357     IBUS_OBJECT_CLASS (factory_info_parent_class)->destroy ((IBusObject *)info);
358 }
359
360 static gboolean
361 ibus_factory_info_serialize (IBusFactoryInfo *info,
362                              IBusMessageIter *iter)
363 {
364     gboolean retval;
365
366     retval = factory_info_parent_class->serialize ((IBusSerializable *)info, iter);
367     g_return_val_if_fail (retval, FALSE);
368
369     retval = ibus_message_iter_append (iter, IBUS_TYPE_OBJECT_PATH, &info->path);
370     g_return_val_if_fail (retval, FALSE);
371
372     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->name);
373     g_return_val_if_fail (retval, FALSE);
374
375     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->lang);
376     g_return_val_if_fail (retval, FALSE);
377
378     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->icon);
379     g_return_val_if_fail (retval, FALSE);
380
381     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->authors);
382     g_return_val_if_fail (retval, FALSE);
383
384     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->credits);
385     g_return_val_if_fail (retval, FALSE);
386
387     return TRUE;
388 }
389
390 static gboolean
391 ibus_factory_info_deserialize (IBusFactoryInfo *info,
392                                IBusMessageIter *iter)
393 {
394     gboolean retval;
395
396     retval = factory_info_parent_class->deserialize ((IBusSerializable *)info, iter);
397     g_return_val_if_fail (retval, FALSE);
398
399     retval = ibus_message_iter_get (iter, IBUS_TYPE_OBJECT_PATH, &info->path);
400     g_return_val_if_fail (retval, FALSE);
401     info->path = g_strdup (info->path);
402
403     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->name);
404     g_return_val_if_fail (retval, FALSE);
405     info->name = g_strdup (info->name);
406
407     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->lang);
408     g_return_val_if_fail (retval, FALSE);
409     info->lang = g_strdup (info->lang);
410
411     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->icon);
412     g_return_val_if_fail (retval, FALSE);
413     info->icon = g_strdup (info->icon);
414
415     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->authors);
416     g_return_val_if_fail (retval, FALSE);
417     info->authors = g_strdup (info->authors);
418
419     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->credits);
420     g_return_val_if_fail (retval, FALSE);
421     info->credits = g_strdup (info->credits);
422
423     return TRUE;
424 }
425
426 static gboolean
427 ibus_factory_info_copy (IBusFactoryInfo       *dest,
428                         const IBusFactoryInfo *src)
429 {
430     gboolean retval;
431
432     retval = factory_info_parent_class->copy ((IBusSerializable *)dest,
433                                               (IBusSerializable *)src);
434     g_return_val_if_fail (retval, FALSE);
435
436     g_return_val_if_fail (IBUS_IS_FACTORY_INFO (dest), FALSE);
437     g_return_val_if_fail (IBUS_IS_FACTORY_INFO (src), FALSE);
438
439     dest->path = g_strdup (src->path);
440     dest->name = g_strdup (src->name);
441     dest->lang = g_strdup (src->lang);
442     dest->icon = g_strdup (src->icon);
443     dest->authors = g_strdup (src->authors);
444     dest->credits = g_strdup (src->credits);
445
446     return TRUE;
447 }
448
449 IBusFactoryInfo *
450 ibus_factory_info_new (const gchar *path,
451                        const gchar *name,
452                        const gchar *lang,
453                        const gchar *icon,
454                        const gchar *authors,
455                        const gchar *credits)
456 {
457     g_assert (path);
458     g_assert (name);
459     g_assert (lang);
460     g_assert (icon);
461     g_assert (authors);
462     g_assert (credits);
463
464     IBusFactoryInfo *info;
465
466     info = (IBusFactoryInfo *) g_object_new (IBUS_TYPE_FACTORY_INFO, NULL);
467
468     info->path = g_strdup (path);
469     info->name = g_strdup (name);
470     info->lang = g_strdup (lang);
471     info->icon = g_strdup (icon);
472     info->authors = g_strdup (authors);
473     info->credits = g_strdup (credits);
474
475     return info;
476 }
477
478