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_cmd.h"
21 #include "irreco_config.h"
26 * Stores a command which is called when a button is pressed.
27 * Serves also as an abstraction between built in commands and backend commands.
30 void irreco_cmd_clean(IrrecoCmd
* irreco_cmd
);
31 gboolean
irreco_cmd_get_current_layout_pos(IrrecoData
* irreco_data
,
32 guint
* pos
, guint
* len
);
33 void irreco_cmd_set_current_layout_pos(IrrecoData
* irreco_data
,
36 IrrecoCmd
*irreco_cmd_create()
38 IrrecoCmd
*irreco_cmd
;
41 irreco_cmd
= g_slice_new0(IrrecoCmd
);
42 IRRECO_RETURN_PTR(irreco_cmd
);
45 void irreco_cmd_destroy(IrrecoCmd
* irreco_cmd
)
48 irreco_cmd_clean(irreco_cmd
);
49 g_slice_free(IrrecoCmd
, irreco_cmd
);
53 void irreco_cmd_clean(IrrecoCmd
* irreco_cmd
)
56 switch (irreco_cmd
->type
) {
57 case IRRECO_COMMAND_NONE
:
58 case IRRECO_COMMAND_NEXT_REMOTE
:
59 case IRRECO_COMMAND_PREVIOUS_REMOTE
:
60 case IRRECO_COMMAND_FULLSCREEN_TOGGLE
:
63 case IRRECO_COMMAND_BACKEND
:
64 irreco_backend_instance_remove_cmd_dependency(
65 irreco_cmd
->backend
.instance
, irreco_cmd
);
66 irreco_cmd
->backend
.instance
= NULL
;
67 g_free(irreco_cmd
->backend
.device_name
);
68 irreco_cmd
->backend
.device_name
= NULL
;
69 g_free(irreco_cmd
->backend
.command_name
);
70 irreco_cmd
->backend
.command_name
= NULL
;
71 g_string_free(irreco_cmd
->backend
.title
, TRUE
);
72 irreco_cmd
->backend
.title
= NULL
;
75 case IRRECO_COMMAND_SHOW_LAYOUT
:
76 g_free(irreco_cmd
->layout
.name
);
77 irreco_cmd
->layout
.name
= NULL
;
78 g_string_free(irreco_cmd
->layout
.title
, TRUE
);
79 irreco_cmd
->backend
.title
= NULL
;
82 case IRRECO_COMMAND_WAIT
:
83 g_string_free(irreco_cmd
->wait
.title
, TRUE
);
84 irreco_cmd
->wait
.title
= NULL
;
87 irreco_cmd
->type
= IRRECO_COMMAND_NONE
;
91 void irreco_cmd_set_builtin(IrrecoCmd
* irreco_cmd
,
95 irreco_cmd_clean(irreco_cmd
);
98 case IRRECO_COMMAND_NONE
:
99 case IRRECO_COMMAND_NEXT_REMOTE
:
100 case IRRECO_COMMAND_PREVIOUS_REMOTE
:
101 case IRRECO_COMMAND_FULLSCREEN_TOGGLE
:
102 irreco_cmd
->type
= type
;
106 IRRECO_ERROR("Type id \"%i\" is not reserved for"
107 "built-in commands.\n", type
);
114 void irreco_cmd_set_backend(IrrecoCmd
* irreco_cmd
,
115 IrrecoBackendInstance
* instance
,
116 const gchar
* device_name
,
117 const gchar
* command_name
)
120 irreco_cmd_clean(irreco_cmd
);
121 irreco_cmd
->type
= IRRECO_COMMAND_BACKEND
;
122 irreco_cmd
->backend
.instance
= instance
;
123 irreco_cmd
->backend
.device_name
= g_strdup(device_name
);
124 irreco_cmd
->backend
.command_name
= g_strdup(command_name
);
125 irreco_cmd
->backend
.title
= g_string_new("");
126 irreco_backend_instance_add_cmd_dependency(instance
, irreco_cmd
);
130 void irreco_cmd_set_layout(IrrecoCmd
* irreco_cmd
,
134 irreco_cmd_clean(irreco_cmd
);
135 irreco_cmd
->type
= IRRECO_COMMAND_SHOW_LAYOUT
;
136 irreco_cmd
->layout
.name
= g_strdup(name
);
137 irreco_cmd
->layout
.title
= g_string_new("");
141 void irreco_cmd_set_wait(IrrecoCmd
* irreco_cmd
, gulong delay
)
144 irreco_cmd_clean(irreco_cmd
);
145 irreco_cmd
->type
= IRRECO_COMMAND_WAIT
;
146 irreco_cmd
->wait
.delay
= delay
;
147 irreco_cmd
->wait
.title
= g_string_new("");
153 * Copy data from one IrrecoCmd object to another.
155 void irreco_cmd_copy(IrrecoCmd
* from
, IrrecoCmd
* to
)
158 switch (from
->type
) {
159 case IRRECO_COMMAND_NONE
:
160 case IRRECO_COMMAND_NEXT_REMOTE
:
161 case IRRECO_COMMAND_PREVIOUS_REMOTE
:
162 case IRRECO_COMMAND_FULLSCREEN_TOGGLE
:
163 irreco_cmd_set_builtin(to
, from
->type
);
166 case IRRECO_COMMAND_BACKEND
:
167 irreco_cmd_set_backend(to
,
168 from
->backend
.instance
,
169 from
->backend
.device_name
,
170 from
->backend
.command_name
);
173 case IRRECO_COMMAND_SHOW_LAYOUT
:
174 irreco_cmd_set_layout(to
, from
->layout
.name
);
177 case IRRECO_COMMAND_WAIT
:
178 irreco_cmd_set_wait(to
, from
->wait
.delay
);
186 * Create a new IrrecoCmd based on an old IrrecoCmd.
188 IrrecoCmd
*irreco_cmd_dublicate(IrrecoCmd
* old
)
193 new = irreco_cmd_create();
194 irreco_cmd_copy(old
, new);
195 IRRECO_RETURN_PTR(new);
199 * Get descriptive title for the command.
201 const gchar
*irreco_cmd_get_long_name(IrrecoCmd
* irreco_cmd
)
204 switch (irreco_cmd
->type
) {
205 case IRRECO_COMMAND_NONE
:
206 IRRECO_RETURN_STR(_(IRRECO_COMMAND_NONE_TITLE
));
207 case IRRECO_COMMAND_NEXT_REMOTE
:
208 IRRECO_RETURN_STR(_(IRRECO_COMMAND_NEXT_REMOTE_TITLE
));
209 case IRRECO_COMMAND_PREVIOUS_REMOTE
:
210 IRRECO_RETURN_STR(_(IRRECO_COMMAND_PREVIOUS_REMOTE_TITLE
));
211 case IRRECO_COMMAND_FULLSCREEN_TOGGLE
:
212 IRRECO_RETURN_STR(_(IRRECO_COMMAND_FULLSCREEN_TOGGLE_TITLE
));
214 case IRRECO_COMMAND_BACKEND
:
215 if (irreco_str_isempty(irreco_cmd
->backend
.title
->str
)) {
216 g_string_printf(irreco_cmd
->backend
.title
, "%s: %s",
217 irreco_cmd
->backend
.device_name
,
218 irreco_cmd
->backend
.command_name
);
220 IRRECO_RETURN_STR(irreco_cmd
->backend
.title
->str
);
222 case IRRECO_COMMAND_SHOW_LAYOUT
:
223 if (irreco_str_isempty(irreco_cmd
->layout
.title
->str
)) {
224 g_string_printf(irreco_cmd
->layout
.title
, "%s%s",
225 _(IRRECO_COMMAND_SHOW_LAYOUT_TITLE_PREFIX
),
226 irreco_cmd
->layout
.name
);
228 IRRECO_RETURN_STR(irreco_cmd
->layout
.title
->str
);
230 case IRRECO_COMMAND_WAIT
:
231 if (irreco_str_isempty(irreco_cmd
->wait
.title
->str
)) {
232 g_string_printf(irreco_cmd
->wait
.title
,
233 IRRECO_COMMAND_WAIT_TITLE_FORMAT
,
234 (float)(irreco_cmd
->wait
.delay
) /
235 (float)IRRECO_SECOND_IN_USEC
);
237 IRRECO_RETURN_STR(irreco_cmd
->wait
.title
->str
);
240 IRRECO_ERROR("Could not get title for command. "
241 "Which should not be possible!\n");
242 IRRECO_RETURN_PTR(NULL
);
247 * Get short name of the command.
249 const gchar
*irreco_cmd_get_short_name(IrrecoCmd
* irreco_cmd
)
252 switch (irreco_cmd
->type
) {
253 case IRRECO_COMMAND_NONE
:
254 IRRECO_RETURN_STR(_(IRRECO_COMMAND_NONE_TITLE
));
255 case IRRECO_COMMAND_NEXT_REMOTE
:
256 IRRECO_RETURN_STR(_(IRRECO_COMMAND_NEXT_REMOTE_TITLE
));
257 case IRRECO_COMMAND_PREVIOUS_REMOTE
:
258 IRRECO_RETURN_STR(_(IRRECO_COMMAND_PREVIOUS_REMOTE_TITLE
));
259 case IRRECO_COMMAND_FULLSCREEN_TOGGLE
:
260 IRRECO_RETURN_STR(_(IRRECO_COMMAND_FULLSCREEN_TOGGLE_NAME
));
261 case IRRECO_COMMAND_BACKEND
:
262 IRRECO_RETURN_STR(irreco_cmd
->backend
.command_name
);
263 case IRRECO_COMMAND_SHOW_LAYOUT
:
264 IRRECO_RETURN_STR(irreco_cmd
->layout
.name
);
265 case IRRECO_COMMAND_WAIT
:
266 g_string_printf(irreco_cmd
->wait
.title
,
268 (float)(irreco_cmd
->wait
.delay
) /
269 (float)IRRECO_SECOND_IN_USEC
);
270 IRRECO_RETURN_STR(irreco_cmd
->wait
.title
->str
);
273 IRRECO_ERROR("Could not get title for command. "
274 "Which should not be possible!\n");
275 IRRECO_RETURN_PTR(NULL
);
280 void irreco_cmd_print(IrrecoCmd
* irreco_cmd
)
283 switch (irreco_cmd
->type
) {
284 case IRRECO_COMMAND_NONE
:
285 IRRECO_PRINTF("Type: IRRECO_COMMAND_NONE\n");
288 case IRRECO_COMMAND_NEXT_REMOTE
:
289 IRRECO_PRINTF("Type: IRRECO_COMMAND_NEXT_REMOTE\n");
292 case IRRECO_COMMAND_PREVIOUS_REMOTE
:
293 IRRECO_PRINTF("Type: IRRECO_COMMAND_PREVIOUS_REMOTE\n");
296 case IRRECO_COMMAND_FULLSCREEN_TOGGLE
:
297 IRRECO_PRINTF("Type: IRRECO_COMMAND_FULLSCREEN_TOGGLE\n");
300 case IRRECO_COMMAND_BACKEND
:
301 IRRECO_PRINTF("Type: IRRECO_COMMAND_BACKEND\n");
302 IRRECO_PRINTF("Int/dev/cmd: \"%s\" \"%s\" \"%s\"\n",
303 irreco_cmd
->backend
.instance
->name
,
304 irreco_cmd
->backend
.device_name
,
305 irreco_cmd
->backend
.command_name
);
308 case IRRECO_COMMAND_SHOW_LAYOUT
:
309 IRRECO_PRINTF("Type: IRRECO_COMMAND_SHOW_LAYOUT\n");
310 IRRECO_PRINTF("Layout: \"%s\"\n",
311 irreco_cmd
->layout
.name
);
314 case IRRECO_COMMAND_WAIT
:
315 IRRECO_PRINTF("Type: IRRECO_COMMAND_WAIT\n");
316 IRRECO_PRINTF("Delay: \"%lu\"\n",
317 irreco_cmd
->wait
.delay
);
325 gboolean
irreco_cmd_execute(IrrecoCmd
* irreco_cmd
, IrrecoData
* irreco_data
)
328 IrrecoButtonLayout
*layout
;
331 IRRECO_PRINTF("Execuging command.\n");
332 irreco_cmd_print(irreco_cmd
);
334 switch (irreco_cmd
->type
) {
335 case IRRECO_COMMAND_NONE
: break;
337 /* Display next layout in UserUi. */
338 case IRRECO_COMMAND_NEXT_REMOTE
:
339 if (!irreco_cmd_get_current_layout_pos(irreco_data
,
340 &pos
, &len
) || len
< 2) break;
341 if (++pos
>= len
) pos
= 0;
342 irreco_cmd_set_current_layout_pos(irreco_data
, pos
);
343 IRRECO_RETURN_BOOL(FALSE
);
345 /* Display previous layout in UserUi. */
346 case IRRECO_COMMAND_PREVIOUS_REMOTE
:
347 if (!irreco_cmd_get_current_layout_pos(irreco_data
,
348 &pos
, &len
) || len
< 2) break;
352 pos
= irreco_string_table_lenght(
353 irreco_data
->irreco_layout_array
) - 1;
356 irreco_cmd_set_current_layout_pos(irreco_data
, pos
);
357 IRRECO_RETURN_BOOL(FALSE
);
359 case IRRECO_COMMAND_FULLSCREEN_TOGGLE
:
360 if (irreco_data
->window_manager
->user_window
!= NULL
) {
361 irreco_window_toggle_fullscreen(
362 irreco_data
->window_manager
->user_window
->window
);
364 IRRECO_RETURN_BOOL(TRUE
);
366 case IRRECO_COMMAND_BACKEND
:
367 IRRECO_RETURN_BOOL(irreco_backend_instance_send_command(
368 irreco_cmd
->backend
.instance
,
369 irreco_cmd
->backend
.device_name
,
370 irreco_cmd
->backend
.command_name
));
372 case IRRECO_COMMAND_SHOW_LAYOUT
:
373 if (irreco_string_table_get(
374 irreco_data
->irreco_layout_array
,
375 irreco_cmd
->layout
.name
,
376 (gpointer
*) &layout
)) {
377 irreco_window_manager_set_layout(
378 irreco_data
->window_manager
, layout
);
380 IRRECO_RETURN_BOOL(FALSE
);
382 case IRRECO_COMMAND_WAIT
:
384 IRRECO_ERROR("Wait command should be handled in "
385 "command chain execution function.\n");
386 IRRECO_RETURN_BOOL(TRUE
);
389 IRRECO_ERROR("Could not execute command. Unknown type id \"%i\".\n",
391 IRRECO_RETURN_BOOL(FALSE
);
396 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
397 /* Layout position finding and setting. */
398 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
401 * Get the position of the current layout inside the
402 * irreco_data->irreco_layout_array, and the lenght of the array.
404 gboolean
irreco_cmd_get_current_layout_pos(IrrecoData
* irreco_data
,
405 guint
* pos
, guint
* len
)
407 IrrecoButtonLayout
*layout
;
408 IrrecoStringTable
*table
= irreco_data
->irreco_layout_array
;
411 layout
= irreco_data
->window_manager
->current_layout
;
412 if (layout
== NULL
) IRRECO_RETURN_BOOL(FALSE
);
414 if (!irreco_string_table_get_index(table
, layout
, pos
)) {
415 IRRECO_RETURN_BOOL(FALSE
);
418 *len
= irreco_string_table_lenght(table
);
419 IRRECO_RETURN_BOOL(TRUE
);
423 * Set active layout of User ui by using a position index of the layout in
424 * irreco_data->irreco_layout_array.
426 void irreco_cmd_set_current_layout_pos(IrrecoData
* irreco_data
,
429 IrrecoButtonLayout
*layout
;
430 IrrecoStringTable
*table
= irreco_data
->irreco_layout_array
;
433 if (irreco_string_table_index(table
, pos
, NULL
, (gpointer
*) &layout
)){
434 irreco_window_manager_set_layout(irreco_data
->window_manager
,
437 irreco_window_manager_set_layout(irreco_data
->window_manager
,
444 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
446 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
448 const gchar
*irreco_cmd_type_to_str(IrrecoCmdType type
)
452 case IRRECO_COMMAND_NONE
:
453 IRRECO_RETURN_STR(IRRECO_COMMAND_NONE_STRING
);
455 case IRRECO_COMMAND_NEXT_REMOTE
:
456 IRRECO_RETURN_STR(IRRECO_COMMAND_NEXT_REMOTE_STRING
);
458 case IRRECO_COMMAND_PREVIOUS_REMOTE
:
459 IRRECO_RETURN_STR(IRRECO_COMMAND_PREVIOUS_REMOTE_STRING
);
461 case IRRECO_COMMAND_FULLSCREEN_TOGGLE
:
462 IRRECO_RETURN_STR(IRRECO_COMMAND_FULLSCREEN_TOGGLE_STRING
);
464 case IRRECO_COMMAND_BACKEND
:
465 IRRECO_RETURN_STR(IRRECO_COMMAND_SHOW_BACKEND_STRING
);
467 case IRRECO_COMMAND_SHOW_LAYOUT
:
468 IRRECO_RETURN_STR(IRRECO_COMMAND_SHOW_LAYOUT_STRING
);
470 case IRRECO_COMMAND_WAIT
:
471 IRRECO_RETURN_STR(IRRECO_COMMAND_WAIT_STRING
);
473 IRRECO_RETURN_PTR(NULL
);
476 IrrecoCmdType
irreco_cmd_str_to_type(const gchar
* type
)
479 if (strcmp(type
, IRRECO_COMMAND_NONE_STRING
) == 0) {
480 IRRECO_RETURN_INT(IRRECO_COMMAND_NONE
);
482 } else if (strcmp(type
, IRRECO_COMMAND_NEXT_REMOTE_STRING
) == 0) {
483 IRRECO_RETURN_INT(IRRECO_COMMAND_NEXT_REMOTE
);
485 } else if (strcmp(type
, IRRECO_COMMAND_PREVIOUS_REMOTE_STRING
) == 0) {
486 IRRECO_RETURN_INT(IRRECO_COMMAND_PREVIOUS_REMOTE
);
488 } else if (strcmp(type
, IRRECO_COMMAND_FULLSCREEN_TOGGLE_STRING
) == 0) {
489 IRRECO_RETURN_INT(IRRECO_COMMAND_FULLSCREEN_TOGGLE
);
491 } else if (strcmp(type
, IRRECO_COMMAND_SHOW_BACKEND_STRING
) == 0) {
492 IRRECO_RETURN_INT(IRRECO_COMMAND_BACKEND
);
494 } else if (strcmp(type
, IRRECO_COMMAND_SHOW_LAYOUT_STRING
) == 0) {
495 IRRECO_RETURN_INT(IRRECO_COMMAND_SHOW_LAYOUT
);
497 } else if (strcmp(type
, IRRECO_COMMAND_WAIT_STRING
) == 0) {
498 IRRECO_RETURN_INT(IRRECO_COMMAND_WAIT
);
501 IRRECO_RETURN_INT(-1);
505 void irreco_cmd_to_keyfile(IrrecoCmd
*command
,
511 irreco_gkeyfile_set_string(keyfile
, group
, "type",
512 irreco_cmd_type_to_str(command
->type
));
514 if (command
->type
== IRRECO_COMMAND_BACKEND
) {
515 irreco_gkeyfile_set_string(keyfile
, group
, "type",
516 IRRECO_COMMAND_SHOW_BACKEND_STRING
);
517 irreco_gkeyfile_set_string(keyfile
, group
,
519 command
->backend
.instance
->name
);
520 irreco_gkeyfile_set_string(keyfile
, group
, "device-name",
521 command
->backend
.device_name
);
522 irreco_gkeyfile_set_string(keyfile
, group
, "command-name",
523 command
->backend
.command_name
);
525 } else if (command
->type
== IRRECO_COMMAND_SHOW_LAYOUT
) {
526 irreco_gkeyfile_set_string(keyfile
, group
, "type",
527 IRRECO_COMMAND_SHOW_LAYOUT_STRING
);
528 irreco_gkeyfile_set_string(keyfile
, group
, "show-layout",
529 command
->layout
.name
);
531 } else if (command
->type
== IRRECO_COMMAND_WAIT
) {
532 g_key_file_set_integer(keyfile
, group
, "delay",
533 command
->wait
.delay
);
539 static IrrecoCmdType
irreco_cmd_type_from_keyfile(IrrecoKeyFile
* keyfile
)
542 gchar
*type_name
= NULL
;
545 if (irreco_keyfile_get_str(keyfile
, "type", &type_name
) == FALSE
) {
546 IRRECO_RETURN_INT(-1);
549 if ((type
= irreco_cmd_str_to_type(type_name
)) == -1) {
550 IRRECO_ERROR("Unknown command type \"%s\"\n", type_name
);
554 IRRECO_RETURN_INT(type
);
557 IrrecoCmd
* irreco_cmd_from_keyfile(IrrecoData
* irreco_data
,
558 IrrecoKeyFile
* keyfile
)
565 type
= irreco_cmd_type_from_keyfile(keyfile
);
566 if (type
== -1) IRRECO_RETURN_PTR(NULL
);
568 /* Create IrrecoCmd. */
570 case IRRECO_COMMAND_NONE
:
571 case IRRECO_COMMAND_NEXT_REMOTE
:
572 case IRRECO_COMMAND_PREVIOUS_REMOTE
:
573 case IRRECO_COMMAND_FULLSCREEN_TOGGLE
:
574 command
= irreco_cmd_create();
575 irreco_cmd_set_builtin(command
, type
);
576 IRRECO_RETURN_PTR(command
);
579 case IRRECO_COMMAND_BACKEND
: {
580 gchar
*instance_name
= NULL
;
581 gchar
*device_name
= NULL
;
582 gchar
*command_name
= NULL
;
583 IrrecoBackendInstance
* backend_instance
;
585 if (!irreco_keyfile_get_str(keyfile
, "instance-name",
587 !irreco_keyfile_get_str(keyfile
, "device-name",
589 !irreco_keyfile_get_str(keyfile
, "command-name",
591 g_free(instance_name
);
593 g_free(command_name
);
594 IRRECO_RETURN_PTR(NULL
);
597 if (!irreco_backend_manager_find_instance(
598 irreco_data
->irreco_backend_manager
,
600 &backend_instance
)) {
601 IRRECO_ERROR("Could not find instance with name "
602 "\"%s\"\n", instance_name
);
603 IRRECO_RETURN_PTR(NULL
);
605 command
= irreco_cmd_create();
606 irreco_cmd_set_backend(command
,
611 g_free(instance_name
);
613 g_free(command_name
);
614 IRRECO_RETURN_PTR(command
);
617 case IRRECO_COMMAND_SHOW_LAYOUT
: {
619 if (!irreco_keyfile_get_str(keyfile
, "show-layout",
621 IRRECO_RETURN_PTR(NULL
);
624 command
= irreco_cmd_create();
625 irreco_cmd_set_layout(command
, show_layout
);
627 IRRECO_RETURN_PTR(command
);
630 case IRRECO_COMMAND_WAIT
: {
632 if (!irreco_keyfile_get_uint(keyfile
, "delay", &delay
)) {
633 IRRECO_RETURN_PTR(NULL
);
636 command
= irreco_cmd_create();
637 irreco_cmd_set_wait(command
, delay
);
638 IRRECO_RETURN_PTR(command
);
642 IRRECO_DEBUG("Unknown command type id \"%i\".\n", type
);
643 IRRECO_RETURN_PTR(NULL
);