RFC: Operation Options API proposal



Beloved Grilo hackers,

Please find below, and also in pdf format[1] my latest proposal for
operation options.
Please comment and argue, and especially, give your opinion on the
remaining questions at the end.

Cheers,

Guij

[1] http://emont.org/grilo/operation_options-20110323-1.pdf


----8<-------
.. vim:ft=rst

#################################
Extensible Options for Operations
#################################


=================
Problem Statement
=================

We want to have an extensible way to provide options to change the
behaviour of
various operations in Grilo. Such options include the filtering and
sorting of
results. These options would not add state to a media source: they should be
provided when launching an operation, and should affect only this operation.

We also want to have a way for the caller to know in advance to what
extent the
options it wants can be handled by the underlying source.

We are ready to break the API to put in place the new options system,
but the
system should be so that adding new options in the future should be possible
without breaking neither API nor ABI.

This document will focus on API design, and leave implementation issues for
later. We first need to make sure we have an API that fits the programmer's
need, then we will think about how to implement it best (I believe this
will be
quite straightforward, and mostly non-controversial anyway).


============
Proposed API
============

Note that GrlCaps and GrlOperationOptions have some similarities, we
could make
them inherit from a common ancestor (GData comes in mind, or maybe even
GHashTable), though composition might be preferable.

Even though I don't think we need it now, the system can be extended to be
dynamic, by extending capabilities with something like::

  gboolean grl_caps_allow_option_set (GrlCaps *caps,
                                      GrlOperationOptions *options,
                                      const gchar *option_name,
                                      GValue *value);

and by allowing sources to provide their implementation, and calling it in
grl_operation_options_set_value().


Capabilities
------------

The consensus seems to be reached on the necessity of a separate GrlCaps
type,
that would handle the capabilities of a Source.

I would see an API similar to GrlData, but without having GrlCaps being an
object.

::

  /* setters _new()/_free are for sources to use, getters are for
   * applications */

  GrlCaps *grl_caps_new (void);
  void grl_caps_free (GrlCaps *caps);

  /* Using GValue here for consistency with GrlData, but I wonder whether a
   * simple gpointer wouldn't be enough */
  void grl_caps_set_value (GrlCaps *caps, const gchar *name, GValue *value);
  GValue *grl_caps_get_value (GrlCaps *caps, const gchar *name);

  /* nice helpers for the main types */
  void grl_caps_set_string (GrlCaps *caps, const gchar *name, gchar *value);
  gchar *grl_caps_get_string (GrlCaps *caps, const gchar *name);

  void grl_caps_set_boolean (GrlCaps *caps, const gchar *name, gboolean
value);
  gboolean grl_caps_get_boolean (GrlCaps *caps, const gchar *name);

  void grl_caps_set_int (GrlCaps *caps, const gchar *name, gint value);
  gint grl_caps_get_int (GrlCaps *caps, const gchar *name);

  void grl_caps_set_float (GrlCaps *caps, const gchar *name, gfloat value);
  gfloat grl_caps_get_float (GrlCaps *caps, const gchar *name);

  /* nice wrappers like: */
  void grl_caps_set_frobuz (GrlCaps *caps, GrlFrobuz *frobuz);
  GrlFrobuz *grl_caps_get_frobuz (GrlCaps *caps);

  /* wrappers we already want */

  /* whether source supports pagination (skip & count)
  void grl_caps_set_pagination (GrlCaps *caps, gboolean pagination);
  gboolean grl_caps_get_pagination (GrlCaps *caps);
  /* flags the source can honour. Only GRL_RESOLVE_FAST_ONLY makes
sense, since
   * the other flags are entirely handled by core */
  void grl_caps_set_flags (GrlCaps *caps, GrlMetadataResolutionFlags flags);
  GrlMetadataResolutionFlags grl_caps_get_falgs (GrlCaps *caps);


Operation Options
-----------------


