TpProxy subclasses and mixins

## TpProxy subclasses and mixins TpProxy subclasses and mixins — Providing extra functionality for a TpProxy or subclass, or subclassing it |

## Synopsis

    #include <telepathy-glib/proxy-subclass.h>

    DBusGProxy *        tp_proxy_add_interface_by_id        (TpProxy *self,
                                                             GQuark iface);
    void                tp_proxy_add_interfaces             (TpProxy *self,
                                                             const gchar * const *interfaces);
    DBusGProxy *        tp_proxy_borrow_interface_by_id     (TpProxy *self,
                                                             GQuark iface,
                                                             GError **error);
    DBusGProxy *        tp_proxy_get_interface_by_id        (TpProxy *self,
                                                             GQuark iface,
                                                             GError **error);
    void                tp_proxy_invalidate                 (TpProxy *self,
                                                             const GError *error);
    void                (*TpProxyInterfaceAddedCb)          (TpProxy *self,
                                                             guint quark,
                                                             DBusGProxy *proxy,
                                                             gpointer unused);
    void                tp_proxy_or_subclass_hook_on_interface_add
                                                            (GType proxy_or_subclass,
                                                             TpProxyInterfaceAddedCb callback);
    void                tp_proxy_init_known_interfaces      (void);
    void                tp_proxy_subclass_add_error_mapping (GType proxy_subclass,
                                                             const gchar *static_prefix,
                                                             GQuark domain,
                                                             GType code_enum_type);
    gboolean            tp_proxy_dbus_g_proxy_claim_for_signal_adding
                                                            (DBusGProxy *proxy);

    void                (*TpProxyInvokeFunc)                (TpProxy *self,
                                                             GError *error,
                                                             GValueArray *args,
                                                             GCallback callback,
                                                             gpointer user_data,
                                                             GObject *weak_object);
    TpProxyPendingCall * tp_proxy_pending_call_v0_new       (TpProxy *self,
                                                             GQuark iface,
                                                             const gchar *member,
                                                             DBusGProxy *iface_proxy,
                                                             TpProxyInvokeFunc invoke_callback,
                                                             GCallback callback,
                                                             gpointer user_data,
                                                             GDestroyNotify destroy,
                                                             GObject *weak_object,
                                                             gboolean cancel_must_raise);
    void                tp_proxy_pending_call_v0_completed  (gpointer p);
    void                tp_proxy_pending_call_v0_take_pending_call
                                                            (TpProxyPendingCall *pc,
                                                             DBusGProxyCall *pending_call);
    void                tp_proxy_pending_call_v0_take_results
                                                            (TpProxyPendingCall *pc,
                                                             GError *error,
                                                             GValueArray *args);
    TpProxySignalConnection * tp_proxy_signal_connection_v0_new
                                                            (TpProxy *self,
                                                             GQuark iface,
                                                             const gchar *member,
                                                             const GType *expected_types,
                                                             GCallback collect_args,
                                                             TpProxyInvokeFunc invoke_callback,
                                                             GCallback callback,
                                                             gpointer user_data,
                                                             GDestroyNotify destroy,
                                                             GObject *weak_object,
                                                             GError **error);
    void                tp_proxy_signal_connection_v0_take_results
                                                            (TpProxySignalConnection *sc,
                                                             GValueArray *args);

## Description

The implementations of TpProxy subclasses and "mixin" functions need access to the underlying dbus-glib objects used to implement the TpProxy API.

Mixin functions to implement particular D-Bus interfaces should usually be auto-generated, by copying tools/glib-client-gen.py from telepathy-glib.

## Details

### tp_proxy_add_interface_by_id ()

    DBusGProxy *        tp_proxy_add_interface_by_id        (TpProxy *self,
                                                             GQuark iface);

Declare that this proxy supports a given interface.

To use methods and signals of that interface, either call `tp_proxy_get_interface_by_id()` to get the DBusGProxy, or use the tp_cli_* wrapper functions (strongly recommended).

If the interface is the proxy's "main interface", or has already been added, then do nothing.

`self` : | the TpProxy, which must not have become "invalidated".
`iface` : | quark representing the interface to be added
Returns : | either `NULL` or a borrowed DBusGProxy corresponding to `iface`, depending on implementation details. To reliably borrow the DBusGProxy, use `tp_proxy_get_interface_by_id()`. (This method should probably have returned void; sorry.)

Since 0.7.1

### tp_proxy_add_interfaces ()

    void                tp_proxy_add_interfaces             (TpProxy *self,
                                                             const gchar * const *interfaces);

Declare that this proxy supports the given interfaces. Equivalent to calling `g_quark_from_string()` followed by `tp_proxy_add_interface_by_id()` for each of the interface names.

`self` : | the TpProxy, which must not have become "invalidated".
`interfaces` : | the names of the interfaces to be added

