<commit_before># telepathy-spec - Base classes defining the interfaces of the Telepathy framework
#
# Copyright (C) 2005,2006 Collabora Limited
# Copyright (C) 2005,2006 Nokia Corporation
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import dbus.service

from telepathy import *

class Channel(dbus.service.Object):
    """
    All communication in the Telepathy framework is carried out via channel
    objects which are created and managed by connections. This interface must
    be implemented by all channel objects, along with one single channel type,
    such as Channel.Type.ContactList which represents a list of people (such
    as a buddy list) or a Channel.Type.Text which represents a channel over
    which textual messages are sent and received.

    Each channel may have an immutable handle associated with it, which may
    be any handle type, such as a contact, room or list handle, indicating
    that the channel is for communicating with that handle. If a channel does
    not have a handle, it means that the channel is defined by some other
    terms, such as it may be a transient group defined only by its members
    as visible through the Channel.Interface.Group interface.

    Other optional interfaces can be implemented to indicate other available
    functionality, such as Channel.Interface.Group if the channel contains
    a number of contacts, Channel.Interface.Password to indicate
    that a channel may have a password set to require entry, and
    Properties for extra data about channels which represent chat
    rooms or voice calls. The interfaces implemented may not vary after the
    channel's creation has been signalled to the bus (with the connection's
    NewChannel signal).

    Specific connection manager implementations may implement channel types and
    interfaces which are not contained within this specification in order to
    support further functionality. To aid interoperability between client and
    connection manager implementations, the interfaces specified here should be
    used wherever applicable, and new interfaces made protocol-independent
    wherever possible. Because of the potential for 3rd party interfaces adding
    methods or signals with conflicting names, the D-Bus interface names should
    always be used to invoke methods and bind signals.
    """
    def __init__(self, connection, type, handle):
        """
        Initialise the base channel object.

        Parameters:
        connection - the parent Connection object
        type - interface name for the type of this channel
        handle - the channels handle if applicable
        """
        self._conn = connection
        object_path = self._conn.get_channel_path()
        dbus.service.Object.__init__(self, self._conn._name, object_path)

        self._type = type
        self._handle = handle
        self._interfaces = set()

    @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='')
    def Close(self):
        """
        Request that the channel be closed. This is not the case until
        the Closed signal has been emitted, and depending on the connection
        manager this may simply remove you from the channel on the server,
        rather than causing it to stop existing entirely. Some channels
        such as contact list channels may not be closed.

        Possible Errors:
        Disconnected, NetworkError, NotImplemented
        """
        self.Closed()
        self._conn.remove_channel(self)

    @dbus.service.signal(CHANNEL_INTERFACE, signature='')
    def Closed(self):
        """
        Emitted when the channel has been closed. Method calls on the
        channel are no longer valid after this signal has been emitted,
        and the connection manager may then remove the object from the bus
        at any point.
        """
        pass

    @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='s')
    def GetChannelType(self):
        """ Returns the interface name for the type of this channel. """
        return self._type

    @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='uu')
    def GetHandle(self):
        """ Returns the handle type and number if this channel represents a
        communication with a particular contact, room or server-stored list, or
        zero if it is transient and defined only by its contents. """
        if self._handle:
            return self._handle.get_type(), self._handle
        else:
            return (CONNECTION_HANDLE_TYPE_NONE, 0)

    @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='as')
    def GetInterfaces(self):
        """
        Get the optional interfaces implemented by the channel.

        Returns:
        an array of the D-Bus interface names
        """
        return self._interfaces


