Labeled Shmdata for Quiddity
Summary
Shmdata writer and follower inside Quiddities should be granted with labels, allowing them to be addressed specifically. This will impact connection related methods, but also make it possible to connect specific Shmdata of a Quiddity.
(Shmdata writer is the mechanism that make quiddities writing into a Shmdata. A similar mechanism is available for reading Shmdata, it is called Shmdata follower. They both add a layer to the raw Shmdata Follower and Writer class: provide monitoring and introspection information for the quiddity user.)
Motivation
Provide a mechanism that allows quiddities to connect a specific Shmdata to another specific Shmdata of another quiddity. This is particularly required for quiddity with multiple Shmdata follower, or multiple Shmdata writer. Currently, the connection method does not allow that and some quiddity internally implement complex mechanism in order to select which Shmdata to connect to which internal thing. For instance, the RTMP quiddity takes 1 audio input and 1 video input and select connection using caps, but it can be worst with quiddity that requires to read of multiple Shmdata of the same type, as it was the case with the posture quiddity that required to simultaneously read two video streams, "texture" and "point cloud".
The purpose of this refactoring is to add labels & ID to Shmdata writer and reader in quiddities, and use them in the connection API in order to simplify the writing quiddity with multiple Shmdata. In turn, it is expected to provide a more powerful quiddity API.
The timing (now) is motivated by the following:
- Scenic 4 has just been released, and the new version will rely on python wrapper, as well as the haptic floor project. It seems preferable to apply breaking changes before these actions
- The switcher documentation, with the objective to build a better process for use and contribution, should follow the documentation of Shmdata. Again, these breaking changes should happen before this.
Proposal
New Connection specification spec
The following example illustrates how a quiddity will provide connection specification to the rest of the world. I will be provided by each quiddity subclass (or defaulted to empty) and made available to the switcher user as an introspection mechanism. This spec might be changed on the fly.
"follower":
[
{
"label": "texture",
"description": "blablabal"
"can_do": ["video/x-raw, format=S16LE"]
},
{
"label": "mic%d",
"description": "blablabal"
"can_do": ["audio/x-raw, ...", "audio/mpeg"],
},
{
"label": "custom",
"description": "blablabal"
"can_do": "",
}
]
"writer":
[
{
"label": "texture",
"description": "blablabal"
"can_do": ["video/x-raw, format=S16LE"]
},
{
"label": "mic%d",
"description": "blablabal"
"can_do": ["audio/x-raw, ...", "audio/mpeg"]
},
{
"label": "custom",
"description": "blablabal"
"can_do": ["ltc/diff"]
}
]
New Quiddity connection API (Claw class)
Connection methods instead of being available as quiddity methods the user "invoke", it will be available as delegate in the quiddity class, as it is currently the case for properties, methods, signals and trees.
Here follows a proposal of C++ API. The Python API will be added to the quiddity wrapper, in the same way as property, signal and method APIs are.
// ------------------------------------------------------------------------------
// file quiddity.hpp
// a tree with the connection spec, same as specified by the user,
// but an extra id (sid_t) is given by the connection spec class
Make_consultable(Quiddity, InfoTree, connection_spec_.get(), connection_spec);
//Connector
Make_consultable(Quiddity, Claw, &claw_, claw);
// -------------------------------------------------------------------------------
// file Claw.hpp, a Friend of the quiddity class
// sid are specs for shmdata spec identification
// for reader connid will be writen in the infotree with the shmdata information
Class(Quiddity* quid, const std::string& connection_spec, )
public:
using OnConnect_t = std::function<bool(const std::string& /*shmpath*/, sid_t /*sid*/)>;
using OnDisconnect_t = std::function<bool(sid_t /*sid*/)>;
// reader quiddity
conid_t connect(sid_t local_sid, quiddity::qid_t writer_quid, sid_t writer_sid);
conid_t connect(sid_t local_sid, const std::string& shmpath);
bool disconnect(conid_t);
// label & sid converion connect using shmdata labels
std::string get_label(sid_t writer_sid);
std::string get_shmpath(sid_t id);
sid_t get_sid(const std::string& label);
// dynamic specs
bool add_follower_spec(InfoTree::ptr spec);
bool add_writer_spec(InfoTree::ptr spec);
bool remove_follower_spec(const std::string& label);
bool remove_writer_spec(const std::string& label);
// test if connection is possible
bool can_sink_caps(shmdat::Type caps, sid_t local_sid);
sid_t get_first_compatible_sid(shmdat::Type caps);
std::vector<sid_t> get_compatible_sids(shmdat::Type caps);
New API for use in Quiddity
Quiddity will inherit from this class. SID are Shmdata ID, associated to labels
// forward spec to quiddity, possibly conspec could be a static class member
// in the initialization list:
Quiddity(std::forward<quiddity::Config>(conf), const std::string& clawspec, callbacks);
Impact on already existing code
- connect and disconnect are no longer Quiddity method, but part of the switcher API
- invoke is not required anymore, but rather connect methods are part of the Quiddity API.
- Impacts switcher-ctrl, C++ API and python API
- remove use of Shmdata writer suffix in favour of explicit naming
- ".shmdata.writer.suffix" will disappear from quiddity information tree
- connect(quid_id, suffix) must be rewritten with connect(quid) that determine automagically which Shmdata to connect with, or better with connect(local_sid, writer_quid_id, writer_sid)
- remove
- ".shmdata.max_reader" in the Quiddity infotree
- max reader can be obtained by analysis of the connection spec, and may be added to the Quiddity connection API
Roadmap
- Implement new API
- create a ConnectionSpec class and include it in Quiddities that Writes or Read Shmdata
- write a ConnectionSpec test
- document how to write specs (quiddity dev) and how to read it (switcher user)
- write the Claw class
- write a test Quiddity with multiple writers and multiple readers
- document how Quiddity connects
- write a C++ connect test with the new Quiddity
- Refactor critical quiddities
- RTMP
- avrec
- executor
- shm-delay
- Add the new system to all quiddities and bundle
- add to all quiddities
- update C++ API and tests
- update python API and python examples
- Add connect to switcher-ctrl
- Remove old API
- remove Connector class
- remove unused methods, as mentioned in the Refactoring section
More details
Possible Improvement after refactoring
The following improvements are not possible currently, without a significant refactoring or addition of very specific code
- Get SIP quiddity refactored with the connection instead of managing per-contact connection internally
- Bundle with multiple reader
- Bundle with Shmdata specific connection
- Get the entire connection state in JSON, and possibly implement a "scene" feature (switching among several states of connections) in switcher that could be included in switcher save file
- Get rid of Quiddity category since the ConnectionSpec provide a more powerful way to determine what the Quiddities do with Shmdata
- Design and Implement tests that connects automatically what can be connected