Added button image data transmission from
[irreco.git] / irreco / src / core / irreco_backend_instance.c
blobc8897d580962207c1245959bd77e7dcda13460da
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->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)
90 IRRECO_ENTER
91 irreco_backend_instance_destroy_full(self, FALSE);
92 IRRECO_RETURN
95 /**
96 * Handle the destruction of the instance and device list.
98 void irreco_backend_instance_destroy_full(IrrecoBackendInstance *self,
99 gboolean permanently)
101 IRRECO_ENTER
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,
115 permanently);
116 IRRECO_BACKEND_RETURN("destroy()");
118 /* Cleanup lib assosiated stuff. */
119 irreco_string_table_free(self->device_list);
120 g_free(self->config);
121 self->config = NULL;
123 /* Free name and description. */
124 g_free(self->name);
125 self->name = NULL;
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);
132 IRRECO_RETURN
135 /** @} */
139 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
140 /* Public Functions */
141 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
144 * @name Public Functions
145 * @{
148 void irreco_backend_instance_add_cmd_dependency(IrrecoBackendInstance *self,
149 IrrecoCmd * command)
151 IRRECO_ENTER
152 g_ptr_array_add(self->irreco_cmd_dependencies, command);
154 IRRECO_RETURN
157 void
158 irreco_backend_instance_remove_cmd_dependency(IrrecoBackendInstance *self,
159 IrrecoCmd * command)
161 IRRECO_ENTER
162 g_ptr_array_remove_fast(self->irreco_cmd_dependencies,
163 command);
165 IRRECO_RETURN
168 gboolean irreco_backend_instance_check_status(IrrecoBackendInstance *self,
169 IrrecoBackendStatus status)
171 IRRECO_ENTER
173 if (status != IRRECO_BACKEND_OK) {
174 GString *string;
175 const gchar *error_msg;
176 const gchar *name;
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;
186 } else {
187 name = self->name;
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,
207 gchar * name)
209 IRRECO_ENTER;
210 g_free(self->name);
211 self->name = g_strdup(name);
213 IRRECO_RETURN
217 * DO NOT CALL DIRECTLY, use irreco_backend_manager_set_instance_config()
219 void irreco_backend_instance_set_config(IrrecoBackendInstance *self,
220 gchar * config)
222 IRRECO_ENTER;
223 g_free(self->config);
224 self->config = g_strdup(config);
226 IRRECO_RETURN
230 * Get description of the instance.
232 * The description can also be found at self->description.
234 const gchar *
235 irreco_backend_instance_get_description(IrrecoBackendInstance *self)
237 IRRECO_ENTER
239 g_free(self->description);
240 self->description = NULL;
242 if (self->lib->api->get_description == NULL) {
243 IRRECO_RETURN_PTR(NULL);
244 } else {
245 IRRECO_BACKEND_ENTER(self, "get_description()");
246 self->description =
247 self->lib->api->get_description(
248 self->contex);
249 IRRECO_BACKEND_RETURN("get_description()");
250 IRRECO_RETURN_PTR(self->description);
254 const gchar *
255 irreco_backend_instance_get_name_and_description(IrrecoBackendInstance *self)
257 GString *string;
258 IRRECO_ENTER
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)
281 gchar *filepath;
282 IrrecoBackendStatus status;
283 IRRECO_ENTER
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()");
295 g_free(filepath);
296 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
297 self, status));
301 * Call irreco_backend_save_to_conf() inside the backend.
303 gboolean irreco_backend_instance_save_to_conf(IrrecoBackendInstance *self)
305 gchar *filepath;
306 IrrecoBackendStatus status;
307 IRRECO_ENTER
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()");
319 g_free(filepath);
320 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(self, status));
324 * Send command.
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;
343 IRRECO_ENTER
345 IRRECO_PRINTF("Sending command \"%s\" to device \"%s\".\n",
346 command_name, device_name);
348 /* Find device. */
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);
366 /* Send command*/
367 IRRECO_BACKEND_ENTER(self, "send_command()");
368 status = self->lib->api->send_command(
369 self->contex,
370 device_name,
371 device->contex,
372 command_name,
373 command_contex);
374 IRRECO_BACKEND_RETURN("send_command()");
375 IRRECO_RETURN_BOOL(irreco_backend_instance_check_status(
376 self, status));
379 void irreco_backend_instance_configure(IrrecoBackendInstance *self,
380 GtkWindow *parent)
382 IrrecoBackendStatus status;
383 IRRECO_ENTER
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);
391 IRRECO_RETURN
394 void irreco_backend_instance_create_device(IrrecoBackendInstance *self,
395 GtkWindow *parent)
397 IrrecoBackendStatus status;
398 IRRECO_ENTER
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);
406 IRRECO_RETURN
409 /** @} */
413 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
414 /* Device / Command management */
415 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
417 * @name Command management
418 * @{
422 * Used by callbacks
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;
431 IRRECO_ENTER
433 if (current_backend_instance == NULL) {
434 IRRECO_ERROR("Variable current_backend_instance is not set.\n");
435 IRRECO_RETURN
437 if (name == NULL) {
438 IRRECO_ERROR("Device name is NULL. "
439 "Device name must be given\n");
440 IRRECO_RETURN
443 if (!irreco_string_table_exists(current_backend_instance->device_list,
444 name)) {
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);
452 IRRECO_RETURN
455 void irreco_backend_get_command_callback(const gchar *name,
456 gpointer command_contex)
458 IRRECO_ENTER
459 if (current_device == NULL) {
460 IRRECO_ERROR("Variable current_device is not set.\n");
461 IRRECO_RETURN
463 if (name == NULL) {
464 IRRECO_ERROR("Command name is NULL. "
465 "Command name must be given\n");
466 IRRECO_RETURN
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);
475 IRRECO_RETURN
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;
486 IRRECO_ENTER
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(
509 self->contex,
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);
521 IRRECO_RETURN
524 gboolean irreco_backend_instance_export_conf(IrrecoBackendInstance *self,
525 const char * device_name,
526 IrrecoBackendFileContainer **file_container)
528 IrrecoBackendStatus status;
529 IRRECO_ENTER
531 IRRECO_BACKEND_ENTER(self, "export_conf()");
532 status = self->lib->api->export_conf(self->contex, device_name,
533 file_container);
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;
543 IRRECO_ENTER
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;
557 IRRECO_ENTER
559 IRRECO_BACKEND_ENTER(self, "check_conf()");
560 status = self->lib->api->check_conf(self->contex, file_container,
561 &file_exist);
562 IRRECO_BACKEND_RETURN("check_conf()");
564 irreco_backend_instance_check_status(self, status);
566 IRRECO_RETURN_BOOL(file_exist);
568 /** @} */
569 /** @} */