class ChannelTypeContactSearch(Channel):
    """
    A channel type for searching server-stored user directories. A new channel
    should be requested by a client for each search attempt, and it should be
    closed when the search is completed or the required result has been found
    in order to free unused handles. The search can be cancelled at any time
    by calling the channel Close method, although depending upon the protocol
    the connection manager may not be able to prevent the server from sending
    further results.

    Before searching, the GetSearchKeys method should be used to discover any
    instructions sent by the server, and the valid search keys which can be
    provided to the Search method. A search request is then started by
    providing some of these terms to the Search method, and the search status
    will be set to CHANNEL_CONTACT_SEARCH_STATE_DURING. When results are
    returned by the server, the SearchResultReceived signal is emitted for each
    contact found, and when the search is complete, the search status will be
    set to CHANNEL_SEARCH_STATE_AFTER.
    """
    def __init__(self, connection):
        """
        Initialise the contact search channel.
        """
        Channel.__init__(self, connection, CHANNEL_TYPE_CONTACT_SEARCH)
        self._search_state = CHANNEL_SEARCH_STATE_BEFORE

    @dbus.service.method(CHANNEL_TYPE_CONTACT_SEARCH, in_signature='', out_signature='sa{s(bg)}')
    def GetSearchKeys(self):
        """
        Returns any instructions from the server along with a dictionary of
        search key names to their types, and a boolean indicating if the key is
        mandatory. The following well-known search key names should be used
        where appropriate:
         s:first - the desired contact's given name
         s:last - the desired contact's family name
         s:nick - the desired contact's nickname
         s:email - the e-mail address of the desired contact

        Returns:
        a string with any instructions from the server
        a dictionary mapping string search key names to an array of:
            booleans indicating if the search key is mandatory
            type signature of the value for this search key

        Possible Errors:
        Disconnected, NetworkError, NotAvailable
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_CONTACT_SEARCH, in_signature='a{sv}', out_signature='')
    def Search(self, terms):
        """
        Send a request to start a search for contacts on this connection. A
        valid search request will cause the SearchStateChanged signal to be
        emitted with the status CHANNEL_CONTACT_SEARCH_STATE_DURING.

        Parameters:
        a dictionary mapping search key names to the desired values

        Possible Errors:
        Disconnected, NetworkError, InvalidArgument
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_CONTACT_SEARCH, in_signature='', out_signature='u')
    def GetSearchState(self):
        """
        Returns the current state of this search channel object. One of the
        following values:
        0 - CHANNEL_CONTACT_SEARCH_STATE_BEFORE
            the search has not started
        1 - CHANNEL_CONTACT_SEARCH_STATE_DURING
            the search is in progress
        2 - CHANNEL_CONTACT_SEARCH_STATE_AFTER
            the search has been completed

        Returns:
        an integer representing the search state
        """
        return self._search_state

    @dbus.service.signal(CHANNEL_TYPE_CONTACT_SEARCH, signature='u')
    def SearchStateChanged(self, state):
        """
        Emitted when the search state (as returned by the GetSearchState
        method) changes.

        Parameters:
        state - an integer representing the new search state
        """
        self._search_state = state

    @dbus.service.signal(CHANNEL_TYPE_CONTACT_SEARCH, signature='ua{sv}')
    def SearchResultReceived(self, contact, values):
        """
        Emitted when a search result is received from the server.

        Parameters:
        an integer handle for the contact
        a dictionary mapping search key names to values for this contact
        """
        pass


class ChannelTypeContactList(Channel):
    """
    A channel type for representing a list of people on the server which is
    not used for communication. This is intended for use with the interface
    Channel.Interface.Group for managing buddy lists and privacy lists
    on the server. This channel type has no methods because all of the
    functionality it represents is available via the group interface.

    Singleton instances of this channel type should be created by the
    connection manager at connection time if the list exists on the server, or
    may be requested by using the appropriate handle.  These handles can be
    obtained using RequestHandle with a handle type of
    CONNECTION_HANDLE_TYPE_LIST and one of the following identifiers:
     subscribe - the group of contacts for whom you wish to receive presence
     publish - the group of contacts who may receive your presence
     hide - a group of contacts who are on the publish list but are temporarily disallowed from receiving your presence
     allow - a group of contacts who may send you messages
     deny - a group of contacts who may not send you messages
    """
    _dbus_interfaces = [CHANNEL_TYPE_CONTACT_LIST]

    def __init__(self, connection, handle):
        """
        Initialise the channel.

        Parameters:
        connection - the parent Telepathy Connection object
        """
        Channel.__init__(self, connection, CHANNEL_TYPE_CONTACT_LIST, handle)


