title: Design notes for Telepathy-Ring version: 2011-02-04 General ------- Telepathy-ring is a Telepathy connection manager for GSM and similar Circuit Switched (CS) mobile telephony. Currently, it implements basic Connection Manager functionality with Contacts and Capabilities extensions, StreamedMedia channels for voice calls, and Text channel for SMS. Testing ------- For testing basic functionality, use the 'tests/check-ring.sh' script, or separate ltap-phone-script or ltap-sim packages. Use of CS Telephone ------------------- Interface between the host and the CS TE (terminal equipment, in other words, actual phone or modem) is implemented using the "modem" libraries and D-Bus services provided by oFono. The modem library interface provides uniform interface towards the phone, be it physically and software-wise implemented in any way. The Telepathy Connection interface represent the links towards the Call, SMS and SIM services provided by TE. The Call and SMS links are implemented using telepathy-glib ChannelManager interface. Short Overview of Telepathy Media Handling with VoIP Calls ---------------------------------------------------------- The Telepathy framework has been originally developed with VoIP calls in mind. With VoIP. the call signaling and media connections use separate transport streams and they can be handled by separate software elements. For example, when a SIP VoIP call is set up, the phone application can start up a separate stream engine process. The stream engine takes care of the actual media transport and processing. The Telepathy.Channel.Type.StreamedMedia interface is used to represent the signaling connection of a VoIP call within the Telepathy connection manager. The channel provides additional media handler interfaces in order set up and negotiate the separate media connections for the VoIP call. When the call is set up, the new Telepathy.Channel instance is dispatched to the ChannelHandler responsible for the StreamedMedia channels. It is usually the actual call UI application, taking care of user interface and media aspects. While the Telepathy framework provides a Stream Engine package for media processing, it does specify that a Telepathy client should use this particular media stream engine with standard interfaces, however. The media stream engine uses the Telepathy.Channel.Interface.MediaSignaling in order to obtain the call-specific Media.SessionHandler interface(s) from the signaling channel. After signaling channel has been informed that the media engine is ready to set up the media streams, it creates Media.StreamHandler interface instances for each media stream within the session and emits them to the media engine. The Media.StreamHandler interface is then used to negotiate and set up the individual media stream(s). The call UI application itself does not necessarily use the above-mentioned media signaling interfaces directly. It can use Channel.Type.StreamedMedia interface towards the call signaling and the Telepathy.StreamEngine interface towards the media stream engine. Unfortunately, that latter interface is not mandatory part of the Telepathy framework. CS Calls and Media Handling in Telepathy ---------------------------------------- The TelepathyChannel object can be used represent a circuit switched call connection. The optional interfaces like Channel.Interface.DTMF or Channel.Interface.Hold can be used as is with the CS call. However, the media handling is more problematic. The media within a circuit-switched call can be handled with different modes, depending on the processing it requires: 1) TE has its own, independent media handling (e.g., TE is a separate phone connected through USB or Bluetooth) 2) TE uses same media devices as host applications, but it takes care of obtaining the media processing resources by itself (e.g, TE is a GSM module which connects directly to the audio hw) - Note: some audio (or video) pre-emption may be needed even in this case 3) TE emits audio frames via the libcs connection to the host for processing (e.g., TE is a GSM module which has no connection to audio hw, but the host software must take care of encoding and decoding audio) The cases 1 and 2 are referred as "independent media" and case 3 as "shared media" below. Independent media mode requires more attention from the telepathy client handling the CS call channels. Either no media stream engine is started, or all the media stream engines should be able to detect the media mode as described above. The shared media mode looks pretty much like the VoIP case above: a separate media stream engine should be started and it negotiates the media transport connection using the media handler interfaces. However, the existing Media.StreamHandler interface is very VoIP-centric. Even the very basic media semantics are quite different when handling a CS call. There are multiple options for handling the CS calls: 1) Add new Channel type (e.g., CircuitMedia) and ChannelHandlers 2) Add CS call support to the standard Telepathy Stream Engine 3) Add separate CS Stream Engine With the latter option options, the existing telepathy clients that use the Telepathy Stream Engine can make CS calls with no or minimal changes. There are also multiple options handling the the media signaling interface between the CS call channel and the media stream: 1) Do not implement Telepathy.Channel.Interface.MediaSignaling with CS call 2) Integrate CS Stream Engine with CS Connection Manager (and use private interfaces between signaling and media) 3) Add new Telepathy.Channel.Interface (e.g., CircuitMediaSignaling) 4) Extend Media.SessionHandler interface 5) Extend Media.StreamHandler interface The third option may require new interfaces not unlike Media.SessionHandler or Media.StreamHandler for handling different media within a multimedia CS call. The media engine design does not necessarily need any interface towards application. The microphone muting and adjusting volume levels is best done with system-level means and policy. The final design decision was to not to provide any Telepathy interface to control CS call media, but instead tightly couple the media engine with the modem. CS Call Handling Assumptions ---------------------------- The discussion below follows these assumptions: - a CS call object has RingMediaChannel DBUS interface which implements - Telepathy.Channel.Type.StreamedMedia (as is) - Telepathy.Channel.Interface.Group (accepting or rejecting calls) - Telepathy.Channel.Interface.DTMF (sending or receiving DTMF tones) - Telepathy.Channel.Interface.Hold (placing call on hold or retrieving it) There is no Telepathy.Channel.Interface.MediaSignaling. Outbound calls -------------- - client requests a Channel.Type.StreamedMedia with target id (dialed telephone number) using the Connection.Requests.CreateChannel() method - RingCallChannel object (rc) is created - RingConnection emits NewChannel with ringchannel - emit MembersChanged: - selfhandle is added to current members - handle for dialed number is added to the list of remote pending members - client requests channel to set up media streams to remote handle with Telepathy.Channel.Type.StreamedMedia.RequestStreams() method - RingCallChannel calls modem_call_request_dial() (org.ofono.VoiceCallManager.Dial()) - emit StreamAdded() signal for audio stream - RingCallChannel receives MODEM_CALL_STATE_DIALING - emits StreamStateChanged with TP_MEDIA_STREAM_STATE_CONNECTING - RingCallChannel receives MODEM_CALL_STATE_ALERTING - emits StreamStateChanged with TP_MEDIA_STREAM_STATE_CONNECTED - emits StreamDirectionChanged with TP_MEDIA_STREAM_DIRECTION_RECEIVE, TP_MEDIA_STREAM_PENDING_REMOTE_SEND cleared and TP_MEDIA_STREAM_PENDING_LOCAL_SEND set - RingCallChannel receives MODEM_CALL_STATE_ACTIVE - emits MembersChanged signal where remote handle (bob) is added as proper member - emits StreamStateChanged with TP_MEDIA_STREAM_STATE_CONNECTED - emits StreamDirectionChanged with both TP_MEDIA_STREAM_PENDING_REMOTE_SEND and TP_MEDIA_STREAM_PENDING_LOCAL_SEND cleared Incoming calls -------------- - RingConnection gets 'incoming' signal from modem/call-service (Calls property in Ofono) - binds remote telephone number to a handle - creates new RingCallChannel (rc) object for handle with remote user and audio stream - emits NewChannel signal - emit MembersChanged signal: - handle (handle) is added to the list of current members - selfhandle is added to local pending members - emits StreamAdded indicating that an audio stream has been added - NewChannel (and MembersChanged?) is dispatched to client - RingCallChannel receives MODEM_CALL_STATE_{INCOMING,WAITING} - emits StreamStateChanged (TP_MEDIA_STREAM_STATE_CONNECTED) - emits StreamDirectionChanged with TP_MEDIA_STREAM_DIRECTION_SEND, TP_MEDIA_STREAM_PENDING_REMOTE_SEND set and TP_MEDIA_STREAM_PENDING_LOCAL_SEND cleared - client accepts the call with Channel.Interface.Group.AddMembers (adding selfhandle to members) - RingCallChannel invokes modem_call_answer() (VoiceCall.Answer method) - RingCallChannel receives MODEM_CALL_STATE_ACTIVE - emits MembersChanged signal where self handle is added as proper member - emits StreamStateChanged with TP_MEDIA_STREAM_STATE_CONNECTED - emits StreamDirectionChanged with both TP_MEDIA_STREAM_PENDING_REMOTE_SEND and TP_MEDIA_STREAM_PENDING_LOCAL_SEND cleared