#ifndef _library__portctrl_data__hpp__included__ #define _library__portctrl_data__hpp__included__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "json.hpp" #include "threads.hpp" #include "memtracker.hpp" namespace binarystream { class input; class output; } /** * Memory to allocate for controller frame. */ #define MAXIMUM_CONTROLLER_FRAME_SIZE 128 /** * Maximum amount of data frame::display() can write. */ #define MAX_DISPLAY_LENGTH 128 /** * Maximum amount of data frame::serialize() can write. */ #define MAX_SERIALIZED_SIZE 256 /** * Size of controller page. */ #define CONTROLLER_PAGE_SIZE 65500 /** * Special return value for deserialize() indicating no input was taken. */ #define DESERIALIZE_SPECIAL_BLANK 0xFFFFFFFFUL namespace portctrl { extern const char* movie_page_id; /** * Is not field terminator. * * Parameter ch: The character. * Returns: True if character is not terminator, false if character is terminator. */ inline bool is_nonterminator(char ch) throw() { return (ch != '|' && ch != '\r' && ch != '\n' && ch != '\0'); } /** * Read button value. * * Parameter buf: Buffer to read from. * Parameter idx: Index to buffer. Updated. * Returns: The read value. */ inline bool read_button_value(const char* buf, size_t& idx) throw() { char ch = buf[idx]; if(is_nonterminator(ch)) idx++; return (ch != '|' && ch != '\r' && ch != '\n' && ch != '\0' && ch != '.' && ch != ' ' && ch != '\t'); } /** * Read axis value. * * Parameter buf: Buffer to read from. * Parameter idx: Index to buffer. Updated. * Returns: The read value. */ short read_axis_value(const char* buf, size_t& idx) throw(); /** * Write axis value. * * Parameter buf: The buffer to write to. * Parameter _v: The axis value. * Returns: Number of bytes written. */ size_t write_axis_value(char* buf, short _v); /** * Skip whitespace. * * Parameter buf: Buffer to read from. * Parameter idx: Index to buffer. Updated. */ inline void skip_field_whitespace(const char* buf, size_t& idx) throw() { while(buf[idx] == ' ' || buf[idx] == '\t') idx++; } /** * Skip rest of the field. * * Parameter buf: Buffer to read from. * Parameter idx: Index to buffer. Updated. * Parameter include_pipe: If true, also skip the '|'. */ inline void skip_rest_of_field(const char* buf, size_t& idx, bool include_pipe) throw() { while(is_nonterminator(buf[idx])) idx++; if(include_pipe && buf[idx] == '|') idx++; } /** * Serialize short. */ inline void serialize_short(unsigned char* buf, short val) { buf[0] = static_cast(val) >> 8; buf[1] = static_cast(val); } /** * Serialize short. */ inline short unserialize_short(const unsigned char* buf) { return static_cast((static_cast(buf[0]) << 8) | static_cast(buf[1])); } class type; /** * Index triple. * * Note: The index 0 has to be mapped to triple (0, 0, 0). */ struct index_triple { /** * If true, the other parameters are valid. Otherwise this index doesn't correspond to anything valid, but still * exists. The reason for having invalid entries is to be backward-compatible. */ bool valid; /** * The port number. */ unsigned port; /** * The controller number. */ unsigned controller; /** * The control number. */ unsigned control; }; /** * Controller index mappings */ struct index_map { /** * The poll indices. */ std::vector indices; /** * The logical controller mappings. */ std::vector> logical_map; /** * Legacy PCID mappings. */ std::vector> pcid_map; }; class type_set; /** * A button or axis on controller */ struct button { /** * Type of button */ enum _type { TYPE_NULL, //Nothing (except takes the slot). TYPE_BUTTON, //Button. TYPE_AXIS, //Axis. TYPE_RAXIS, //Relative Axis (mouse). TYPE_TAXIS, //Throttle Axis (does not pair). TYPE_LIGHTGUN, //Lightgun axis. }; enum _type type; char32_t symbol; std::string name; bool shadow; int16_t rmin; //Range min. int16_t rmax; //Range max. bool centers; std::string macro; //Name in macro (must be prefix-free). char msymbol; //Symbol in movie. /** * Is analog? */ bool is_analog() const throw() { return type == (TYPE_AXIS) || (type == TYPE_RAXIS) || (type == TYPE_TAXIS) || (type == TYPE_LIGHTGUN); } }; /** * A controller. */ struct controller { std::string cclass; //Controller class. std::string type; //Controller type. std::vector