class ChannelTypeStreamedMedia(Channel):
    """
    A channel that can send and receive streamed media such as audio or video.
    Provides a number of methods for listing and requesting new streams, and
    signals to indicate when streams have been added, removed and changed
    status.

    In general this should always be used in conjunction with the IceSignalling
    interface to exchange connection candidates and codec choices with
    whichever component is responsible for the streams. However, in certain
    applications where no candidate exchange is necessary (eg the streams are
    handled by specialised hardware which is controlled directly by the
    connection manager), the signalling interface can be omitted and this
    channel type used simply to control the streams.

    This channel type defines two type-specific capability flags (as used in
    Connection.Interface.Capabilities):
      CHANNEL_MEDIA_CAPABILITY_AUDIO = 1
        The handle is capable of using audio streams within a media channel.
      CHANNEL_MEDIA_CAPABILITY_VIDEO = 2
        The handle is capable of using video streams within a media channel.
    """
    def __init__(self, connection, handle):
        """
        Initialise the channel.

        Parameters:
        connection - the parent Telepathy Connection object
        """
        Channel.__init__(self, connection, CHANNEL_TYPE_STREAMED_MEDIA, handle)

    @dbus.service.method(CHANNEL_TYPE_STREAMED_MEDIA, in_signature='',
                                                      out_signature='a(uuuuuu)')
    def ListStreams(self):
        """
        Returns an array of structs representing the streams currently active
        within this channel. Each stream is identified by an unsigned integer
        which is unique for each stream within the channel.

        Stream types are identified by the following values:
          MEDIA_STREAM_TYPE_AUDIO = 0
          MEDIA_STREAM_TYPE_VIDEO = 1

        Stream states are identified by one of the following values:
          MEDIA_STREAM_STATE_DISCONNECTED = 0
            The stream is disconnected.
          MEDIA_STREAM_STATE_CONNECTING = 1
            The stream is trying to connect.
          MEDIA_STREAM_STATE_CONNECTED = 2
            The stream is connected.

        Stream directions are identified by one of the following values:
          MEDIA_STREAM_DIRECTION_NONE = 0
          MEDIA_STREAM_DIRECTION_SEND = 1
          MEDIA_STREAM_DIRECTION_RECEIVE = 2
          MEDIA_STREAM_DIRECTION_BIDIRECTIONAL = 3

        Pending directionality changes are indicated by a bitwise OR of the
        following flags:
          MEDIA_STREAM_PENDING_LOCAL_SEND = 1
            The local user has been asked to send media by the remote user.
            Call RequestStreamDirection to indicate whether or not this is
            acceptable.
          MEDIA_STREAM_PENDING_REMOTE_SEND = 2
            The remote user has been asked to send media by the local user.
            The StreamDirectionChanged signal will be emitted when the remote
            user accepts or rejects this change.

        Returns:
        an array of structs containing:
            the stream identifier
            the contact handle who the stream is with (or 0 if the stream
                represents more than a single member)
            the type of the stream
            the current stream state
            the current direction of the stream
            the current pending send flags
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_STREAMED_MEDIA, in_signature='uau',
                                                      out_signature='au')
    def RequestStreams(self, contact_handle, types):
        """
        Request that streams be established to exchange the given types of
        media with the given member. In general this will try and establish a
        bidirectional stream, but on some protocols it may not be possible to
        indicate to the peer that you would like to receive media, so a
        send-only stream will be created initially. In the cases where the
        stream requires remote agreement (eg you wish to receive media from
        them), the StreamDirectionChanged signal will be emitted with the
        MEDIA_STREAM_PENDING_REMOTE_SEND flag set, and the signal emitted again
        with the flag cleared when the remote end has replied.

        Parameters:
        contact_handle - a contact handle with whom to establish the streams
        types - an array of stream types (as defined in ListStreams)

        Returns:
        an array of newly created stream identifiers (as defined in ListStreams)
            in the same order as the given stream types

        Possible Errors:
        InvalidHandle, InvalidArgument (invalid stream type), NotAvailable (if
        the contact is not able to do this stream type)
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_STREAMED_MEDIA, in_signature='au',
                                                      out_signature='')
    def RemoveStreams(self, streams):
        """
        Request that the given streams are removed.

        Parameters:
        streams - an array of stream identifiers (as defined in ListStreams)

        Possible Errors:
        InvalidArgument (unknown stream identifier)
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_STREAMED_MEDIA, in_signature='uu',
                                                      out_signature='')
    def RequestStreamDirection(self, stream_id, stream_direction):
        """
        Request a change in the direction of an existing stream. In particular,
        this might be useful to stop sending media of a particular type,
        or inform the peer that you are no longer using media that is being
        sent to you.
<commit_msg>Channel.Type.StreamedMedia: make return value to RequestStreams identical to ListStreams<commit_after># telepathy-spec - Base classes defining the interfaces of the Telepathy framework
#
# Copyright (C) 2005,2006 Collabora Limited
# Copyright (C) 2005,2006 Nokia Corporation
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import dbus.service

