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 * @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
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.
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
;
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
)
76 irreco_backend_instance_destroy_full(self
, FALSE
);
81 * Handle the destruction of the instance and device list.
83 void irreco_backend_instance_destroy_full(IrrecoBackendInstance
*self
,
88 if (self
== NULL
) IRRECO_RETURN
90 /* Remove all IrrecoCmd dependencies. */
91 IRRECO_PTR_ARRAY_BACKWARDS(self
->irreco_cmd_dependencies
,
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
,
101 IRRECO_BACKEND_RETURN("destroy()");
103 /* Cleanup lib assosiated stuff. */
104 irreco_string_table_free(self
->device_list
);
105 g_free(self
->config
);
108 /* Free name and description. */
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
);
120 void irreco_backend_instance_add_cmd_dependency(IrrecoBackendInstance
*self
,
124 g_ptr_array_add(self
->irreco_cmd_dependencies
, command
);
130 irreco_backend_instance_remove_cmd_dependency(IrrecoBackendInstance
*self
,
134 g_ptr_array_remove_fast(self
->irreco_cmd_dependencies
,
140 gboolean
irreco_backend_instance_check_status(IrrecoBackendInstance
*self
,
141 IrrecoBackendStatus status
)
145 if (status
!= IRRECO_BACKEND_OK
) {
147 const gchar
*error_msg
;
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
;
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
,
183 self
->name
= g_strdup(name
);
189 * DO NOT CALL DIRECTLY, use irreco_backend_manager_set_instance_config()
191 void irreco_backend_instance_set_config(IrrecoBackendInstance
*self
,
195 g_free(self
->config
);
196 self
->config
= g_strdup(config
);
202 * Get description of the instance.
204 * The description can also be found at self->description.
207 irreco_backend_instance_get_description(IrrecoBackendInstance
*self
)
211 g_free(self
->description
);
212 self
->description
= NULL
;
214 if (self
->lib
->api
->get_description
== NULL
) {
215 IRRECO_RETURN_PTR(NULL
);
217 IRRECO_BACKEND_ENTER(self
, "get_description()");
219 self
->lib
->api
->get_description(
221 IRRECO_BACKEND_RETURN("get_description()");
222 IRRECO_RETURN_PTR(self
->description
);
227 irreco_backend_instance_get_name_and_description(IrrecoBackendInstance
*self
)
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
)
254 IrrecoBackendStatus status
;
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()");
268 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
273 * Call irreco_backend_save_to_conf() inside the backend.
275 gboolean
irreco_backend_instance_save_to_conf(IrrecoBackendInstance
*self
)
278 IrrecoBackendStatus status
;
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()");
292 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self
, status
));
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
;
317 IRRECO_PRINTF("Sending command \"%s\" to device \"%s\".\n",
318 command_name
, device_name
);
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
);
339 IRRECO_BACKEND_ENTER(self
, "send_command()");
340 status
= self
->lib
->api
->send_command(
346 IRRECO_BACKEND_RETURN("send_command()");
347 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
351 void irreco_backend_instance_configure(IrrecoBackendInstance
*self
,
354 IrrecoBackendStatus status
;
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
);
366 void irreco_backend_instance_create_device(IrrecoBackendInstance
*self
,
369 IrrecoBackendStatus status
;
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
);
383 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
384 /* Device / Command management */
385 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
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
;
399 if (current_backend_instance
== NULL
) {
400 IRRECO_ERROR("Variable current_backend_instance is not set.\n");
404 IRRECO_ERROR("Device name is NULL. "
405 "Device name must be given\n");
409 if (!irreco_string_table_exists(current_backend_instance
->device_list
,
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
);
421 void irreco_backend_get_command_callback(const gchar
*name
,
422 gpointer command_contex
)
425 if (current_device
== NULL
) {
426 IRRECO_ERROR("Variable current_device is not set.\n");
430 IRRECO_ERROR("Command name is NULL. "
431 "Command name must be given\n");
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
);
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
;
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(
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
);
490 gboolean
irreco_backend_instance_export_conf(IrrecoBackendInstance
*self
,
491 const char * device_name
,
492 IrrecoBackendFileContainer
**file_container
)
494 IrrecoBackendStatus status
;
497 IRRECO_BACKEND_ENTER(self
, "export_conf()");
498 status
= self
->lib
->api
->export_conf(self
->contex
, device_name
,
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
;
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
;
525 IRRECO_BACKEND_ENTER(self
, "check_conf()");
526 status
= self
->lib
->api
->check_conf(self
->contex
, file_container
,
528 IRRECO_BACKEND_RETURN("check_conf()");
530 irreco_backend_instance_check_status(self
, status
);
532 IRRECO_RETURN_BOOL(file_exist
);