2024-08-14 00:33:52 +03:00
# include <stdio.h>
# include <unistd.h>
# include "getchar.h"
# include "../processing.h"
2024-08-15 21:57:17 +03:00
# include "../module_registry.h"
2024-08-14 00:33:52 +03:00
typedef struct {
GraphNode as_GraphNode ;
IOHandling subscription ;
2024-08-14 23:23:21 +03:00
int32_t namespace ;
2024-08-14 00:33:52 +03:00
} GetcharGraphNode ;
static void
handle_io ( EventPositionBase * self , int fd , bool is_output )
{
( void ) is_output ;
GetcharGraphNode * node = DOWNCAST ( GetcharGraphNode , GraphNode , DOWNCAST ( GraphNode , EventPositionBase , self ) ) ;
char buf [ 1 ] ;
ssize_t status = read ( fd , buf , 1 ) ;
if ( status < 0 ) {
perror ( " Failed to read character " ) ;
return ;
}
EventData data = {
. code = {
. ns = 0 ,
2024-08-14 15:53:17 +03:00
. major = 0 ,
. minor = 1 ,
2024-08-14 00:33:52 +03:00
} ,
. ttl = 100 ,
. priority = 10 ,
2024-08-18 16:23:49 +03:00
. payload = ( unsigned char ) buf [ 0 ] ,
2024-08-14 00:33:52 +03:00
. modifiers = EMPTY_MODIFIER_SET ,
2024-08-14 14:47:55 +03:00
. time = get_current_time ( ) ,
2024-08-14 00:33:52 +03:00
} ;
if ( status = = 0 ) {
node - > subscription . enabled = false ;
2024-08-14 15:53:17 +03:00
data . code . minor = 2 ;
2024-08-14 00:33:52 +03:00
data . payload = 0 ;
}
for ( size_t i = 0 ; i < node - > as_GraphNode . outputs . length ; + + i ) {
EventNode * ev = event_create ( & data ) ;
if ( ! ev ) {
perror ( " Failed to create event " ) ;
break ;
}
ev - > position = & node - > as_GraphNode . outputs . elements [ i ] - > as_EventPositionBase ;
}
}
static GraphNode *
2024-08-17 12:02:26 +03:00
create ( GraphNodeSpecification * spec , GraphNodeConfig * config , InitializationEnvironment * env )
2024-08-14 00:33:52 +03:00
{
2024-08-15 17:53:02 +03:00
GetcharGraphNode * node = T_ALLOC ( 1 , GetcharGraphNode ) ;
2024-08-14 00:33:52 +03:00
if ( ! node ) {
return NULL ;
}
* node = ( GetcharGraphNode ) {
. as_GraphNode = {
. as_EventPositionBase = {
. handle_event = NULL ,
. waiting_new_event = false ,
} ,
. specification = spec ,
. inputs = EMPTY_GRAPH_CHANNEL_LIST ,
. outputs = EMPTY_GRAPH_CHANNEL_LIST ,
} ,
. subscription = {
. self = & node - > as_GraphNode . as_EventPositionBase ,
. handle_io = handle_io ,
. enabled = true ,
} ,
2024-08-19 12:21:51 +03:00
. namespace = config - > options ? env_resolve_constant ( env , config_setting_get_member ( config - > options , " namespace " ) ) : 0 ,
2024-08-14 00:33:52 +03:00
} ;
return & node - > as_GraphNode ;
}
static void destroy
( GraphNodeSpecification * self , GraphNode * target )
{
( void ) self ;
free ( target ) ;
}
static void
register_io ( GraphNodeSpecification * self , GraphNode * target , ProcessingState * state )
{
( void ) self ;
GetcharGraphNode * node = DOWNCAST ( GetcharGraphNode , GraphNode , target ) ;
io_subscription_list_add ( & state - > wait_input , fileno ( stdin ) , & node - > subscription ) ;
}
GraphNodeSpecification nodespec_getchar = ( GraphNodeSpecification ) {
. create = & create ,
. destroy = & destroy ,
. register_io = & register_io ,
. name = " getchar " ,
2024-08-18 16:26:54 +03:00
. documentation = " Converts stdin bytes to events \n Does not accept events \n Sends events on all connectors with major and minor codes (0, 1) and the read byte as payload "
" \n Option 'namespace' (optional): set namespace for the generated events "
,
2024-08-14 00:33:52 +03:00
} ;
2024-08-15 21:57:17 +03:00
MODULE_CONSTRUCTOR ( init )
{
register_graph_node_specification ( & nodespec_getchar ) ;
}