from telepathy import *

class Channel(dbus.service.Object):
    """
    All communication in the Telepathy framework is carried out via channel
    objects which are created and managed by connections. This interface must
    be implemented by all channel objects, along with one single channel type,
    such as Channel.Type.ContactList which represents a list of people (such
    as a buddy list) or a Channel.Type.Text which represents a channel over
    which textual messages are sent and received.

    Each channel may have an immutable handle associated with it, which may
    be any handle type, such as a contact, room or list handle, indicating
    that the channel is for communicating with that handle. If a channel does
    not have a handle, it means that the channel is defined by some other
    terms, such as it may be a transient group defined only by its members
    as visible through the Channel.Interface.Group interface.

    Other optional interfaces can be implemented to indicate other available
    functionality, such as Channel.Interface.Group if the channel contains
    a number of contacts, Channel.Interface.Password to indicate
    that a channel may have a password set to require entry, and
    Properties for extra data about channels which represent chat
    rooms or voice calls. The interfaces implemented may not vary after the
    channel's creation has been signalled to the bus (with the connection's
    NewChannel signal).

    Specific connection manager implementations may implement channel types and
    interfaces which are not contained within this specification in order to
    support further functionality. To aid interoperability between client and
    connection manager implementations, the interfaces specified here should be
    used wherever applicable, and new interfaces made protocol-independent
    wherever possible. Because of the potential for 3rd party interfaces adding
    methods or signals with conflicting names, the D-Bus interface names should
    always be used to invoke methods and bind signals.
    """
    def __init__(self, connection, type, handle):
        """
        Initialise the base channel object.

        Parameters:
        connection - the parent Connection object
        type - interface name for the type of this channel
        handle - the channels handle if applicable
        """
        self._conn = connection
        object_path = self._conn.get_channel_path()
        dbus.service.Object.__init__(self, self._conn._name, object_path)

        self._type = type
        self._handle = handle
        self._interfaces = set()

    @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='')
    def Close(self):
        """
        Request that the channel be closed. This is not the case until
        the Closed signal has been emitted, and depending on the connection
        manager this may simply remove you from the channel on the server,
        rather than causing it to stop existing entirely. Some channels
        such as contact list channels may not be closed.

        Possible Errors:
        Disconnected, NetworkError, NotImplemented
        """
        self.Closed()
        self._conn.remove_channel(self)

    @dbus.service.signal(CHANNEL_INTERFACE, signature='')
    def Closed(self):
        """
        Emitted when the channel has been closed. Method calls on the
        channel are no longer valid after this signal has been emitted,
        and the connection manager may then remove the object from the bus
        at any point.
        """
        pass

    @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='s')
    def GetChannelType(self):
        """ Returns the interface name for the type of this channel. """
        return self._type

    @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='uu')
    def GetHandle(self):
        """ Returns the handle type and number if this channel represents a
        communication with a particular contact, room or server-stored list, or
        zero if it is transient and defined only by its contents. """
        if self._handle:
            return self._handle.get_type(), self._handle
        else:
            return (CONNECTION_HANDLE_TYPE_NONE, 0)

    @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='as')
    def GetInterfaces(self):
        """
        Get the optional interfaces implemented by the channel.

        Returns:
        an array of the D-Bus interface names
        """
        return self._interfaces


