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"
25 * @addtogroup IrrecoBackendInstance
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
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.
46 * Source file of @ref IrrecoBackendInstance.
50 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
51 /* Construction & Destruction */
52 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
55 * @name Construction & Destruction
59 IrrecoBackendInstance
*
60 irreco_backend_instance_create(IrrecoBackendLib
* backend_lib
,
61 IrrecoData
*irreco_data
)
63 IrrecoBackendInstance
*self
;
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
)
94 irreco_backend_instance_destroy_full(self
, FALSE
);
99 * Handle the destruction of the instance and device list.
101 void irreco_backend_instance_destroy_full(IrrecoBackendInstance
*self
,
102 gboolean permanently
)
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
,
119 IRRECO_BACKEND_RETURN("destroy()");
121 /* Cleanup lib assosiated stuff. */
122 irreco_string_table_free(self
->device_list
);
123 g_free(self
->config
);
126 /* Free name and description. */
127 g_string_free(self
->name
, TRUE
);
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
);
142 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
143 /* Public Functions */
144 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
147 * @name Public Functions
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
,
181 g_ptr_array_add(self
->irreco_cmd_dependencies
, command
);
187 irreco_backend_instance_remove_cmd_dependency(IrrecoBackendInstance
*self
,
191 g_ptr_array_remove_fast(self
->irreco_cmd_dependencies
,
197 gboolean
irreco_backend_instance_check_status(IrrecoBackendInstance
*self
,
198 IrrecoBackendStatus status
)
202 if (status
!= IRRECO_BACKEND_OK
) {
204 const gchar
*error_msg
;
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
;
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
,
242 g_string_assign(self
->name
, name
);
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
,
255 g_free(self
->config
);
256 self
->config
= g_strdup(config
);
262 * Get name of the instance.
265 irreco_backend_instance_get_name(IrrecoBackendInstance
*self
)
269 if (irreco_str_isempty(self
->name
->str
)) {
270 IRRECO_RETURN_PTR(NULL
);
272 IRRECO_RETURN_CONST_STR(self
->name
->str
);
277 * Get description of the instance.
280 irreco_backend_instance_get_description(IrrecoBackendInstance
*self
)
284 if (self
->lib
->api
->get_description
== NULL
) {
285 g_string_assign(self
->description
, "");
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
);
298 if (irreco_str_isempty(self
->description
->str
)) {
299 IRRECO_RETURN_PTR(NULL
);
301 IRRECO_RETURN_CONST_STR(self
->description
->str
);
306 * Get name and description of the instance in one string.
309 irreco_backend_instance_get_name_and_description(IrrecoBackendInstance
*self
)
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
);
320 g_string_assign(self
->name_and_description
, self
->name
->str
);
323 if (irreco_str_isempty(self
->name
->str
)) {
324 IRRECO_RETURN_PTR(NULL
);
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
)
336 IrrecoBackendStatus status
;
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()");
350 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
355 * Call irreco_backend_save_to_conf() inside the backend.
357 gboolean
irreco_backend_instance_save_to_conf(IrrecoBackendInstance
*self
)
360 IrrecoBackendStatus status
;
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()");
374 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self
, status
));
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
;
399 IRRECO_PRINTF("Sending command \"%s\" to device \"%s\".\n",
400 command_name
, device_name
);
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
);
421 IRRECO_BACKEND_ENTER(self
, "send_command()");
422 status
= self
->lib
->api
->send_command(
428 IRRECO_BACKEND_RETURN("send_command()");
429 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
433 void irreco_backend_instance_configure(IrrecoBackendInstance
*self
,
436 IrrecoBackendStatus status
;
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
);
448 void irreco_backend_instance_create_device(IrrecoBackendInstance
*self
,
451 IrrecoBackendStatus status
;
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
);
467 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
468 /* Device / Command management */
469 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
471 * @name Command management
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
;
487 if (current_backend_instance
== NULL
) {
488 IRRECO_ERROR("Variable current_backend_instance is not set.\n");
492 IRRECO_ERROR("Device name is NULL. "
493 "Device name must be given\n");
497 if (!irreco_string_table_exists(current_backend_instance
->device_list
,
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
);
509 void irreco_backend_get_command_callback(const gchar
*name
,
510 gpointer command_contex
)
513 if (current_device
== NULL
) {
514 IRRECO_ERROR("Variable current_device is not set.\n");
518 IRRECO_ERROR("Command name is NULL. "
519 "Command name must be given\n");
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
);
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
;
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(
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
);
578 gboolean
irreco_backend_instance_export_conf(IrrecoBackendInstance
*self
,
579 const char * device_name
,
580 IrrecoBackendFileContainer
**file_container
)
582 IrrecoBackendStatus status
;
585 IRRECO_BACKEND_ENTER(self
, "export_conf()");
586 status
= self
->lib
->api
->export_conf(self
->contex
, device_name
,
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
;
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
;
613 IRRECO_BACKEND_ENTER(self
, "check_conf()");
614 status
= self
->lib
->api
->check_conf(self
->contex
, file_container
,
616 IRRECO_BACKEND_RETURN("check_conf()");
618 irreco_backend_instance_check_status(self
, status
);
620 IRRECO_RETURN_BOOL(file_exist
);