Improved commentary.
[irreco.git] / irreco / src / core / irreco_backend_instance.c
blob3677bca9da02b7b5c845b58964367b00eb3e3b3f
1 /*
2 * irreco - Ir Remote Control
3 * Copyright (C) 2007 Arto Karppinen (arto.karppinen@iki.fi)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program 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
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "irreco_backend_instance.h"
21 #include "irreco_config.h"
22 #include "irreco_backend_err_dlg.h"
24 /**
25 * @typedef IrrecoBackendInstance
27 * Since it is possible that there are, for exmaple, several LIRC servers the
28 * user wants to use, we should make sure that the user can use several LIRC
29 * servers.
31 * Because of this every backend should be programmed so, that it is possible to
32 * create several instances of them by calling irreco_backend_create() several
33 * times. Ofcourse, if there are several instances of the same backend around,
34 * then those instances must also be properly handled inside Irreco, which is
35 * exactly what this file should do.
40 /**
41 * Backend instance will call create() from the backend lib, and
42 * allocate structures for the instance.
44 IrrecoBackendInstance *
45 irreco_backend_instance_create(IrrecoBackendLib * backend_lib,
46 IrrecoData *irreco_data)
48 IrrecoBackendInstance *self;
49 IRRECO_ENTER
51 g_assert(backend_lib != NULL);
53 self = g_slice_new0(IrrecoBackendInstance);
54 self->irreco_data = irreco_data;
55 self->lib = backend_lib;
56 self->irreco_cmd_dependencies = g_ptr_array_new();
58 IRRECO_BACKEND_ENTER(self, "create()");
59 self->contex = self->lib->api->create();
60 IRRECO_BACKEND_RETURN("create()");
62 if (self->contex == NULL) {
63 g_slice_free(IrrecoBackendInstance, self);
64 IRRECO_RETURN_PTR(NULL);
67 self->device_list = irreco_string_table_new(
68 G_DESTROYNOTIFY(irreco_backend_device_destroy), NULL);
70 IRRECO_RETURN_PTR(self);
73 void irreco_backend_instance_destroy(IrrecoBackendInstance *self)
75 IRRECO_ENTER
76 irreco_backend_instance_destroy_full(self, FALSE);
77 IRRECO_RETURN
80 /**
81 * Handle the destruction of the instance and device list.
83 void irreco_backend_instance_destroy_full(IrrecoBackendInstance *self,
84 gboolean permanently)
86 IRRECO_ENTER
88 if (self == NULL) IRRECO_RETURN
90 /* Remove all IrrecoCmd dependencies. */
91 IRRECO_PTR_ARRAY_BACKWARDS(self->irreco_cmd_dependencies,
92 IrrecoCmd *, command)
93 irreco_cmd_set_builtin(command, IRRECO_COMMAND_NONE);
94 IRRECO_PTR_ARRAY_FORWARDS_END
95 g_ptr_array_free(self->irreco_cmd_dependencies, TRUE);
97 /* Notify library of destruction. */
98 IRRECO_BACKEND_ENTER(self, "destroy()");
99 self->lib->api->destroy(self->contex,
100 permanently);
101 IRRECO_BACKEND_RETURN("destroy()");
103 /* Cleanup lib assosiated stuff. */
104 irreco_string_table_free(self->device_list);
105 g_free(self->config);
106 self->config = NULL;
108 /* Free name and description. */
109 g_free(self->name);
110 self->name = NULL;
111 g_free(self->description);
112 self->description = NULL;
113 g_free(self->name_and_description);
114 self->name_and_description = NULL;
116 g_slice_free(IrrecoBackendInstance, self);
117 IRRECO_RETURN
120 void irreco_backend_instance_add_cmd_dependency(IrrecoBackendInstance *self,
121 IrrecoCmd * command)
123 IRRECO_ENTER
124 g_ptr_array_add(self->irreco_cmd_dependencies, command);
126 IRRECO_RETURN
129 void
130 irreco_backend_instance_remove_cmd_dependency(IrrecoBackendInstance *self,
131 IrrecoCmd * command)
133 IRRECO_ENTER
134 g_ptr_array_remove_fast(self->irreco_cmd_dependencies,
135 command);
137 IRRECO_RETURN
140 gboolean irreco_backend_instance_check_status(IrrecoBackendInstance *self,
141 IrrecoBackendStatus status)
143 IRRECO_ENTER
145 if (status != IRRECO_BACKEND_OK) {
146 GString *string;
147 const gchar *error_msg;
148 const gchar *name;
150 IRRECO_BACKEND_ENTER(self, "get_error_msg()");
151 error_msg = self->lib->api->get_error_msg(
152 self->contex, status);
153 IRRECO_BACKEND_RETURN("get_error_msg()");
155 /* Print description if it is available. */
156 if (self->name_and_description) {
157 name = self->name_and_description;
158 } else {
159 name = self->name;
162 string = g_string_new(NULL);
163 g_string_printf(string, "%i", status);
164 irreco_show_backend_err_dlg(
165 irreco_window_manager_get_gtk_window(
166 self->irreco_data->window_manager),
167 self->lib->name, name, string->str, error_msg);
168 g_string_free(string, TRUE);
170 IRRECO_RETURN_BOOL(FALSE);
172 IRRECO_RETURN_BOOL(TRUE);
176 * DO NOT CALL DIRECTLY, use irreco_backend_manager_set_instance_name()
178 void irreco_backend_instance_set_name(IrrecoBackendInstance *self,
179 gchar * name)
181 IRRECO_ENTER;
182 g_free(self->name);
183 self->name = g_strdup(name);
185 IRRECO_RETURN
189 * DO NOT CALL DIRECTLY, use irreco_backend_manager_set_instance_config()
191 void irreco_backend_instance_set_config(IrrecoBackendInstance *self,
192 gchar * config)
194 IRRECO_ENTER;
195 g_free(self->config);
196 self->config = g_strdup(config);
198 IRRECO_RETURN
202 * Get description of the instance.
204 * The description can also be found at self->description.
206 const gchar *
207 irreco_backend_instance_get_description(IrrecoBackendInstance *self)
209 IRRECO_ENTER
211 g_free(self->description);
212 self->description = NULL;
214 if (self->lib->api->get_description == NULL) {
215 IRRECO_RETURN_PTR(NULL);
216 } else {
217 IRRECO_BACKEND_ENTER(self, "get_description()");
218 self->description =
219 self->lib->api->get_description(
220 self->contex);
221 IRRECO_BACKEND_RETURN("get_description()");
222 IRRECO_RETURN_PTR(self->description);
226 const gchar *
227 irreco_backend_instance_get_name_and_description(IrrecoBackendInstance *self)
229 GString *string;
230 IRRECO_ENTER
232 g_free(self->name_and_description);
233 self->name_and_description = NULL;
235 if (self->name == NULL) IRRECO_RETURN_PTR(NULL);
237 string = g_string_new(self->name);
238 if (irreco_backend_instance_get_description(self) != NULL) {
239 g_string_append(string, " - ");
240 g_string_append(string, self->description);
243 self->name_and_description = g_string_free(string, FALSE);
244 IRRECO_RETURN_PTR(self->name_and_description);
249 * Call irreco_backend_read_from_conf() inside the backend.
251 gboolean irreco_backend_instance_read_from_conf(IrrecoBackendInstance *self)
253 gchar *filepath;
254 IrrecoBackendStatus status;
255 IRRECO_ENTER
257 if (self->config == NULL) {
258 IRRECO_ERROR("Config file is not set. Cannot read config "
259 "of instance \"%s\"\n", self->name);
262 filepath = irreco_get_config_file("irreco", self->config);
263 IRRECO_BACKEND_ENTER(self, "from_conf()");
264 status = self->lib->api->from_conf(
265 self->contex, filepath);
266 IRRECO_BACKEND_RETURN("from_conf()");
267 g_free(filepath);
268 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
269 self, status));
273 * Call irreco_backend_save_to_conf() inside the backend.
275 gboolean irreco_backend_instance_save_to_conf(IrrecoBackendInstance *self)
277 gchar *filepath;
278 IrrecoBackendStatus status;
279 IRRECO_ENTER
281 if (self->config == NULL) {
282 IRRECO_ERROR("Config file is not set. Cannot save config "
283 "of instance \"%s\"\n", self->name);
286 filepath = irreco_get_config_file("irreco", self->config);
287 IRRECO_BACKEND_ENTER(self, "to_conf()");
288 status = self->lib->api->to_conf(
289 self->contex, filepath);
290 IRRECO_BACKEND_RETURN("to_conf()");
291 g_free(filepath);
292 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self, status));
296 * Send command.
298 * This function takes device and command name as strings for a purpose.
299 * Because the list of supported commands and devices for some instance
300 * of a backend depend on the configuration of the backend, and because
301 * you cant assume that the configuration remains the same, you cannot
302 * assume that the structures allocated by irreco to store those commands
303 * will exist in the future.
305 * So the proper way to do this is to take a copy of device name and command
306 * name, and when were sending command, to check if the command still exists.
308 gboolean irreco_backend_instance_send_command(IrrecoBackendInstance *self,
309 const gchar *device_name,
310 const gchar *command_name)
312 IrrecoBackendStatus status;
313 IrrecoBackendDevice *device;
314 gpointer command_contex;
315 IRRECO_ENTER
317 IRRECO_PRINTF("Sending command \"%s\" to device \"%s\".\n",
318 command_name, device_name);
320 /* Find device. */
321 if (!irreco_string_table_get(self->device_list, device_name,
322 (gpointer *) &device)) {
323 IRRECO_ERROR("Cant send command \"%s\" to device \"%s\" "
324 "because no such device exists.\n",
325 command_name, device_name);
326 IRRECO_RETURN_BOOL(FALSE);
329 /* Find command contex. */
330 if (!irreco_string_table_get(device->command_list, command_name,
331 (gpointer *) &command_contex)) {
332 IRRECO_ERROR("Cant send command \"%s\" to device \"%s\" "
333 "because device does not support that command.\n",
334 command_name, device_name);
335 IRRECO_RETURN_BOOL(FALSE);
338 /* Send command*/
339 IRRECO_BACKEND_ENTER(self, "send_command()");
340 status = self->lib->api->send_command(
341 self->contex,
342 device_name,
343 device->contex,
344 command_name,
345 command_contex);
346 IRRECO_BACKEND_RETURN("send_command()");
347 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
348 self, status));
351 void irreco_backend_instance_configure(IrrecoBackendInstance *self,
352 GtkWindow *parent)
354 IrrecoBackendStatus status;
355 IRRECO_ENTER
357 IRRECO_BACKEND_ENTER(self, "configure()");
358 status = self->lib->api->configure(
359 self->contex, parent);
360 IRRECO_BACKEND_RETURN("configure()");
361 irreco_backend_instance_check_status(self, status);
363 IRRECO_RETURN
366 void irreco_backend_instance_create_device(IrrecoBackendInstance *self,
367 GtkWindow *parent)
369 IrrecoBackendStatus status;
370 IRRECO_ENTER
372 IRRECO_BACKEND_ENTER(self, "create_device()");
373 status = self->lib->api->create_device(
374 self->contex, parent);
375 IRRECO_BACKEND_RETURN("create_device()");
376 irreco_backend_instance_check_status(self, status);
378 IRRECO_RETURN
383 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
384 /* Device / Command management */
385 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
388 * Used by callbacks
390 IrrecoBackendInstance *current_backend_instance = NULL;
391 IrrecoBackendDevice *current_device = NULL;
393 void irreco_backend_get_device_callback(const gchar *name,
394 gpointer device_contex)
396 IrrecoBackendDevice *backend_device;
397 IRRECO_ENTER
399 if (current_backend_instance == NULL) {
400 IRRECO_ERROR("Variable current_backend_instance is not set.\n");
401 IRRECO_RETURN
403 if (name == NULL) {
404 IRRECO_ERROR("Device name is NULL. "
405 "Device name must be given\n");
406 IRRECO_RETURN
409 if (!irreco_string_table_exists(current_backend_instance->device_list,
410 name)) {
411 backend_device = irreco_backend_device_create(
412 name, current_backend_instance, device_contex);
413 irreco_string_table_add(current_backend_instance->device_list,
414 backend_device->name, backend_device);
415 IRRECO_PRINTF("Device \"%s\" added.\n", backend_device->name);
418 IRRECO_RETURN
421 void irreco_backend_get_command_callback(const gchar *name,
422 gpointer command_contex)
424 IRRECO_ENTER
425 if (current_device == NULL) {
426 IRRECO_ERROR("Variable current_device is not set.\n");
427 IRRECO_RETURN
429 if (name == NULL) {
430 IRRECO_ERROR("Command name is NULL. "
431 "Command name must be given\n");
432 IRRECO_RETURN
435 if (!irreco_string_table_exists(current_device->command_list, name)) {
436 irreco_string_table_add(current_device->command_list,
437 name, command_contex);
438 IRRECO_PRINTF("Command \"%s\" added.\n", name);
441 IRRECO_RETURN
445 * This function will first get a list of devices from the backend instance,
446 * and after that get a list of commands for every device. After this,
447 * Irreco should have a complete list of commands the backend instance provides.
449 void irreco_backend_instance_get_devcmd_list(IrrecoBackendInstance *self)
451 IrrecoBackendStatus status;
452 IRRECO_ENTER
454 /* Destroy old data. */
455 irreco_string_table_remove_all(self->device_list);
457 /* Fetch a list of devices. */
458 current_backend_instance = self;
459 IRRECO_BACKEND_ENTER(self, "get_devices()");
460 status = self->lib->api->get_devices(
461 self->contex, irreco_backend_get_device_callback);
462 IRRECO_BACKEND_RETURN("get_devices()");
463 irreco_backend_instance_check_status(self, status);
464 current_backend_instance = NULL;
466 /* Fetch all commands from all devices. */
467 IRRECO_BACKEND_INSTANCE_FOREACH(self, backend_device)
468 IRRECO_PRINTF("Getting commands of device \"%s\".\n",
469 backend_device->name);
471 current_device = backend_device;
473 IRRECO_BACKEND_ENTER(self, "get_commands()");
474 status = self->lib->api->get_commands(
475 self->contex,
476 backend_device->name,
477 backend_device->contex,
478 irreco_backend_get_command_callback);
479 IRRECO_BACKEND_RETURN("get_commands()");
480 irreco_backend_instance_check_status(self, status);
482 current_device = NULL;
483 irreco_string_table_sort_abc(backend_device->command_list);
484 IRRECO_BACKEND_INSTANCE_FOREACH_END
485 irreco_string_table_sort_abc(self->device_list);
487 IRRECO_RETURN
490 gboolean irreco_backend_instance_export_conf(IrrecoBackendInstance *self,
491 const char * device_name,
492 IrrecoBackendFileContainer **file_container)
494 IrrecoBackendStatus status;
495 IRRECO_ENTER
497 IRRECO_BACKEND_ENTER(self, "export_conf()");
498 status = self->lib->api->export_conf(self->contex, device_name,
499 file_container);
500 IRRECO_BACKEND_RETURN("export_conf()");
502 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self, status));
505 gboolean irreco_backend_instance_import_conf(IrrecoBackendInstance *self,
506 IrrecoBackendFileContainer *file_container)
508 IrrecoBackendStatus status;
509 IRRECO_ENTER
511 IRRECO_BACKEND_ENTER(self, "import_conf()");
512 status = self->lib->api->import_conf(self->contex, file_container);
513 IRRECO_BACKEND_RETURN("import_conf()");
515 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self, status));
518 gboolean irreco_backend_instance_check_conf(IrrecoBackendInstance *self,
519 IrrecoBackendFileContainer *file_container)
521 IrrecoBackendStatus status;
522 gboolean file_exist = TRUE;
523 IRRECO_ENTER
525 IRRECO_BACKEND_ENTER(self, "check_conf()");
526 status = self->lib->api->check_conf(self->contex, file_container,
527 &file_exist);
528 IRRECO_BACKEND_RETURN("check_conf()");
530 irreco_backend_instance_check_status(self, status);
532 IRRECO_RETURN_BOOL(file_exist);