class ChannelTypeContactSearch(Channel):
    """
    A channel type for searching server-stored user directories. A new channel
    should be requested by a client for each search attempt, and it should be
    closed when the search is completed or the required result has been found
    in order to free unused handles. The search can be cancelled at any time
    by calling the channel Close method, although depending upon the protocol
    the connection manager may not be able to prevent the server from sending
    further results.

    Before searching, the GetSearchKeys method should be used to discover any
    instructions sent by the server, and the valid search keys which can be
    provided to the Search method. A search request is then started by
    providing some of these terms to the Search method, and the search status
    will be set to CHANNEL_CONTACT_SEARCH_STATE_DURING. When results are
    returned by the server, the SearchResultReceived signal is emitted for each
    contact found, and when the search is complete, the search status will be
    set to CHANNEL_SEARCH_STATE_AFTER.
    """
    def __init__(self, connection):
        """
        Initialise the contact search channel.
        """
        Channel.__init__(self, connection, CHANNEL_TYPE_CONTACT_SEARCH)
        self._search_state = CHANNEL_SEARCH_STATE_BEFORE

    @dbus.service.method(CHANNEL_TYPE_CONTACT_SEARCH, in_signature='', out_signature='sa{s(bg)}')
    def GetSearchKeys(self):
        """
        Returns any instructions from the server along with a dictionary of
        search key names to their types, and a boolean indicating if the key is
        mandatory. The following well-known search key names should be used
        where appropriate:
         s:first - the desired contact's given name
         s:last - the desired contact's family name
         s:nick - the desired contact's nickname
         s:email - the e-mail address of the desired contact

        Returns:
        a string with any instructions from the server
        a dictionary mapping string search key names to an array of:
            booleans indicating if the search key is mandatory
            type signature of the value for this search key

        Possible Errors:
        Disconnected, NetworkError, NotAvailable
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_CONTACT_SEARCH, in_signature='a{sv}', out_signature='')
    def Search(self, terms):
        """
        Send a request to start a search for contacts on this connection. A
        valid search request will cause the SearchStateChanged signal to be
        emitted with the status CHANNEL_CONTACT_SEARCH_STATE_DURING.

        Parameters:
        a dictionary mapping search key names to the desired values

        Possible Errors:
        Disconnected, NetworkError, InvalidArgument
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_CONTACT_SEARCH, in_signature='', out_signature='u')
    def GetSearchState(self):
        """
        Returns the current state of this search channel object. One of the
        following values:
        0 - CHANNEL_CONTACT_SEARCH_STATE_BEFORE
            the search has not started
        1 - CHANNEL_CONTACT_SEARCH_STATE_DURING
            the search is in progress
        2 - CHANNEL_CONTACT_SEARCH_STATE_AFTER
            the search has been completed

        Returns:
        an integer representing the search state
        """
        return self._search_state

    @dbus.service.signal(CHANNEL_TYPE_CONTACT_SEARCH, signature='u')
    def SearchStateChanged(self, state):
        """
        Emitted when the search state (as returned by the GetSearchState
        method) changes.

        Parameters:
        state - an integer representing the new search state
        """
        self._search_state = state

    @dbus.service.signal(CHANNEL_TYPE_CONTACT_SEARCH, signature='ua{sv}')
    def SearchResultReceived(self, contact, values):
        """
        Emitted when a search result is received from the server.

        Parameters:
        an integer handle for the contact
        a dictionary mapping search key names to values for this contact
        """
        pass


class ChannelTypeContactList(Channel):
    """
    A channel type for representing a list of people on the server which is
    not used for communication. This is intended for use with the interface
    Channel.Interface.Group for managing buddy lists and privacy lists
    on the server. This channel type has no methods because all of the
    functionality it represents is available via the group interface.

    Singleton instances of this channel type should be created by the
    connection manager at connection time if the list exists on the server, or
    may be requested by using the appropriate handle.  These handles can be
    obtained using RequestHandle with a handle type of
    CONNECTION_HANDLE_TYPE_LIST and one of the following identifiers:
     subscribe - the group of contacts for whom you wish to receive presence
     publish - the group of contacts who may receive your presence
     hide - a group of contacts who are on the publish list but are temporarily disallowed from receiving your presence
     allow - a group of contacts who may send you messages
     deny - a group of contacts who may not send you messages
    """
    _dbus_interfaces = [CHANNEL_TYPE_CONTACT_LIST]

    def __init__(self, connection, handle):
        """
        Initialise the channel.

        Parameters:
        connection - the parent Telepathy Connection object
        """
        Channel.__init__(self, connection, CHANNEL_TYPE_CONTACT_LIST, handle)


