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
->lib
= backend_lib
;
71 self
->irreco_cmd_dependencies
= g_ptr_array_new();
73 IRRECO_BACKEND_ENTER(self
, "create()");
74 self
->contex
= self
->lib
->api
->create();
75 IRRECO_BACKEND_RETURN("create()");
77 if (self
->contex
== NULL
) {
78 g_slice_free(IrrecoBackendInstance
, self
);
79 IRRECO_RETURN_PTR(NULL
);
82 self
->device_list
= irreco_string_table_new(
83 G_DESTROYNOTIFY(irreco_backend_device_destroy
), NULL
);
85 IRRECO_RETURN_PTR(self
);
88 void irreco_backend_instance_destroy(IrrecoBackendInstance
*self
)
91 irreco_backend_instance_destroy_full(self
, FALSE
);
96 * Handle the destruction of the instance and device list.
98 void irreco_backend_instance_destroy_full(IrrecoBackendInstance
*self
,
103 if (self
== NULL
) IRRECO_RETURN
105 /* Remove all IrrecoCmd dependencies. */
106 IRRECO_PTR_ARRAY_BACKWARDS(self
->irreco_cmd_dependencies
,
107 IrrecoCmd
*, command
)
108 irreco_cmd_set_builtin(command
, IRRECO_COMMAND_NONE
);
109 IRRECO_PTR_ARRAY_FORWARDS_END
110 g_ptr_array_free(self
->irreco_cmd_dependencies
, TRUE
);
112 /* Notify library of destruction. */
113 IRRECO_BACKEND_ENTER(self
, "destroy()");
114 self
->lib
->api
->destroy(self
->contex
,
116 IRRECO_BACKEND_RETURN("destroy()");
118 /* Cleanup lib assosiated stuff. */
119 irreco_string_table_free(self
->device_list
);
120 g_free(self
->config
);
123 /* Free name and description. */
126 g_free(self
->description
);
127 self
->description
= NULL
;
128 g_free(self
->name_and_description
);
129 self
->name_and_description
= NULL
;
131 g_slice_free(IrrecoBackendInstance
, self
);
139 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
140 /* Public Functions */
141 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
144 * @name Public Functions
148 void irreco_backend_instance_add_cmd_dependency(IrrecoBackendInstance
*self
,
152 g_ptr_array_add(self
->irreco_cmd_dependencies
, command
);
158 irreco_backend_instance_remove_cmd_dependency(IrrecoBackendInstance
*self
,
162 g_ptr_array_remove_fast(self
->irreco_cmd_dependencies
,
168 gboolean
irreco_backend_instance_check_status(IrrecoBackendInstance
*self
,
169 IrrecoBackendStatus status
)
173 if (status
!= IRRECO_BACKEND_OK
) {
175 const gchar
*error_msg
;
178 IRRECO_BACKEND_ENTER(self
, "get_error_msg()");
179 error_msg
= self
->lib
->api
->get_error_msg(
180 self
->contex
, status
);
181 IRRECO_BACKEND_RETURN("get_error_msg()");
183 /* Print description if it is available. */
184 if (self
->name_and_description
) {
185 name
= self
->name_and_description
;
190 string
= g_string_new(NULL
);
191 g_string_printf(string
, "%i", status
);
192 irreco_show_backend_err_dlg(
193 irreco_window_manager_get_gtk_window(
194 self
->irreco_data
->window_manager
),
195 self
->lib
->name
, name
, string
->str
, error_msg
);
196 g_string_free(string
, TRUE
);
198 IRRECO_RETURN_BOOL(FALSE
);
200 IRRECO_RETURN_BOOL(TRUE
);
204 * DO NOT CALL DIRECTLY, use irreco_backend_manager_set_instance_name()
206 void irreco_backend_instance_set_name(IrrecoBackendInstance
*self
,
211 self
->name
= g_strdup(name
);
217 * DO NOT CALL DIRECTLY, use irreco_backend_manager_set_instance_config()
219 void irreco_backend_instance_set_config(IrrecoBackendInstance
*self
,
223 g_free(self
->config
);
224 self
->config
= g_strdup(config
);
230 * Get description of the instance.
232 * The description can also be found at self->description.
235 irreco_backend_instance_get_description(IrrecoBackendInstance
*self
)
239 g_free(self
->description
);
240 self
->description
= NULL
;
242 if (self
->lib
->api
->get_description
== NULL
) {
243 IRRECO_RETURN_PTR(NULL
);
245 IRRECO_BACKEND_ENTER(self
, "get_description()");
247 self
->lib
->api
->get_description(
249 IRRECO_BACKEND_RETURN("get_description()");
250 IRRECO_RETURN_PTR(self
->description
);
255 irreco_backend_instance_get_name_and_description(IrrecoBackendInstance
*self
)
260 g_free(self
->name_and_description
);
261 self
->name_and_description
= NULL
;
263 if (self
->name
== NULL
) IRRECO_RETURN_PTR(NULL
);
265 string
= g_string_new(self
->name
);
266 if (irreco_backend_instance_get_description(self
) != NULL
) {
267 g_string_append(string
, " - ");
268 g_string_append(string
, self
->description
);
271 self
->name_and_description
= g_string_free(string
, FALSE
);
272 IRRECO_RETURN_PTR(self
->name_and_description
);
277 * Call irreco_backend_read_from_conf() inside the backend.
279 gboolean
irreco_backend_instance_read_from_conf(IrrecoBackendInstance
*self
)
282 IrrecoBackendStatus status
;
285 if (self
->config
== NULL
) {
286 IRRECO_ERROR("Config file is not set. Cannot read config "
287 "of instance \"%s\"\n", self
->name
);
290 filepath
= irreco_get_config_file("irreco", self
->config
);
291 IRRECO_BACKEND_ENTER(self
, "from_conf()");
292 status
= self
->lib
->api
->from_conf(
293 self
->contex
, filepath
);
294 IRRECO_BACKEND_RETURN("from_conf()");
296 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
301 * Call irreco_backend_save_to_conf() inside the backend.
303 gboolean
irreco_backend_instance_save_to_conf(IrrecoBackendInstance
*self
)
306 IrrecoBackendStatus status
;
309 if (self
->config
== NULL
) {
310 IRRECO_ERROR("Config file is not set. Cannot save config "
311 "of instance \"%s\"\n", self
->name
);
314 filepath
= irreco_get_config_file("irreco", self
->config
);
315 IRRECO_BACKEND_ENTER(self
, "to_conf()");
316 status
= self
->lib
->api
->to_conf(
317 self
->contex
, filepath
);
318 IRRECO_BACKEND_RETURN("to_conf()");
320 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self
, status
));
326 * This function takes device and command name as strings for a purpose.
327 * Because the list of supported commands and devices for some instance
328 * of a backend depend on the configuration of the backend, and because
329 * you cant assume that the configuration remains the same, you cannot
330 * assume that the structures allocated by irreco to store those commands
331 * will exist in the future.
333 * So the proper way to do this is to take a copy of device name and command
334 * name, and when were sending command, to check if the command still exists.
336 gboolean
irreco_backend_instance_send_command(IrrecoBackendInstance
*self
,
337 const gchar
*device_name
,
338 const gchar
*command_name
)
340 IrrecoBackendStatus status
;
341 IrrecoBackendDevice
*device
;
342 gpointer command_contex
;
345 IRRECO_PRINTF("Sending command \"%s\" to device \"%s\".\n",
346 command_name
, device_name
);
349 if (!irreco_string_table_get(self
->device_list
, device_name
,
350 (gpointer
*) &device
)) {
351 IRRECO_ERROR("Cant send command \"%s\" to device \"%s\" "
352 "because no such device exists.\n",
353 command_name
, device_name
);
354 IRRECO_RETURN_BOOL(FALSE
);
357 /* Find command contex. */
358 if (!irreco_string_table_get(device
->command_list
, command_name
,
359 (gpointer
*) &command_contex
)) {
360 IRRECO_ERROR("Cant send command \"%s\" to device \"%s\" "
361 "because device does not support that command.\n",
362 command_name
, device_name
);
363 IRRECO_RETURN_BOOL(FALSE
);
367 IRRECO_BACKEND_ENTER(self
, "send_command()");
368 status
= self
->lib
->api
->send_command(
374 IRRECO_BACKEND_RETURN("send_command()");
375 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
379 void irreco_backend_instance_configure(IrrecoBackendInstance
*self
,
382 IrrecoBackendStatus status
;
385 IRRECO_BACKEND_ENTER(self
, "configure()");
386 status
= self
->lib
->api
->configure(
387 self
->contex
, parent
);
388 IRRECO_BACKEND_RETURN("configure()");
389 irreco_backend_instance_check_status(self
, status
);
394 void irreco_backend_instance_create_device(IrrecoBackendInstance
*self
,
397 IrrecoBackendStatus status
;
400 IRRECO_BACKEND_ENTER(self
, "create_device()");
401 status
= self
->lib
->api
->create_device(
402 self
->contex
, parent
);
403 IRRECO_BACKEND_RETURN("create_device()");
404 irreco_backend_instance_check_status(self
, status
);
413 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
414 /* Device / Command management */
415 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
417 * @name Command management
424 IrrecoBackendInstance
*current_backend_instance
= NULL
;
425 IrrecoBackendDevice
*current_device
= NULL
;
427 void irreco_backend_get_device_callback(const gchar
*name
,
428 gpointer device_contex
)
430 IrrecoBackendDevice
*backend_device
;
433 if (current_backend_instance
== NULL
) {
434 IRRECO_ERROR("Variable current_backend_instance is not set.\n");
438 IRRECO_ERROR("Device name is NULL. "
439 "Device name must be given\n");
443 if (!irreco_string_table_exists(current_backend_instance
->device_list
,
445 backend_device
= irreco_backend_device_create(
446 name
, current_backend_instance
, device_contex
);
447 irreco_string_table_add(current_backend_instance
->device_list
,
448 backend_device
->name
, backend_device
);
449 IRRECO_PRINTF("Device \"%s\" added.\n", backend_device
->name
);
455 void irreco_backend_get_command_callback(const gchar
*name
,
456 gpointer command_contex
)
459 if (current_device
== NULL
) {
460 IRRECO_ERROR("Variable current_device is not set.\n");
464 IRRECO_ERROR("Command name is NULL. "
465 "Command name must be given\n");
469 if (!irreco_string_table_exists(current_device
->command_list
, name
)) {
470 irreco_string_table_add(current_device
->command_list
,
471 name
, command_contex
);
472 IRRECO_PRINTF("Command \"%s\" added.\n", name
);
479 * This function will first get a list of devices from the backend instance,
480 * and after that get a list of commands for every device. After this,
481 * Irreco should have a complete list of commands the backend instance provides.
483 void irreco_backend_instance_get_devcmd_list(IrrecoBackendInstance
*self
)
485 IrrecoBackendStatus status
;
488 /* Destroy old data. */
489 irreco_string_table_remove_all(self
->device_list
);
491 /* Fetch a list of devices. */
492 current_backend_instance
= self
;
493 IRRECO_BACKEND_ENTER(self
, "get_devices()");
494 status
= self
->lib
->api
->get_devices(
495 self
->contex
, irreco_backend_get_device_callback
);
496 IRRECO_BACKEND_RETURN("get_devices()");
497 irreco_backend_instance_check_status(self
, status
);
498 current_backend_instance
= NULL
;
500 /* Fetch all commands from all devices. */
501 IRRECO_BACKEND_INSTANCE_FOREACH(self
, backend_device
)
502 IRRECO_PRINTF("Getting commands of device \"%s\".\n",
503 backend_device
->name
);
505 current_device
= backend_device
;
507 IRRECO_BACKEND_ENTER(self
, "get_commands()");
508 status
= self
->lib
->api
->get_commands(
510 backend_device
->name
,
511 backend_device
->contex
,
512 irreco_backend_get_command_callback
);
513 IRRECO_BACKEND_RETURN("get_commands()");
514 irreco_backend_instance_check_status(self
, status
);
516 current_device
= NULL
;
517 irreco_string_table_sort_abc(backend_device
->command_list
);
518 IRRECO_BACKEND_INSTANCE_FOREACH_END
519 irreco_string_table_sort_abc(self
->device_list
);
524 gboolean
irreco_backend_instance_export_conf(IrrecoBackendInstance
*self
,
525 const char * device_name
,
526 IrrecoBackendFileContainer
**file_container
)
528 IrrecoBackendStatus status
;
531 IRRECO_BACKEND_ENTER(self
, "export_conf()");
532 status
= self
->lib
->api
->export_conf(self
->contex
, device_name
,
534 IRRECO_BACKEND_RETURN("export_conf()");
536 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self
, status
));
539 gboolean
irreco_backend_instance_import_conf(IrrecoBackendInstance
*self
,
540 IrrecoBackendFileContainer
*file_container
)
542 IrrecoBackendStatus status
;
545 IRRECO_BACKEND_ENTER(self
, "import_conf()");
546 status
= self
->lib
->api
->import_conf(self
->contex
, file_container
);
547 IRRECO_BACKEND_RETURN("import_conf()");
549 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self
, status
));
552 gboolean
irreco_backend_instance_check_conf(IrrecoBackendInstance
*self
,
553 IrrecoBackendFileContainer
*file_container
)
555 IrrecoBackendStatus status
;
556 gboolean file_exist
= TRUE
;
559 IRRECO_BACKEND_ENTER(self
, "check_conf()");
560 status
= self
->lib
->api
->check_conf(self
->contex
, file_container
,
562 IRRECO_BACKEND_RETURN("check_conf()");
564 irreco_backend_instance_check_status(self
, status
);
566 IRRECO_RETURN_BOOL(file_exist
);