Since 0.14.4

### tp_proxy_borrow_interface_by_id ()

    DBusGProxy *        tp_proxy_borrow_interface_by_id     (TpProxy *self,
                                                             GQuark iface,
                                                             GError **error);

### Warning

`tp_proxy_borrow_interface_by_id` is deprecated and should not be used in newly-written code. Since 0.19.9. New code should use `tp_proxy_get_interface_by_id()` instead.

`self` : | the TpProxy
`iface` : | quark representing the interface required
`error` : | used to raise an error in the TP_DBUS_ERRORS domain if `iface` is invalid, `self` has been invalidated or `self` does not implement `iface`
Returns : | a borrowed reference to a DBusGProxy for which the bus name and object path are the same as for `self`, but the interface is as given (or `NULL` if an `error` is raised). The reference is only valid as long as `self` is.

Since 0.7.1

### tp_proxy_get_interface_by_id ()

    DBusGProxy *        tp_proxy_get_interface_by_id        (TpProxy *self,
                                                             GQuark iface,
                                                             GError **error);

`self` : | the TpProxy
`iface` : | quark representing the interface required
`error` : | used to raise an error in the TP_DBUS_ERRORS domain if `iface` is invalid, `self` has been invalidated or `self` does not implement `iface`
Returns : | a borrowed reference to a DBusGProxy for which the bus name and object path are the same as for `self`, but the interface is as given (or `NULL` if an `error` is raised). The reference is only valid as long as `self` is.

Since 0.19.9

### tp_proxy_invalidate ()

    void                tp_proxy_invalidate                 (TpProxy *self,
                                                             const GError *error);

Mark `self` as having been invalidated - no further calls will work, and if not already invalidated, the "invalidated" signal will be emitted with the given error.

`self` : | a proxy
`error` : | an error causing the invalidation

Since 0.7.1

### TpProxyInterfaceAddedCb ()

    void                (*TpProxyInterfaceAddedCb)          (TpProxy *self,
                                                             guint quark,
                                                             DBusGProxy *proxy,
                                                             gpointer unused);

The signature of a "interface-added" signal callback.

`self` : | the proxy
`quark` : | a quark whose string value is the interface being added
`proxy` : | the DBusGProxy for the added interface
`unused` : | unused

Since 0.7.1

### tp_proxy_or_subclass_hook_on_interface_add ()

    void                tp_proxy_or_subclass_hook_on_interface_add
                                                            (GType proxy_or_subclass,
                                                             TpProxyInterfaceAddedCb callback);

Arrange for `callback` to be connected to "interface-added" during the TpProxy constructor. This is done sufficiently early that it will see the signal for the default interface (`interface` member of TpProxyClass), if any, being added. The intended use is for the callback to call `dbus_g_proxy_add_signal()` on the new DBusGProxy.

Since 0.7.6, to ensure correct overriding of interfaces that might be added to telepathy-glib, before calling this function you should call tp_proxy_init_known_interfaces, tp_connection_init_known_interfaces, tp_channel_init_known_interfaces etc. as appropriate for the subclass.

`proxy_or_subclass` : | The GType of TpProxy or a subclass
`callback` : | A signal handler for "interface-added"

Since 0.7.1

### tp_proxy_init_known_interfaces ()

    void                tp_proxy_init_known_interfaces      (void);

Ensure that the known interfaces for TpProxy have been set up. This is done automatically when necessary, but for correct overriding of library interfaces by local extensions, you should call this function before calling `tp_proxy_or_subclass_hook_on_interface_add()`.

Functions like tp_connection_init_known_interfaces and tp_channel_init_known_interfaces do this automatically.

Since 0.7.6

### tp_proxy_subclass_add_error_mapping ()

    void                tp_proxy_subclass_add_error_mapping (GType proxy_subclass,
                                                             const gchar *static_prefix,
                                                             GQuark domain,
                                                             GType code_enum_type);

Register a mapping from D-Bus errors received from the given proxy subclass to GError instances.

When a D-Bus error is received, the TpProxy code checks for error mappings registered for the class of the proxy receiving the error, then for all of its parent classes.

If there is an error mapping for which the D-Bus error name starts with the mapping's `static_prefix`, the proxy will check the corresponding `code_enum_type` for a value whose `value_nick` is the rest of the D-Bus error name (with the leading dot removed). If there isn't such a value, it will continue to try other error mappings.

If a suitable error mapping and code are found, the GError that is raised will have its error domain set to the `domain` from the error mapping, and its error code taken from the enum represented by the `code_enum_type`.

If no suitable error mapping or code is found, the GError will have error domain `TP_DBUS_ERRORS` and error code `TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR`.