class ChannelTypeStreamedMedia(Channel):
    """
    A channel that can send and receive streamed media such as audio or video.
    Provides a number of methods for listing and requesting new streams, and
    signals to indicate when streams have been added, removed and changed
    status.

    In general this should always be used in conjunction with the IceSignalling
    interface to exchange connection candidates and codec choices with
    whichever component is responsible for the streams. However, in certain
    applications where no candidate exchange is necessary (eg the streams are
    handled by specialised hardware which is controlled directly by the
    connection manager), the signalling interface can be omitted and this
    channel type used simply to control the streams.

    This channel type defines two type-specific capability flags (as used in
    Connection.Interface.Capabilities):
      CHANNEL_MEDIA_CAPABILITY_AUDIO = 1
        The handle is capable of using audio streams within a media channel.
      CHANNEL_MEDIA_CAPABILITY_VIDEO = 2
        The handle is capable of using video streams within a media channel.
    """
    def __init__(self, connection, handle):
        """
        Initialise the channel.

        Parameters:
        connection - the parent Telepathy Connection object
        """
        Channel.__init__(self, connection, CHANNEL_TYPE_STREAMED_MEDIA, handle)

    @dbus.service.method(CHANNEL_TYPE_STREAMED_MEDIA, in_signature='',
                                                      out_signature='a(uuuuuu)')
    def ListStreams(self):
        """
        Returns an array of structs representing the streams currently active
        within this channel. Each stream is identified by an unsigned integer
        which is unique for each stream within the channel.

        Stream types are identified by the following values:
          MEDIA_STREAM_TYPE_AUDIO = 0
          MEDIA_STREAM_TYPE_VIDEO = 1

        Stream states are identified by one of the following values:
          MEDIA_STREAM_STATE_DISCONNECTED = 0
            The stream is disconnected.
          MEDIA_STREAM_STATE_CONNECTING = 1
            The stream is trying to connect.
          MEDIA_STREAM_STATE_CONNECTED = 2
            The stream is connected.

        Stream directions are identified by one of the following values:
          MEDIA_STREAM_DIRECTION_NONE = 0
          MEDIA_STREAM_DIRECTION_SEND = 1
          MEDIA_STREAM_DIRECTION_RECEIVE = 2
          MEDIA_STREAM_DIRECTION_BIDIRECTIONAL = 3

        Pending directionality changes are indicated by a bitwise OR of the
        following flags:
          MEDIA_STREAM_PENDING_LOCAL_SEND = 1
            The local user has been asked to send media by the remote user.
            Call RequestStreamDirection to indicate whether or not this is
            acceptable.
          MEDIA_STREAM_PENDING_REMOTE_SEND = 2
            The remote user has been asked to send media by the local user.
            The StreamDirectionChanged signal will be emitted when the remote
            user accepts or rejects this change.

        Returns:
        an array of structs containing:
            the stream identifier
            the contact handle who the stream is with (or 0 if the stream
                represents more than a single member)
            the type of the stream
            the current stream state
            the current direction of the stream
            the current pending send flags
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_STREAMED_MEDIA, in_signature='uau',
                                                      out_signature='a(uuuuuu)')
    def RequestStreams(self, contact_handle, types):
        """
        Request that streams be established to exchange the given types of
        media with the given member. In general this will try and establish a
        bidirectional stream, but on some protocols it may not be possible to
        indicate to the peer that you would like to receive media, so a
        send-only stream will be created initially. In the cases where the
        stream requires remote agreement (eg you wish to receive media from
        them), the StreamDirectionChanged signal will be emitted with the
        MEDIA_STREAM_PENDING_REMOTE_SEND flag set, and the signal emitted again
        with the flag cleared when the remote end has replied.

        Parameters:
        contact_handle - a contact handle with whom to establish the streams
        types - an array of stream types (as defined in ListStreams)

        Returns:
        an array of structs (in the same order as the given stream types)
        containing:
            the stream identifier
            the contact handle who the stream is with (or 0 if the stream
                represents more than a single member)
            the type of the stream
            the current stream state
            the current direction of the stream
            the current pending send flags

        Possible Errors:
        InvalidHandle, InvalidArgument (invalid stream type), NotAvailable (if
        the contact is not able to do this stream type)
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_STREAMED_MEDIA, in_signature='au',
                                                      out_signature='')
    def RemoveStreams(self, streams):
        """
        Request that the given streams are removed.

        Parameters:
        streams - an array of stream identifiers (as defined in ListStreams)

        Possible Errors:
        InvalidArgument (unknown stream identifier)
        """
        pass

    @dbus.service.method(CHANNEL_TYPE_STREAMED_MEDIA, in_signature='uu',
                                                      out_signature='')
    def RequestStreamDirection(self, stream_id, stream_direction):
        """
        Request a change in the direction of an existing stream. In particular,
        this might be useful to stop sending media of a particular type,
        or inform the peer that you are no longer using media that is being
        sent to you.

{'fraction_non_alphanumeric': 0.04320343307817212, 'fraction_numerical': 0.00298654604500116, 'mean_word_length': 2.679611650485437, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4483671', 'n_tokens_mistral': 8226, 'n_tokens_neox': 7915, 'n_words': 3908}