::

  /* new/free and setters is for programs, getters are for sources.
   */

  GrlOperationOptions *grl_operation_options_new (GrlCaps *caps);
  void grl_operation_options_free (GrlOperationOptions *options);

  /* Return TRUE if options could be set, FALSE if that was not allowed
by caps
   */
  gboolean grl_operation_options_set_value (GrlOperationOptions *options,
                                            const gchar *name,
                                            GValue *value);
  GValue grl_operation_options_get_value (GrlOperationOptions *options,
                                          const gchar *name);

  /* nice helpers for the main types */
  gboolean grl_operation_options_set_string (GrlOperationOptions *options,
                                             const gchar *name,
                                             gchar *value);
  gchar *grl_operation_options_get_string (GrlOperationOptions *options,
                                           const gchar *name);

  gboolean grl_operation_options_set_boolean (GrlOperationOptions *options,
                                              const gchar *name,
                                              gboolean value);
  gboolean grl_operation_options_get_boolean (GrlOperationOptions *options,
                                              const gchar *name);

  gboolean grl_operation_options_set_int (GrlOperationOptions *options,
                                          const gchar *name,
                                          gint value);
  gint grl_operation_options_get_int (GrlOperationOptions *options,
                                      const gchar *name);

  gboolean grl_operation_options_set_float (GrlOperationOptions *options,
                                            const gchar *name,
                                            gfloat value);
  gfloat grl_operation_options_get_float (GrlOperationOptions *options,
                                          const gchar *name);

  /* nice wrappers like: */
  gboolean grl_operation_options_set_frobuz (GrlOperationOptions *options,
                                             GrlFrobuz *frobuz);
  GrlFrobuz *grl_operation_options_get_frobuz (GrlOperationOptions
*options);

  /* wrappers we already want */

  /* Note that count is signed, so that it can cleanly be set to -1 to
mean "no
   * limit" */
  gboolean grl_operation_options_set_pagination (GrlOperationOptions
*options,
                                                 guint skip, gint count);
  void grl_operation_options_get_pagination (GrlOperationOptions *options,
                                             guint *skip, gint *count);

  void grl_operation_options_set_flags (GrlOperationOptions *options,
                                        GrlMetadataResolutionFlags flags);
  GrlMetadataResolutionFlags
  grl_operation_options_get_falgs (GrlOperationOptions *options);

:Comments: We might want reference counting on GrlOperationOptions, so that
           the application can choose between dropping its reference
           immediately (and not have to free the options when the
operation has
           terminated) or keep it to use the same GrlOperationOptions
           instance for several operations.


====================
Existing API changes
====================


API modifications for media source
----------------------------------

Caps::

  GrlCaps *grl_media_source_get_caps (GrlMediaSource *source,
                                      GrlSupportedOps operation);

Use::

  guint grl_media_source_browse (GrlMediaSource *source,
                                 GrlMedia *container,
                                 const GList *keys,
                                 GrlOperationOptions *options,
                                 GrlMediaSourceResultCb callback,
                                 gpointer user_data);

  /* And the same thing for the other operations. */

First idea to help the user adjust their options to what the source
supports::

  gboolean
  grl_media_source_supported_options (GrlMediaSource *source,
                                      GrlSupportedOps operation,
                                      GrlOperationOptions *options,
                                      GrlOperationOptions
**effective_options);

Alternative idea, similar to GstCaps in gstreamer, simpler to implement for
plugins, slightly less flexible::

  GrlOperationOptions *
  grl_media_source_supported_options (GrlMediaSource *source,
                                      GrlSupportedOps operation);

  GrlOperationOptions *
  grl_operation_options_intersect (GrlOperationOptions *options1,
                                   GrlOperationOptions *options2);


===================
Remaining Questions
===================

Supposing we all agree on the above (I doubt we will without at least some
slight modifications), some questions are still to be answered:

 - Should we use options for metadata as well, or wait until we rework
the class hierarchy?
 - Should we have an externally visible common ancestor to
GrlOperationOptions
   and GrlCaps? (one that would implement the generic setters and getters)
 - Should we use GValue or gpointer?

Please tell me if there are other aspects that I forgot.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]