`proxy_subclass` : | The GType of a subclass of TpProxy (which must not be TpProxy itself)
`static_prefix` : | A prefix for D-Bus error names, not including the trailing dot (which must remain valid forever, and should usually be in static storage)
`domain` : | A quark representing the corresponding GError domain
`code_enum_type` : | The type of a subclass of GEnumClass

Since 0.7.1

### tp_proxy_dbus_g_proxy_claim_for_signal_adding ()

    gboolean            tp_proxy_dbus_g_proxy_claim_for_signal_adding
                                                            (DBusGProxy *proxy);

Attempt to "claim" a DBusGProxy for addition of signal signatures. If this function has not been called on `proxy` before, `TRUE` is returned, and the caller may safely call `dbus_g_proxy_add_signal()` on `proxy`. If this function has already been caled, `FALSE` is returned, and the caller may not safely call `dbus_g_proxy_add_signal()`.

This is intended for use by auto-generated signal-adding functions, to allow interfaces provided as local extensions to override those in telepathy-glib without causing assertion failures.

`proxy` : | a DBusGProxy
Returns : | `TRUE` if it is safe to call `dbus_g_proxy_add_signal()`

Since 0.7.6

### TpProxyInvokeFunc ()

    void                (*TpProxyInvokeFunc)                (TpProxy *self,
                                                             GError *error,
                                                             GValueArray *args,
                                                             GCallback callback,
                                                             gpointer user_data,
                                                             GObject *weak_object);

Signature of a callback invoked by the TpProxy machinery after a D-Bus method call has succeeded or failed. It is responsible for calling the user-supplied callback.

Because parts of dbus-glib aren't reentrant, this callback may be called from an idle handler shortly after the method call reply is received, rather than from the callback for the reply.

At most one of `args` and `error` can be non-`NULL` (implementations may assert this). `args` and `error` may both be `NULL` if a method with no "out" arguments (i.e. a method that returns nothing) was called successfully.

The TpProxyInvokeFunc must call callback with `user_data`, `weak_object`, and appropriate arguments derived from `error` and `args`. It is responsible for freeing `error` and `args`, if their ownership has not been transferred.

`self` : | the TpProxy on which the D-Bus method was invoked
`error` : | `NULL` if the method call succeeded, or a non-`NULL` error if the method call failed
`args` : | array of "out" arguments (return values) for the D-Bus method, or `NULL` if an error occurred or if there were no "out" arguments
`callback` : | the callback that should be invoked, as passed to `tp_proxy_pending_call_v0_new()`
`user_data` : | user-supplied data to pass to the callback, as passed to `tp_proxy_pending_call_v0_new()`
`weak_object` : | user-supplied object to pass to the callback, as passed to `tp_proxy_pending_call_v0_new()`

Since 0.7.1

### tp_proxy_pending_call_v0_new ()

    TpProxyPendingCall * tp_proxy_pending_call_v0_new       (TpProxy *self,
                                                             GQuark iface,
                                                             const gchar *member,
                                                             DBusGProxy *iface_proxy,
                                                             TpProxyInvokeFunc invoke_callback,
                                                             GCallback callback,
                                                             gpointer user_data,
                                                             GDestroyNotify destroy,
                                                             GObject *weak_object,
                                                             gboolean cancel_must_raise);

Allocate a new pending call structure. After calling this function, the caller must start an asynchronous D-Bus call and give the resulting DBusGProxyCall to the pending call object using `tp_proxy_pending_call_v0_take_pending_call()`.

If dbus-glib gets a reply to the call before it's cancelled, the caller must arrange for `tp_proxy_pending_call_v0_take_results()` to be called with the results (the intention is for this to be done immediately after dbus_g_proxy_end_call in the callback supplied to dbus-glib).

When dbus-glib discards its reference to the user_data supplied in the asynchronous D-Bus call (i.e. after the call is cancelled or a reply arrives), tp_proxy_pending_call_v0_completed must be called (the intention is for the TpProxyPendingCall to be the `user_data` in the async call, and for tp_proxy_pending_call_v0_completed to be the GDestroyNotify passed to the same async call).

This function is for use by TpProxy subclass implementations only, and should usually only be called from code generated by tools/glib-client-gen.py.

`self` : | a proxy
`iface` : | a quark whose string value is the D-Bus interface
`member` : | the name of the method being called
`iface_proxy` : | the interface-specific DBusGProxy for `iface`
`invoke_callback` : | an implementation of TpProxyInvokeFunc which will invoke `callback` with appropriate arguments
`callback` : | a callback to be called when the call completes
`user_data` : | user-supplied data for the callback
`destroy` : | user-supplied destructor for the data
`weak_object` : | if not `NULL`, a GObject which will be weakly referenced by the signal connection - if it is destroyed, the pending call will automatically be cancelled
`cancel_must_raise` : | if `TRUE`, the `invoke_callback` will be run with error `TP_DBUS_ERROR_CANCELLED` if the call is cancelled by a call to `tp_proxy_pending_call_cancel()` or by destruction of the `weak_object`; if `FALSE`, the `invoke_callback` will not be run at all in these cases
Returns : | a new pending call structure

