Mostly minor fixes up until version 0.8.10.
[irreco.git] / irreco / src / core / irreco_backend_instance.c
blobc779fb8f55471e7cfb681e635e997b02dd51c8b5
1 /*
2 * irreco - Ir Remote Control
3 * Copyright (C) 2007 Arto Karppinen (arto.karppinen@iki.fi)
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.
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 * @addtogroup IrrecoBackendInstance
26 * @ingroup Irreco
28 * Since it is possible that there are, for exmaple, several LIRC servers the
29 * user wants to use, we should make sure that the user can use several LIRC
30 * servers.
32 * Because of this every backend should be programmed so, that it is possible to
33 * create several instances of them by calling irreco_backend_create() several
34 * times. Ofcourse, if there are several instances of the same backend around,
35 * then those instances must also be properly handled inside Irreco, which is
36 * exactly what this file should do.
38 * Backend instance will call create() from the backend lib, and
39 * allocate structures for the instance.
41 * @{
44 /**
45 * @file
46 * Source file of @ref IrrecoBackendInstance.
50 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
51 /* Construction & Destruction */
52 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
54 /**
55 * @name Construction & Destruction
56 * @{
59 IrrecoBackendInstance *
60 irreco_backend_instance_create(IrrecoBackendLib * backend_lib,
61 IrrecoData *irreco_data)
63 IrrecoBackendInstance *self;
64 IRRECO_ENTER
66 g_assert(backend_lib != NULL);
68 self = g_slice_new0(IrrecoBackendInstance);
69 self->irreco_data = irreco_data;
70 self->name = g_string_new(NULL);
71 self->description = g_string_new(NULL);
72 self->name_and_description = g_string_new(NULL);
73 self->lib = backend_lib;
74 self->irreco_cmd_dependencies = g_ptr_array_new();
76 IRRECO_BACKEND_ENTER(self, "create()");
77 self->contex = self->lib->api->create();
78 IRRECO_BACKEND_RETURN("create()");
80 if (self->contex == NULL) {
81 g_slice_free(IrrecoBackendInstance, self);
82 IRRECO_RETURN_PTR(NULL);
85 self->device_list = irreco_string_table_new(
86 G_DESTROYNOTIFY(irreco_backend_device_destroy), NULL);
88 IRRECO_RETURN_PTR(self);
91 void irreco_backend_instance_destroy(IrrecoBackendInstance *self)
93 IRRECO_ENTER
94 irreco_backend_instance_destroy_full(self, FALSE);
95 IRRECO_RETURN
98 /**
99 * Handle the destruction of the instance and device list.
101 void irreco_backend_instance_destroy_full(IrrecoBackendInstance *self,
102 gboolean permanently)
104 IRRECO_ENTER
106 if (self == NULL) IRRECO_RETURN
108 /* Remove all IrrecoCmd dependencies. */
109 IRRECO_PTR_ARRAY_BACKWARDS(self->irreco_cmd_dependencies,
110 IrrecoCmd *, command)
111 irreco_cmd_set_builtin(command, IRRECO_COMMAND_NONE);
112 IRRECO_PTR_ARRAY_FORWARDS_END
113 g_ptr_array_free(self->irreco_cmd_dependencies, TRUE);
115 /* Notify library of destruction. */
116 IRRECO_BACKEND_ENTER(self, "destroy()");
117 self->lib->api->destroy(self->contex,
118 permanently);
119 IRRECO_BACKEND_RETURN("destroy()");
121 /* Cleanup lib assosiated stuff. */
122 irreco_string_table_free(self->device_list);
123 g_free(self->config);
124 self->config = NULL;
126 /* Free name and description. */
127 g_string_free(self->name, TRUE);
128 self->name = NULL;
129 g_string_free(self->description, TRUE);
130 self->description = NULL;
131 g_string_free(self->name_and_description, TRUE);
132 self->name_and_description = NULL;
134 g_slice_free(IrrecoBackendInstance, self);
135 IRRECO_RETURN
138 /** @} */
142 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
143 /* Public Functions */
144 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
147 * @name Public Functions
148 * @{
152 * Does this instance support editable devices API?
154 * @return TRUE if supported, FALSE otherwise.
156 gboolean irreco_backend_instance_api_edit(IrrecoBackendInstance *self)
158 if (self->lib->api->flags & IRRECO_BACKEND_EDITABLE_DEVICES) {
159 IRRECO_RETURN_BOOL(TRUE);
161 IRRECO_RETURN_BOOL(FALSE);
165 * Does this instance support command export API?
167 * @return TRUE if supported, FALSE otherwise.
169 gboolean irreco_backend_instance_api_export(IrrecoBackendInstance *self)
171 if (self->lib->api->flags & IRRECO_BACKEND_CONFIGURATION_EXPORT) {
172 IRRECO_RETURN_BOOL(TRUE);
174 IRRECO_RETURN_BOOL(FALSE);
177 void irreco_backend_instance_add_cmd_dependency(IrrecoBackendInstance *self,
178 IrrecoCmd * command)
180 IRRECO_ENTER
181 g_ptr_array_add(self->irreco_cmd_dependencies, command);
183 IRRECO_RETURN
186 void
187 irreco_backend_instance_remove_cmd_dependency(IrrecoBackendInstance *self,
188 IrrecoCmd * command)
190 IRRECO_ENTER
191 g_ptr_array_remove_fast(self->irreco_cmd_dependencies,
192 command);
194 IRRECO_RETURN
197 gboolean irreco_backend_instance_check_status(IrrecoBackendInstance *self,
198 IrrecoBackendStatus status)
200 IRRECO_ENTER
202 if (status != IRRECO_BACKEND_OK) {
203 GString *string;
204 const gchar *error_msg;
205 const gchar *name;
207 IRRECO_BACKEND_ENTER(self, "get_error_msg()");
208 error_msg = self->lib->api->get_error_msg(
209 self->contex, status);
210 IRRECO_BACKEND_RETURN("get_error_msg()");
212 /* Print description if it is available. */
213 if (irreco_str_isempty(self->name_and_description->str)) {
214 name = self->name_and_description->str;
215 } else {
216 name = self->name->str;
219 string = g_string_new(NULL);
220 g_string_printf(string, "%i", status);
221 irreco_show_backend_err_dlg(
222 irreco_window_manager_get_gtk_window(
223 self->irreco_data->window_manager),
224 self->lib->name, name, string->str, error_msg);
225 g_string_free(string, TRUE);
227 IRRECO_RETURN_BOOL(FALSE);
229 IRRECO_RETURN_BOOL(TRUE);
233 * DO NOT CALL DIRECTLY, use irreco_backend_manager_set_instance_name()
235 * @sa irreco_backend_manager_set_instance_name
237 void irreco_backend_instance_set_name(IrrecoBackendInstance *self,
238 gchar * name)
240 IRRECO_ENTER;
242 g_string_assign(self->name, name);
243 IRRECO_RETURN
247 * DO NOT CALL DIRECTLY, use irreco_backend_manager_set_instance_config()
249 * @sa irreco_backend_manager_set_instance_config
251 void irreco_backend_instance_set_config(IrrecoBackendInstance *self,
252 gchar * config)
254 IRRECO_ENTER;
255 g_free(self->config);
256 self->config = g_strdup(config);
258 IRRECO_RETURN
262 * Get name of the instance.
264 const gchar *
265 irreco_backend_instance_get_name(IrrecoBackendInstance *self)
267 IRRECO_ENTER
269 if (irreco_str_isempty(self->name->str)) {
270 IRRECO_RETURN_PTR(NULL);
271 } else {
272 IRRECO_RETURN_CONST_STR(self->name->str);
277 * Get description of the instance.
279 const gchar *
280 irreco_backend_instance_get_description(IrrecoBackendInstance *self)
282 IRRECO_ENTER
284 if (self->lib->api->get_description == NULL) {
285 g_string_assign(self->description, "");
287 } else {
288 gchar *description = NULL;
290 IRRECO_BACKEND_ENTER(self, "get_description()");
291 description = self->lib->api->get_description(self->contex);
292 IRRECO_BACKEND_RETURN("get_description()");
294 g_string_assign(self->description, description);
295 g_free(description);
298 if (irreco_str_isempty(self->description->str)) {
299 IRRECO_RETURN_PTR(NULL);
300 } else {
301 IRRECO_RETURN_CONST_STR(self->description->str);
306 * Get name and description of the instance in one string.
308 const gchar *
309 irreco_backend_instance_get_name_and_description(IrrecoBackendInstance *self)
311 IRRECO_ENTER
313 if (irreco_str_isempty(self->name->str)) {
314 g_string_assign(self->name_and_description, "");
315 } else if (irreco_backend_instance_get_description(self)) {
316 g_string_printf(self->name_and_description,
317 "%s - %s", self->name->str,
318 self->description->str);
319 } else {
320 g_string_assign(self->name_and_description, self->name->str);
323 if (irreco_str_isempty(self->name->str)) {
324 IRRECO_RETURN_PTR(NULL);
325 } else {
326 IRRECO_RETURN_CONST_STR(self->name_and_description->str);
331 * Call irreco_backend_read_from_conf() inside the backend.
333 gboolean irreco_backend_instance_read_from_conf(IrrecoBackendInstance *self)
335 gchar *filepath;
336 IrrecoBackendStatus status;
337 IRRECO_ENTER
339 if (self->config == NULL) {
340 IRRECO_ERROR("Config file is not set. Cannot read config "
341 "of instance \"%s\"\n", self->name->str);
344 filepath = irreco_get_config_file("irreco", self->config);
345 IRRECO_BACKEND_ENTER(self, "from_conf()");
346 status = self->lib->api->from_conf(
347 self->contex, filepath);
348 IRRECO_BACKEND_RETURN("from_conf()");
349 g_free(filepath);
350 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
351 self, status));
355 * Call irreco_backend_save_to_conf() inside the backend.
357 gboolean irreco_backend_instance_save_to_conf(IrrecoBackendInstance *self)
359 gchar *filepath;
360 IrrecoBackendStatus status;
361 IRRECO_ENTER
363 if (self->config == NULL) {
364 IRRECO_ERROR("Config file is not set. Cannot save config "
365 "of instance \"%s\"\n", self->name->str);
368 filepath = irreco_get_config_file("irreco", self->config);
369 IRRECO_BACKEND_ENTER(self, "to_conf()");
370 status = self->lib->api->to_conf(
371 self->contex, filepath);
372 IRRECO_BACKEND_RETURN("to_conf()");
373 g_free(filepath);
374 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self, status));
378 * Send command.
380 * This function takes device and command name as strings for a purpose.
381 * Because the list of supported commands and devices for some instance
382 * of a backend depend on the configuration of the backend, and because
383 * you cant assume that the configuration remains the same, you cannot
384 * assume that the structures allocated by irreco to store those commands
385 * will exist in the future.
387 * So the proper way to do this is to take a copy of device name and command
388 * name, and when were sending command, to check if the command still exists.
390 gboolean irreco_backend_instance_send_command(IrrecoBackendInstance *self,
391 const gchar *device_name,
392 const gchar *command_name)
394 IrrecoBackendStatus status;
395 IrrecoBackendDevice *device;
396 gpointer command_contex;
397 IRRECO_ENTER
399 IRRECO_PRINTF("Sending command \"%s\" to device \"%s\".\n",
400 command_name, device_name);
402 /* Find device. */
403 if (!irreco_string_table_get(self->device_list, device_name,
404 (gpointer *) &device)) {
405 IRRECO_ERROR("Cant send command \"%s\" to device \"%s\" "
406 "because no such device exists.\n",
407 command_name, device_name);
408 IRRECO_RETURN_BOOL(FALSE);
411 /* Find command contex. */
412 if (!irreco_string_table_get(device->command_list, command_name,
413 (gpointer *) &command_contex)) {
414 IRRECO_ERROR("Cant send command \"%s\" to device \"%s\" "
415 "because device does not support that command.\n",
416 command_name, device_name);
417 IRRECO_RETURN_BOOL(FALSE);
420 /* Send command*/
421 IRRECO_BACKEND_ENTER(self, "send_command()");
422 status = self->lib->api->send_command(
423 self->contex,
424 device_name,
425 device->contex,
426 command_name,
427 command_contex);
428 IRRECO_BACKEND_RETURN("send_command()");
429 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
430 self, status));
433 void irreco_backend_instance_configure(IrrecoBackendInstance *self,
434 GtkWindow *parent)
436 IrrecoBackendStatus status;
437 IRRECO_ENTER
439 IRRECO_BACKEND_ENTER(self, "configure()");
440 status = self->lib->api->configure(
441 self->contex, parent);
442 IRRECO_BACKEND_RETURN("configure()");
443 irreco_backend_instance_check_status(self, status);
445 IRRECO_RETURN
448 void irreco_backend_instance_create_device(IrrecoBackendInstance *self,
449 GtkWindow *parent)
451 IrrecoBackendStatus status;
452 IRRECO_ENTER
454 IRRECO_BACKEND_ENTER(self, "create_device()");
455 status = self->lib->api->create_device(
456 self->contex, parent);
457 IRRECO_BACKEND_RETURN("create_device()");
458 irreco_backend_instance_check_status(self, status);
460 IRRECO_RETURN
463 /** @} */
467 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
468 /* Device / Command management */
469 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
471 * @name Command management
472 * @{
476 * Used by callbacks
478 IrrecoBackendInstance *current_backend_instance = NULL;
479 IrrecoBackendDevice *current_device = NULL;
481 void irreco_backend_get_device_callback(const gchar *name,
482 gpointer device_contex)
484 IrrecoBackendDevice *backend_device;
485 IRRECO_ENTER
487 if (current_backend_instance == NULL) {
488 IRRECO_ERROR("Variable current_backend_instance is not set.\n");
489 IRRECO_RETURN
491 if (name == NULL) {
492 IRRECO_ERROR("Device name is NULL. "
493 "Device name must be given\n");
494 IRRECO_RETURN
497 if (!irreco_string_table_exists(current_backend_instance->device_list,
498 name)) {
499 backend_device = irreco_backend_device_create(
500 name, current_backend_instance, device_contex);
501 irreco_string_table_add(current_backend_instance->device_list,
502 backend_device->name, backend_device);
503 IRRECO_PRINTF("Device \"%s\" added.\n", backend_device->name);
506 IRRECO_RETURN
509 void irreco_backend_get_command_callback(const gchar *name,
510 gpointer command_contex)
512 IRRECO_ENTER
513 if (current_device == NULL) {
514 IRRECO_ERROR("Variable current_device is not set.\n");
515 IRRECO_RETURN
517 if (name == NULL) {
518 IRRECO_ERROR("Command name is NULL. "
519 "Command name must be given\n");
520 IRRECO_RETURN
523 if (!irreco_string_table_exists(current_device->command_list, name)) {
524 irreco_string_table_add(current_device->command_list,
525 name, command_contex);
526 IRRECO_PRINTF("Command \"%s\" added.\n", name);
529 IRRECO_RETURN
533 * This function will first get a list of devices from the backend instance,
534 * and after that get a list of commands for every device. After this,
535 * Irreco should have a complete list of commands the backend instance provides.
537 void irreco_backend_instance_get_devcmd_list(IrrecoBackendInstance *self)
539 IrrecoBackendStatus status;
540 IRRECO_ENTER
542 /* Destroy old data. */
543 irreco_string_table_remove_all(self->device_list);
545 /* Fetch a list of devices. */
546 current_backend_instance = self;
547 IRRECO_BACKEND_ENTER(self, "get_devices()");
548 status = self->lib->api->get_devices(
549 self->contex, irreco_backend_get_device_callback);
550 IRRECO_BACKEND_RETURN("get_devices()");
551 irreco_backend_instance_check_status(self, status);
552 current_backend_instance = NULL;
554 /* Fetch all commands from all devices. */
555 IRRECO_BACKEND_INSTANCE_FOREACH(self, backend_device)
556 IRRECO_PRINTF("Getting commands of device \"%s\".\n",
557 backend_device->name);
559 current_device = backend_device;
561 IRRECO_BACKEND_ENTER(self, "get_commands()");
562 status = self->lib->api->get_commands(
563 self->contex,
564 backend_device->name,
565 backend_device->contex,
566 irreco_backend_get_command_callback);
567 IRRECO_BACKEND_RETURN("get_commands()");
568 irreco_backend_instance_check_status(self, status);
570 current_device = NULL;
571 irreco_string_table_sort_abc(backend_device->command_list);
572 IRRECO_BACKEND_INSTANCE_FOREACH_END
573 irreco_string_table_sort_abc(self->device_list);
575 IRRECO_RETURN
578 gboolean irreco_backend_instance_export_conf(IrrecoBackendInstance *self,
579 const char * device_name,
580 IrrecoBackendFileContainer **file_container)
582 IrrecoBackendStatus status;
583 IRRECO_ENTER
585 IRRECO_BACKEND_ENTER(self, "export_conf()");
586 status = self->lib->api->export_conf(self->contex, device_name,
587 file_container);
588 IRRECO_BACKEND_RETURN("export_conf()");
590 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self, status));
593 gboolean irreco_backend_instance_import_conf(IrrecoBackendInstance *self,
594 IrrecoBackendFileContainer *file_container)
596 IrrecoBackendStatus status;
597 IRRECO_ENTER
599 IRRECO_BACKEND_ENTER(self, "import_conf()");
600 status = self->lib->api->import_conf(self->contex, file_container);
601 IRRECO_BACKEND_RETURN("import_conf()");
603 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self, status));
606 gboolean irreco_backend_instance_check_conf(IrrecoBackendInstance *self,
607 IrrecoBackendFileContainer *file_container)
609 IrrecoBackendStatus status;
610 gboolean file_exist = TRUE;
611 IRRECO_ENTER
613 IRRECO_BACKEND_ENTER(self, "check_conf()");
614 status = self->lib->api->check_conf(self->contex, file_container,
615 &file_exist);
616 IRRECO_BACKEND_RETURN("check_conf()");
618 irreco_backend_instance_check_status(self, status);
620 IRRECO_RETURN_BOOL(file_exist);
623 /** @} */
624 /** @} */