User Section

The platform has a test interface accessible via telnet port 23000.  This interface is enabled for the IP address of RI_Platform as configured in platform.cfg:

# The IP address of the interface on THIS machine which the RIPlatform uses
RI.Platform.IpAddr = 192.168.144.100

There exists an initial menu that can change based on which system modules have registered their menus/handlers:

> telnet localhost 23000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
  Test Application v1.00
|--+----------------------
| p | Platform
|--+----------------------
| u | UAL
|--+----------------------
| g | Gstreamer pipline
|--+----------------------
| d | Display
|--+----------------------
| m | MPEOS Media
|--+----------------------
| o | MPEOS POD
|--+----------------------
| q | MPEOS Display
|--+----------------------
| r | MPEOS Recording
|--+----------------------
| t | MPEOS TSB
|--+----------------------
| h | MPEOS HN
|--+----------------------
| x | Exit 
|--+----------------------
//Test > 

Enter these menus by typing the adjacent key; e.g. entering 'p' results in:

----------------------------
| Platform
|--+----------------------
| b | destroy Backpanel     
|--+----------------------
| d | Dump memory info      
|--+----------------------
| f | destroy Frontpanel    
|--+----------------------
| l | Log text              
|--+----------------------
| m | destroy ui Manager    
|--+----------------------
| p | destroy Pipeline mgr  
|--+----------------------
| x | Exit 
|--+----------------------
//Test/Platform > 

A given menu may have sub menus and when those are entered the command prompt changes to show the current menu depth.  The following menu was reached by the user selecting 'u' for UAL, then 'u' again for UPnP, and finally 'm' for MMI.  The user may now make an MMI menu selection and observe the corresponding results...

----------------------------
| MMI
|--+----------------------
| o | Open MMI dialog
|--+----------------------
| b | open Broadcast MMI
|--+----------------------
| c | Close MMI dialog
|--+----------------------
| d | Dump event lists
|--+----------------------
| p | Post event
|--+----------------------
| g | Get event
|--+----------------------
| e | complete Event
|--+----------------------
| x | Exit 
|--+----------------------
//Test/UAL/UPnP/MMI > 

Each menu has an 'x' at the bottom and selecting 'x' will exit the current menu and return to the previous.  Selecting an individual menu item will invoke that particular action.  Menu items may require additional user input; e.g. selecting 'l' for "Log text" results in the userbeing prompted for the text to log:

----------------------------
| Platform
|--+----------------------
| b | destroy Backpanel     
|--+----------------------
| d | Dump memory info      
|--+----------------------
| f | destroy Frontpanel    
|--+----------------------
| l | Log text              
|--+----------------------
| m | destroy ui Manager    
|--+----------------------
| p | destroy Pipeline mgr  
|--+----------------------
| x | Exit 
|--+----------------------
//Test/Platform > 
logging: 

...and when the user enters the text to log, they are returned to the menu:

logging: my text to send to the log
----------------------------
| Platform
|--+----------------------
| b | destroy Backpanel     
|--+----------------------
| d | Dump memory info      
|--+----------------------
| f | destroy Frontpanel    
|--+----------------------
| l | Log text              
|--+----------------------
| m | destroy ui Manager    
|--+----------------------
| p | destroy Pipeline mgr  
|--+----------------------
| x | Exit 
|--+----------------------
//Test/Platform > 

Developer Section

The telnet interface is useful to generate stimulus from the STB that the RI generally doesn't have; i.e. a display change that triggers a video output port event etc.  The underlying infrastructure has been made such that any 'C' module in the platform or MPEOS can use it with relative ease.

To use the telnet test interface from the platform code, one must have the following include:

#include <test_interface.h>

If using the interface from the MPEOS code, the following include is required:

#include <ri_test_interface.h>

To add a menu, one simply needs to generate a single menu string:

#define PLATFORM_TESTS \
    "\r\n" \
    "|---+----------------------\r\n" \
    "| b | destroy Backpanel     \r\n" \
    "|---+----------------------\r\n" \
    "| d | Dump memory info      \r\n" \
    "|---+----------------------\r\n" \
    "| f | destroy Frontpanel    \r\n" \
    "|---+----------------------\r\n" \
    "| l | Log text              \r\n" \
    "|---+----------------------\r\n" \
    "| m | destroy ui Manager    \r\n" \
    "|---+----------------------\r\n" \
    "| p | destroy Pipeline mgr  \r\n"

Next, a handler typed of a well known interface found in the appropriate include file is required:

int testInputHandler(int sock, char *rxBuf)
{
    char buf[1024];
    RILOG_TRACE("%s -- Entry, received: %s\n", _FUNCTION_, rxBuf);


    if (strstr(rxBuf, "b"))
    {
        test_SendString(sock, "\r\n\ndestroy backpanel...\r\n");
        destroy_backpanel(get_backpanel());
        return 0;
    }
    else if (strstr(rxBuf, "d"))
    {
        test_SendString(sock, "\r\n\nMemory Information:\r\n");
        g_mem_profile();
        return 0;
    }
    else if (strstr(rxBuf, "f"))
    {
        test_SendString(sock, "\r\n\ndestroy frontpanel...\r\n");
        destroy_frontpanel(get_frontpanel());
        return 0;
    }
    else if (strstr(rxBuf, "l"))
    {
        if (test_GetString(sock, buf, sizeof(buf), "\r\n\nlogging: "))
        {
            RILOG_INFO("%s \-\- REMOTE LOG: %s\n", \__FUNCTION__, buf);
        }
        else
        {
            RILOG_ERROR("%s \-\- test_GetString failure?\!\n", \__FUNCTION__);
        }
        return 0;
    }
    else if (strstr(rxBuf, "m"))
    {
        test_SendString(sock, "\r\n\ndestroy ui manager...\r\n");
        destroy_ui_manager();
        return 0;
    }
    else if (strstr(rxBuf, "p"))
    {
        test_SendString(sock, "\r\n\ndestroy pipeline manager...\r\n");
        destroy_pipeline_manager();
        return 0;
    }
    else if (strstr(rxBuf, "x"))
    {
        RILOG_TRACE("%s \-\- Exit", \__FUNCTION__);
        return -1;
    }
    else
    {
        strcat(rxBuf, " - unrecognized\r\n\n");
        test_SendString(sock, rxBuf);
        RILOG_TRACE("%s \-\- %s\n", \__FUNCTION__, rxBuf);
        return 0;
    }
}