Since 0.7.1

### tp_proxy_pending_call_v0_completed ()

    void                tp_proxy_pending_call_v0_completed  (gpointer p);

Indicate that dbus-glib has finished with this pending call, and therefore either `tp_proxy_pending_call_v0_take_results()` has already been called, or it will never be called. See `tp_proxy_pending_call_v0_new()`.

The signature is chosen to match GDestroyNotify.

This function is for use by TpProxy subclass implementations only, and should usually only be called from code generated by tools/glib-client-gen.py.

`p` : | a TpProxyPendingCall allocated with `tp_proxy_pending_call_v0_new()`

Since 0.7.1

### tp_proxy_pending_call_v0_take_pending_call ()

    void                tp_proxy_pending_call_v0_take_pending_call
                                                            (TpProxyPendingCall *pc,
                                                             DBusGProxyCall *pending_call);

Set the underlying pending call to be used by this object. See also `tp_proxy_pending_call_v0_new()`.

This function is for use by TpProxy subclass implementations only, and should usually only be called from code generated by tools/glib-client-gen.py.

`pc` : | A pending call on which this function has not yet been called
`pending_call` : | The underlying dbus-glib pending call

Since 0.7.1

### tp_proxy_pending_call_v0_take_results ()

    void                tp_proxy_pending_call_v0_take_results
                                                            (TpProxyPendingCall *pc,
                                                             GError *error,
                                                             GValueArray *args);

Set the "out" arguments (return values) from this pending call. See also `tp_proxy_pending_call_v0_new()`.

This function is for use by TpProxy subclass implementations only, and should usually only be called from code generated by tools/glib-client-gen.py.

`pc` : | A pending call on which this function has not yet been called
`error` : | `NULL` if the call was successful, or an error (whose ownership is taken over by the pending call object). Because of dbus-glib idiosyncrasies, this must be the error produced by dbus-glib, not a copy.
`args` : | `NULL` if the call failed or had no "out" arguments, or an array of "out" arguments (whose ownership is taken over by the pending call object)

Since 0.7.1

### tp_proxy_signal_connection_v0_new ()

    TpProxySignalConnection * tp_proxy_signal_connection_v0_new
                                                            (TpProxy *self,
                                                             GQuark iface,
                                                             const gchar *member,
                                                             const GType *expected_types,
                                                             GCallback collect_args,
                                                             TpProxyInvokeFunc invoke_callback,
                                                             GCallback callback,
                                                             gpointer user_data,
                                                             GDestroyNotify destroy,
                                                             GObject *weak_object,
                                                             GError **error);

Allocate a new structure representing a signal connection, and connect to the signal, arranging for `invoke_callback` to be called when it arrives.

This function is for use by TpProxy subclass implementations only, and should usually only be called from code generated by tools/glib-client-gen.py.

`self` : | a proxy
`iface` : | a quark whose string value is the D-Bus interface
`member` : | the name of the signal to which we're connecting
`expected_types` : | an array of expected GTypes for the arguments, terminated by `G_TYPE_INVALID`
`collect_args` : | a callback to be given to `dbus_g_proxy_connect_signal()`, which must marshal the arguments into a GValueArray and use them to call `tp_proxy_signal_connection_v0_take_results()`; this callback is not guaranteed to be called by future versions of telepathy-glib, which might be able to implement its functionality internally. If no arguments are expected at all (expected_types = { G_TYPE_INVALID }) then this callback should instead be `NULL`
`invoke_callback` : | a function which will be called with `error` = `NULL`, which should invoke `callback` with `user_data`, `weak_object` and other appropriate arguments taken from `args`
`callback` : | user callback to be invoked by `invoke_callback`
`user_data` : | user-supplied data for the callback
`destroy` : | user-supplied destructor for the data, which will be called when the signal connection is disconnected for any reason, or will be called before this function returns if an error occurs
`weak_object` : | if not `NULL`, a GObject which will be weakly referenced by the signal connection - if it is destroyed, the signal connection will automatically be disconnected
`error` : | If not `NULL`, used to raise an error if `NULL` is returned
Returns : | a signal connection structure, or `NULL` if the proxy does not have the desired interface or has become invalid

Since 0.7.1

### tp_proxy_signal_connection_v0_take_results ()

    void                tp_proxy_signal_connection_v0_take_results
                                                            (TpProxySignalConnection *sc,
                                                             GValueArray *args);

Feed the results of a signal invocation back into the signal connection machinery.

This method should only be called from TpProxy subclass implementations, in the callback that implements `collect_args`.

`sc` : | The signal connection
`args` : | The arguments of the signal

Since 0.7.1

## See Also

TpProxy