'General processing of a clip.
Returns a new Clip whose frames are a transformation
(through function ``fun``) of the frames of the current clip.
Parameters
fun
A function with signature (gf,t -> frame) where ``gf`` will
represent the current clip\'s ``get_frame`` method,
i.e. ``gf`` is a function (t->image). Parameter `t` is a time
in seconds, `frame` is a picture (=Numpy array) which will be
returned by the transformed clip (see examples below).
apply_to
Can be either ``\'mask\'``, or ``\'audio\'``, or
``[\'mask\',\'audio\']``.
Specifies if the filter ``fl`` should also be applied to the
audio or the mask of the clip, if any.
keep_duration
Set to True if the transformation does not change the
``duration`` of the clip.
Examples
In the following ``newclip`` a 100 pixels-high clip whose video
content scrolls from the top to the bottom of the frames of
``clip``.
>>> fl = lambda gf,t : gf(t)[int(t):int(t)+50, :]
>>> newclip = clip.fl(fl, apply_to=\'mask\')'

def fl(self, fun, apply_to=None, keep_duration=True):

    if (apply_to is None):
        apply_to = []
    newclip = self.set_make_frame((lambda t: fun(self.get_frame, t)))
    if (not keep_duration):
        newclip.duration = None
        newclip.end = None
    if isinstance(apply_to, str):
        apply_to = [apply_to]
    for attr in apply_to:
        if hasattr(newclip, attr):
            a = getattr(newclip, attr)
            if (a is not None):
                new_a = a.fl(fun, keep_duration=keep_duration)
                setattr(newclip, attr, new_a)
    return newclip