Each handler must handle the 'x' for exit case, if not the user will be stranded in the offending menu.
Once the menu string and handler are written they are paired in a well known struct:

static MenuItem PlatformMenuItem =
{ true, "p", "Platform", PLATFORM_TESTS, testInputHandler }

This struct as defined in test_interface.h contains:

  1. a boolean flag indicating if this menu item gets displayed from the base
  2. the character that selects the menu item (must be unique within the parent menu)
  3. a string representing the title of this menu (must be unique across all menus)
  4. a string representing the text to be displayed (i.e. menu items)
  5. the function pointer to the char-based input handler

With the menu, handler, and struct in place, one must register with the supporting subsystem:

test_RegisterMenu(&PlatformMenuItem);

This inserts the above example menu at the base level and anytime the 'p' key is selected from that menu the subsystem will display the example menu string and flow of control is passed to the example handler when a key is hit.  If one chooses to have a sub-menu to better organize their menu items, the handler must make use of the test_FindMenu() and test_SetNextMenu() functions within the case of the selection for the sub-menu:

    else if (strstr(rxBuf, "u"))
    {
        if (!test_SetNextMenu(test_FindMenu("UPnP")))
        {
            RILOG_ERROR("%s \-\- UPnP sub-menu failed?\n", \__FUNCTION__);
            return 0;
        }
        else
        {
            return 1;
        }
    }

It should be noted that the sub-menu MenuItem struct would not have the boolean flag for "display from base" set.
The subsystem tracks the menu depth and return path and an 'x' selection within a given menu as properly handled by its handler will exit to the previous menu in the stack.  As may have been noticed, the return code from the handler moves within the menu stack; e.g. returning -1 when an 'x' is selected returns to the previous menu, returning 0 stays in the current menu, and returning 1 advances to the next menu as set by the test_SetNextMenu() call.  It is also worth noting that the sock passed into a given handler is also the sock that must be used on all outbound I/O calls.

The following interfaces are supported in the subsystem:

#define MAX_MENU_ITEMS 16
#define MAX_MENU_DEPTH 6
#define MAX_MENUS (MAX_MENU_ITEMS * MAX_MENU_DEPTH)

typedef struct _MenuItem
{
    ri_bool base;   // does this menu item get displayed from the base?
    char *sel_char; // char that causes this menu item to be invoked
    char *title;    // the title of this menu item
    char *text;     // the text to be displayed (i.e. sub menu items)
    int (*handleInput)(int sock, char *rxBuf); // the char-based input handler
} MenuItem;

//
// ri_test_RegisterMenu  registers new menus with the RI test interface
//                       infrastructure.
//
// pMenuItem             pointer to the MenuItem struct to register with the
//                       RI test interface
// returns               success/fail of registration operation
//
RI_MODULE_EXPORT ri_bool ri_test_RegisterMenu(MenuItem *pMenuItem);
        
//  
// ri_test_SetNextMenu   selects the provided menu for continued operation;
//                       i.e. used to traverse up or down in the menu tree
//      
// index                 the index (returned from FindMenu) of the menu to
//                       select
// returns               success/fail of selection operation
//      
RI_MODULE_EXPORT ri_bool ri_test_SetNextMenu(int index);
        
//      
// ri_test_FindMenu      finds a menu within the RI test interface
//                       infrastructure.
//  
// title                 title of the menu to find
// returns               the index of the menu (or MAX_MENUS if not found)
//              
RI_MODULE_EXPORT int ri_test_FindMenu(char *title);
        
//          
// ri_test_GetByte       gets at least one byte from the input stream if open
//      
// sock                  the socket of the input stream
// buf                   the char buffer to place the received bytes into
// size                  the size of the output char buffer (described above)
// returns               the number of bytes read
//  
RI_MODULE_EXPORT int ri_test_GetByte(int sock, char *buf, int size);
    
//      
// ri_test_GetString     gets 'size' bytes from the input stream if open
//          
// sock                  the socket of the input stream
// buf                   the char buffer to place the received bytes into
// size                  the size of the output char buffer (described above)
// prompt                an optional string to display before getting input
// returns               the number of bytes read
//      
RI_MODULE_EXPORT int ri_test_GetString(int sock, char *buf, int size, char *prompt);
    
//      
// ri_test_GetNumber     gets an integer from the input stream if open
//  
// sock                  the socket of the input stream
// buf                   the char buffer to place the received bytes into
// size                  the size of the output char buffer (described above)
// prompt                an optional string to display before getting input
// dfault                the default value to return if obtaining a number fails
// returns               the number obtained or dfault (described above)
//
RI_MODULE_EXPORT int ri_test_GetNumber(int sock, char *buf, int size, char *prompt, int dfault);


// 
// ri_test_SendString    sends a string to the output stream if open
//
// sock                  the socket of the output stream
// string                the char buffer to send
//
RI_MODULE_EXPORT void ri_test_SendString(int sock, char *string);

Key events may be injected into the RI via this Telnet interface - see the following link to learn how: Automating Key Events.

  • No labels