[vlc-devel] [PATCH v2] ios: uiview: add new vout_window module

Alexandre Janniaux ajanni at videolabs.io
Fri Nov 6 17:46:26 CET 2020


err, + extra fixes.

On Fri, Nov 06, 2020 at 05:16:24PM +0100, Alexandre Janniaux wrote:
> Hi,
>
> Indeed, here is the diff taking your request into account.
> I kept the arbitrary value for the initWithFrame() call, in
> the hope to remove them for a cleaner approach in the Enable()
> call instead maybe.
>
> Regards,
> --
> Alexandre Janniaux
> Videolabs
>
> diff --git a/modules/video_output/apple/VLCVideoUIView.m b/modules/video_output/apple/VLCVideoUIView.m
> index c738bf955c..c84bcb1205 100644
> --- a/modules/video_output/apple/VLCVideoUIView.m
> +++ b/modules/video_output/apple/VLCVideoUIView.m
> @@ -1,5 +1,5 @@
>  /*****************************************************************************
> - * uiview.m: iOS UIView vout window provider
> + * VLCVideoUIView.m: iOS UIView vout window provider
>   *****************************************************************************
>   * Copyright (C) 2001-2017 VLC authors and VideoLAN
>   * Copyright (C) 2020 Videolabs
> @@ -28,10 +28,10 @@
>   *****************************************************************************/
>
>  /**
> - * @file uiview.m
> - * @brief UIView implementation as a vout_window provider
> + * @file VLCVideoUIView.m
> + * @brief UIView-based vout_window_t provider
>   *
> - * This UIView window provider mostly handle resizing constraints from upper
> + * This UIView window provider mostly handles resizing constraints from parent
>   * views and provides event forwarding to VLC. It is usable for any kind of
>   * subview and in particular can be used to implement a CAEAGLLayer in a
>   * vlc_gl_t provider as well as a CAMetalLayer, or other CALayer based video
> @@ -84,8 +84,7 @@
>      int _subviews;
>  }
>
> -+ (void)getNewView:(struct vout_window_t*)wnd;
> -- (id)initWithFrame:(CGRect)frame;
> +- (id)initWithWindow:(vout_window_t *)wnd;
>  - (BOOL)fetchViewContainer;
>  - (void)detachFromParent;
>  - (void)tapRecognized:(UITapGestureRecognizer *)tapRecognizer;
> @@ -98,22 +97,13 @@
>   *****************************************************************************/
>  @implementation VLCVideoUIView
>
> -+ (void)getNewView:(struct vout_window_t*)wnd
> -{
> -    VLCVideoUIView *uiview = [self alloc];
> -    if (uiview == nil)
> -        return;
> -
> -    uiview->_wnd = wnd;
> -    uiview->_wnd->sys = (__bridge_retained void*)[uiview initWithFrame:CGRectMake(0.,0.,320.,240.)];
> -}
> -
> -- (id)initWithFrame:(CGRect)frame
> +- (id)initWithWindow:(vout_window_t *)wnd
>  {
> +    _wnd = wnd;
>      _enabled = NO;
>      _subviews = 0;
>
> -    self = [super initWithFrame:frame];
> +    self = [super initWithFrame:CGRectMake(0., 0., 320., 240.)];
>      if (!self)
>          return nil;
>
> @@ -244,7 +234,6 @@
>      assert(_subviews == 0);
>      [self removeFromSuperview];
>
> -    [[NSNotificationCenter defaultCenter] removeObserver:self];
>      [_tapRecognizer.view removeGestureRecognizer:_tapRecognizer];
>  }
>
> @@ -306,11 +295,17 @@ end:
>
>  /* Subview are expected to fill the whole frame so tell the compositor
>   * that it doesn't have to bother with what's behind the window. */
> -- (BOOL)isOpaque { return YES; }
> +- (BOOL)isOpaque
> +{
> +    return YES;
> +}
>
>  /* Prevent the subviews (which are renderers only) to get events so that
>   * they can be dispatched from this vout_window module. */
> -- (BOOL)acceptsFirstResponder { return YES; }
> +- (BOOL)acceptsFirstResponder
> +{
> +    return YES;
> +}
>  @end
>
>  /**
> @@ -356,15 +351,13 @@ static const struct vout_window_operations window_ops =
>
>  static int Open(vout_window_t *wnd)
>  {
> -    wnd->sys = NULL;
> -
>      dispatch_sync(dispatch_get_main_queue(), ^{
> -        [VLCVideoUIView getNewView:wnd];
> +        wnd->sys = [[VLCVideoUIView alloc] initWithWindow:wnd];
>      });
>
>      if (wnd->sys == NULL)
>      {
> -        msg_Err(wnd, "Creating OpenGL ES 2 view failed");
> +        msg_Err(wnd, "Creating UIView window provider failed");
>          goto error;
>      }
>
>
>
> On Fri, Nov 06, 2020 at 01:57:57PM +0100, Felix Paul Kühne wrote:
> > Hello Alexandre,
> >
> > > Am 05.11.2020 um 18:39 schrieb Alexandre Janniaux <ajanni at videolabs.io>:
> > >
> > > Refactor code from the ios vout display to create a dedicated UIView
> > > which handle the touch events and window resizing.
> > >
> > > The resizing events are emitted after any children UIView layer is added
> > > to the UIView vout window so that it doesn't block the main thread under
> > > display lock while the display module is being created. Indeed, it would
> > > result in a lock inversion and thus potential deadlocks.
> > > ---
> > > modules/video_output/Makefile.am    |  15 +-
> > > modules/video_output/apple/uiview.m | 389 ++++++++++++++++++++++++++++
> > > modules/video_output/ios.m          |  66 ++---
> > > 3 files changed, 420 insertions(+), 50 deletions(-)
> > > create mode 100644 modules/video_output/apple/uiview.m
> > >
> > > diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
> > > index c42fdc474a..e6edf9327d 100644
> > > --- a/modules/video_output/Makefile.am
> > > +++ b/modules/video_output/Makefile.am
> > > @@ -52,11 +52,22 @@ libvout_ios_plugin_la_CFLAGS = $(AM_CFLAGS) $(OPENGL_COMMONCFLAGS) -DUSE_OPENGL_
> > > libvout_ios_plugin_la_LIBADD = libvlc_opengles.la
> > > libvout_ios_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' \
> > > 	-Wl,-framework,Foundation,-framework,OpenGLES,-framework,QuartzCore,-framework,UIKit
> > > +
> > > +libuiview_window_plugin_la_SOURCES = video_output/apple/uiview.m
> > > +libuiview_window_plugin_la_LDFLAGS = $(AM_LDFLAGS) \
> > > +	-Wl,-framework,Foundation,-framework,OpenGLES,-framework,QuartzCore,-framework,UIKit
> > > +libuiview_window_plugin_la_OBJCFLAGS = $(AM_OBJCFLAGS) -fobjc-arc
> > > +
> > > if HAVE_IOS
> > > -vout_LTLIBRARIES += libvout_ios_plugin.la libglinterop_cvpx_plugin.la
> > > +vout_LTLIBRARIES += libvout_ios_plugin.la \
> > > +	libglinterop_cvpx_plugin.la \
> > > +	libuiview_window_plugin.la
> > > endif
> > > if HAVE_TVOS
> > > -vout_LTLIBRARIES += libvout_ios_plugin.la libglinterop_cvpx_plugin.la
> > > +vout_LTLIBRARIES += \
> > > +	libvout_ios_plugin.la \
> > > +	libglinterop_cvpx_plugin.la \
> > > +	libuiview_window_plugin.la
> > > endif
> > >
> > > libglinterop_vaapi_plugin_la_SOURCES = video_output/opengl/interop_vaapi.c \
> > > diff --git a/modules/video_output/apple/uiview.m b/modules/video_output/apple/uiview.m
> > > new file mode 100644
> > > index 0000000000..5d8374d0af
> > > --- /dev/null
> > > +++ b/modules/video_output/apple/uiview.m
> >
> > The filename should match the class name (by convention).m
> >
> > > @@ -0,0 +1,389 @@
> > > +/*****************************************************************************
> > > + * uiview.m: iOS UIView vout window provider
> > > + *****************************************************************************
> > > + * Copyright (C) 2001-2017 VLC authors and VideoLAN
> > > + * Copyright (C) 2020 Videolabs
> > > + *
> > > + * Authors: Pierre d'Herbemont <pdherbemont at videolan dot org>
> > > + *          Felix Paul Kühne <fkuehne at videolan dot org>
> > > + *          David Fuhrmann <david dot fuhrmann at googlemail dot com>
> > > + *          Rémi Denis-Courmont
> > > + *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
> > > + *          Eric Petit <titer at m0k.org>
> > > + *          Alexandre Janniaux <ajanni at videolabs.io>
> > > + *
> > > + * This program 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 program 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 Lesser General Public License for more details.
> > > + *
> > > + * You should have received a copy of the GNU Lesser General Public License
> > > + * along with this program; if not, write to the Free Software Foundation,
> > > + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
> > > + *****************************************************************************/
> > > +
> > > +/**
> > > + * @file uiview.m
> > > + * @brief UIView implementation as a vout_window provider
> >
> > This is not an implementation but a sub-class.
> >
> > > + *
> > > + * This UIView window provider mostly handle resizing constraints from upper
> >
> > s/handle/handles
> > s/upper/parent ?
> >
> > > + * views and provides event forwarding to VLC. It is usable for any kind of
> > > + * subview and in particular can be used to implement a CAEAGLLayer in a
> > > + * vlc_gl_t provider as well as a CAMetalLayer, or other CALayer based video
> > > + * output in general.
> > > + *
> > > + * In particular, UI event will be forwarded to the core without the display
> > > + * lock thanks to this implementation, but vout display implementation will
> > > + * need to let the event pass through to this UIView.
> > > + *
> > > + * Note that this module is asynchronous with the usual VLC execution flow:
> > > + * except during Open(), where a status code is needed and synchronization
> > > + * must be done with the main thread, everything is forwarded to and
> > > + * asynchronously executed by the main thread. In particular, the closing
> > > + * of this module must be done asynchronously to not require the main thread
> > > + * to run, and the hosting application will need to drain the main thread
> > > + * dispatch queue. For iOS, it basically means nothing more than running the
> > > + * usual UIApplicationMain.
> > > + */
> > > +
> > > +#import <UIKit/UIKit.h>
> > > +#import <OpenGLES/EAGL.h>
> > > +#import <OpenGLES/ES2/gl.h>
> > > +#import <OpenGLES/ES2/glext.h>
> > > +#import <QuartzCore/QuartzCore.h>
> > > +#import <dlfcn.h>
> > > +
> > > +#ifdef HAVE_CONFIG_H
> > > +# import "config.h"
> > > +#endif
> > > +
> > > +#import <vlc_common.h>
> > > +#import <vlc_plugin.h>
> > > +#import <vlc_dialog.h>
> > > +#import <vlc_mouse.h>
> > > +#import <vlc_vout_window.h>
> > > +
> > > + at interface VLCVideoUIView : UIView {
> > > +    /* VLC window object, set to NULL under _mutex lock when closing. */
> > > +    vout_window_t *_wnd;
> > > +    vlc_mutex_t _mutex;
> > > +
> > > +    /* Parent view defined by libvlc_media_player_set_nsobject. */
> > > +    UIView *_viewContainer;
> > > +
> > > +    /* Window observer for mouse-like events. */
> > > +    UITapGestureRecognizer *_tapRecognizer;
> > > +
> > > +    /* Window state */
> > > +    BOOL _enabled;
> > > +    int _subviews;
> > > +}
> > > +
> > > ++ (void)getNewView:(struct vout_window_t*)wnd;
> > > +- (id)initWithFrame:(CGRect)frame;
> > > +- (BOOL)fetchViewContainer;
> > > +- (void)detachFromParent;
> > > +- (void)tapRecognized:(UITapGestureRecognizer *)tapRecognizer;
> > > +- (void)enable;
> > > +- (void)disable;
> > > + at end
> > > +
> > > +/*****************************************************************************
> > > + * Our UIView object
> > > + *****************************************************************************/
> > > + at implementation VLCVideoUIView
> > > +
> > > ++ (void)getNewView:(struct vout_window_t*)wnd
> > > +{
> > > +    VLCVideoUIView *uiview = [self alloc];
> > > +    if (uiview == nil)
> > > +        return;
> > > +
> > > +    uiview->_wnd = wnd;
> > > +    uiview->_wnd->sys = (__bridge_retained void*)[uiview initWithFrame:CGRectMake(0.,0.,320.,240.)];
> > > +}
> > > +
> > > +- (id)initWithFrame:(CGRect)frame
> > > +{
> > > +    _enabled = NO;
> > > +    _subviews = 0;
> > > +
> > > +    self = [super initWithFrame:frame];
> > > +    if (!self)
> > > +        return nil;
> > > +
> > > +    vlc_mutex_init(&_mutex);
> > > +
> > > +    /* The window is controlled by the host application through the UIView
> > > +     * sizing mechanisms. */
> > > +    self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
> > > +
> > > +    if (![self fetchViewContainer])
> > > +        return nil;
> > > +
> > > +    /* add tap gesture recognizer for DVD menus and stuff */
> > > +    _tapRecognizer = [[UITapGestureRecognizer alloc]
> > > +        initWithTarget:self action:@selector(tapRecognized:)];
> > > +
> > > +    return self;
> > > +}
> > > +
> > > +- (BOOL)fetchViewContainer
> > > +{
> > > +    @try {
> > > +        /* get the object we will draw into */
> > > +        UIView *viewContainer = (__bridge UIView*)var_InheritAddress (_wnd, "drawable-nsobject");
> > > +        if (unlikely(viewContainer == nil)) {
> > > +            msg_Err(_wnd, "provided view container is nil");
> > > +            return NO;
> > > +        }
> > > +
> > > +        if (unlikely(![viewContainer respondsToSelector:@selector(isKindOfClass:)])) {
> > > +            msg_Err(_wnd, "void pointer not an ObjC object");
> > > +            return NO;
> > > +        }
> > > +
> > > +        if (![viewContainer isKindOfClass:[UIView class]]) {
> > > +            msg_Err(_wnd, "passed ObjC object not of class UIView");
> > > +            return NO;
> > > +        }
> > > +
> > > +        /* We need to store the view container because we'll add our view
> > > +         * only when a subview (hopefully able to handle the rendering) will
> > > +         * get created. The main reason for this is that we cannot report
> > > +         * events from the window until the display is opened, otherwise a
> > > +         * race condition involving locking both the main thread and the lock
> > > +         * in the core for the display are happening. */
> > > +        _viewContainer = viewContainer;
> > > +
> > > +        self.frame = viewContainer.bounds;
> > > +        [self reshape];
> > > +
> > > +        return YES;
> > > +    } @catch (NSException *exception) {
> > > +        msg_Err(_wnd, "Handling the view container failed due to an Obj-C exception (%s, %s", [exception.name UTF8String], [exception.reason UTF8String]);
> > > +        return NO;
> > > +    }
> > > +}
> > > +
> > > +- (void)detachFromParent
> > > +{
> > > +    /* We need to lock because we consider that _wnd might be destroyed
> > > +     * after this function returns, typically as it will be called in the
> > > +     * Close() operation which preceed the vout_window_t destruction in
> > > +     * the core. */
> > > +    vlc_mutex_lock(&_mutex);
> > > +    _wnd = NULL;
> > > +    vlc_mutex_unlock(&_mutex);
> > > +}
> > > +
> > > +/**
> > > + * We track whether we currently have a child view, which will be able
> > > + * to do the actual rendering. Depending on how many children view we had
> > > + * and whether we are in enabled state or not, we add or remove the view
> > > + * from/to the parent UIView.
> > > + * This is needed because we cannot emit resize event from the main
> > > + * thread as long as the display is not created, since the display will
> > > + * need the main thread too. It would non-deterministically deadlock
> > > + * otherwise.
> > > + */
> > > +
> > > +- (void)didAddSubview:(UIView*)subview
> > > +{
> > > +    assert(_enabled);
> > > +    _subviews++;
> > > +    if (_subviews == 1)
> > > +        [_viewContainer addSubview:self];
> > > +
> > > +    VLC_UNUSED(subview);
> > > +}
> > > +
> > > +- (void)willRemoveSubview:(UIView*)subview
> > > +{
> > > +    _subviews--;
> > > +    if (_enabled && _subviews == 0)
> > > +        [self removeFromSuperview];
> > > +
> > > +    VLC_UNUSED(subview);
> > > +}
> > > +
> > > +/**
> > > + * Vout window operations implemention, which are expected to be run on
> > > + * the main thread only. Core C wrappers below must typically use
> > > + * dispatch_async with dispatch_get_main_queue() to call them.
> > > + *
> > > + * The addition of the UIView to the parent UIView might happen later
> > > + * if there's no subview attached yet.
> > > + */
> > > +
> > > +- (void)enable
> > > +{
> > > +    if (_enabled)
> > > +        return;
> > > +
> > > +    assert(_subviews == 0);
> > > +    _enabled = YES;
> > > +
> > > +    /* Bind tapRecognizer. */
> > > +    [self addGestureRecognizer:_tapRecognizer];
> > > +    _tapRecognizer.cancelsTouchesInView = NO;
> > > +}
> > > +
> > > +- (void)disable
> > > +{
> > > +    if (!_enabled)
> > > +        return;
> > > +
> > > +    _enabled = NO;
> > > +    assert(_subviews == 0);
> > > +    [self removeFromSuperview];
> > > +
> > > +    [[NSNotificationCenter defaultCenter] removeObserver:self];
> >
> > This appears to be a NO-OP as you never seem to register the observer.
> >
> > > +    [_tapRecognizer.view removeGestureRecognizer:_tapRecognizer];
> > > +}
> > > +
> > > +/**
> > > + * Window state tracking and reporting
> > > + */
> > > +
> > > +- (void)didMoveToWindow
> > > +{
> > > +    self.contentScaleFactor = self.window.screen.scale;
> > > +}
> > > +
> > > +- (void)layoutSubviews
> > > +{
> > > +    [self reshape];
> > > +}
> > > +
> > > +- (void)reshape
> > > +{
> > > +    assert([NSThread isMainThread]);
> > > +
> > > +    CGSize viewSize = [self bounds].size;
> > > +    CGFloat scaleFactor = self.contentScaleFactor;
> > > +
> > > +    /* We need to lock to ensure _wnd is still valid, see detachFromParent. */
> > > +    vlc_mutex_lock(&_mutex);
> > > +    if (_wnd == NULL)
> > > +        goto end;
> > > +    vout_window_ReportSize(_wnd,
> > > +            viewSize.width * scaleFactor,
> > > +            viewSize.height * scaleFactor);
> > > +end:
> > > +    vlc_mutex_unlock(&_mutex);
> > > +}
> > > +
> > > +- (void)tapRecognized:(UITapGestureRecognizer *)tapRecognizer
> > > +{
> > > +    UIGestureRecognizerState state = [tapRecognizer state];
> > > +    CGPoint touchPoint = [tapRecognizer locationInView:self];
> > > +    CGFloat scaleFactor = self.contentScaleFactor;
> > > +
> > > +    /* We need to lock to ensure _wnd is still valid, see detachFromParent. */
> > > +    vlc_mutex_lock(&_mutex);
> > > +    if (_wnd == NULL)
> > > +        goto end;
> > > +    vout_window_ReportMouseMoved(_wnd,
> > > +            (int)touchPoint.x * scaleFactor, (int)touchPoint.y * scaleFactor);
> > > +    vout_window_ReportMousePressed(_wnd, MOUSE_BUTTON_LEFT);
> > > +    vout_window_ReportMouseReleased(_wnd, MOUSE_BUTTON_LEFT);
> > > +end:
> > > +    vlc_mutex_unlock(&_mutex);
> > > +}
> > > +
> > > +- (void)updateConstraints
> > > +{
> > > +    [super updateConstraints];
> > > +    [self reshape];
> > > +}
> > > +
> > > +/* Subview are expected to fill the whole frame so tell the compositor
> > > + * that it doesn't have to bother with what's behind the window. */
> > > +- (BOOL)isOpaque { return YES; }
> >
> > Please consider wasting more lines for this.
> >
> > > +
> > > +/* Prevent the subviews (which are renderers only) to get events so that
> > > + * they can be dispatched from this vout_window module. */
> > > +- (BOOL)acceptsFirstResponder { return YES; }
> >
> > idem.
> > > + at end
> > > +
> > > +/**
> > > + * C core wrapper of the vout window operations for the ObjC module.
> > > + */
> > > +
> > > +static int Enable(vout_window_t *wnd, const vout_window_cfg_t *cfg)
> > > +{
> > > +    VLCVideoUIView *sys = (__bridge VLCVideoUIView *)wnd->sys;
> > > +    dispatch_async(dispatch_get_main_queue(), ^{
> > > +        [sys enable];
> > > +    });
> > > +    return VLC_SUCCESS;
> > > +}
> > > +
> > > +static void Disable(vout_window_t *wnd)
> > > +{
> > > +    VLCVideoUIView *sys = (__bridge VLCVideoUIView *)wnd->sys;
> > > +    dispatch_async(dispatch_get_main_queue(), ^{
> > > +        [sys disable];
> > > +    });
> > > +}
> > > +
> > > +static void Close(vout_window_t *wnd)
> > > +{
> > > +    VLCVideoUIView *sys = (__bridge_transfer VLCVideoUIView*)wnd->sys;
> > > +
> > > +    /* The UIView must not be attached before releasing. Disable() is doing
> > > +     * exactly this in asynchronously the main thread so call it here. */
> > > +    Disable(wnd);
> > > +
> > > +    /* We need to signal the asynchronous implementation that we have been
> > > +     * closed and cannot used _wnd anymore. */
> > > +    [sys detachFromParent];
> > > +}
> > > +
> > > +static const struct vout_window_operations window_ops =
> > > +{
> > > +    .enable = Enable,
> > > +    .disable = Disable,
> > > +    .destroy = Close,
> > > +};
> > > +
> > > +static int Open(vout_window_t *wnd)
> > > +{
> > > +    wnd->sys = NULL;
> > > +
> > > +    dispatch_sync(dispatch_get_main_queue(), ^{
> > > +        [VLCVideoUIView getNewView:wnd];
> >
> > Who and where is this instance stored? using initializers or class functions without storing the result is discouraged as misuse or flow-control breakage is likely.
> >
> > > +    });
> > > +
> > > +    if (wnd->sys == NULL)
> > > +    {
> > > +        msg_Err(wnd, "Creating OpenGL ES 2 view failed");
> > > +        goto error;
> > > +    }
> > > +
> > > +    wnd->type = VOUT_WINDOW_TYPE_NSOBJECT;
> > > +    wnd->handle.nsobject = wnd->sys;
> > > +    wnd->ops = &window_ops;
> > > +
> > > +    return VLC_SUCCESS;
> > > +
> > > +error:
> > > +    return VLC_EGENERIC;
> > > +}
> > > +
> > > +vlc_module_begin ()
> > > +    set_shortname("UIView")
> > > +    set_description("iOS UIView vout window provider")
> > > +    set_category(CAT_VIDEO)
> > > +    set_subcategory(SUBCAT_VIDEO_VOUT)
> > > +    set_capability("vout window", 300)
> > > +    set_callback(Open)
> > > +
> > > +    add_shortcut("uiview", "ios")
> > > +vlc_module_end ()
> > > diff --git a/modules/video_output/ios.m b/modules/video_output/ios.m
> > > index 07c8355d45..d00bbcd3a5 100644
> > > --- a/modules/video_output/ios.m
> > > +++ b/modules/video_output/ios.m
> > > @@ -98,7 +98,6 @@ vlc_module_end ()
> > >     BOOL _placeInvalidated;
> > >
> > >     UIView *_viewContainer;
> > > -    UITapGestureRecognizer *_tapRecognizer;
> > >
> > >     /* Written from MT, read locked from vout */
> > >     vout_display_place_t _place;
> > > @@ -109,7 +108,7 @@ vlc_module_end ()
> > >     vout_display_cfg_t _cfg;
> > > }
> > >
> > > -- (id)initWithFrame:(CGRect)frame andVD:(vout_display_t*)vd;
> > > +- (id)initWithFrame:(CGRect)frame andVD:(vout_display_t*)vd window:(vout_window_t*)wnd;
> > > - (void)cleanAndRelease:(BOOL)flushed;
> > > - (BOOL)makeCurrent:(EAGLContext **)previousEaglContext withGL:(vlc_gl_t *)gl;
> > > - (void)releaseCurrent:(EAGLContext *)previousEaglContext;
> > > @@ -158,7 +157,8 @@ static const struct vlc_display_operations ops = {
> > > static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
> > >                 video_format_t *fmt, vlc_video_context *context)
> > > {
> > > -    if (vout_display_cfg_IsWindowed(cfg))
> > > +    vout_window_t *wnd = cfg->window;
> > > +    if (wnd->type != VOUT_WINDOW_TYPE_NSOBJECT)
> > >         return VLC_EGENERIC;
> > >
> > >     vout_display_sys_t *sys = vlc_obj_calloc(VLC_OBJECT(vd), 1, sizeof(*sys));
> > > @@ -176,8 +176,8 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
> > >
> > >         [VLCOpenGLES2VideoView performSelectorOnMainThread:@selector(getNewView:)
> > >                                                 withObject:[NSArray arrayWithObjects:
> > > -                                                           [NSValue valueWithPointer:&sys->glESView],
> > > -                                                           [NSValue valueWithPointer:vd], nil]
> > > +                                                           [NSValue valueWithPointer:vd],
> > > +                                                           [NSValue valueWithPointer:wnd], nil]
> > >                                              waitUntilDone:YES];
> > >         if (!sys->glESView) {
> > >             msg_Err(vd, "Creating OpenGL ES 2 view failed");
> > > @@ -353,12 +353,14 @@ static void GLESSwap(vlc_gl_t *gl)
> > >
> > > + (void)getNewView:(NSArray *)value
> > > {
> > > -    id *ret = [[value objectAtIndex:0] pointerValue];
> > > -    vout_display_t *vd = [[value objectAtIndex:1] pointerValue];
> > > -    *ret = [[self alloc] initWithFrame:CGRectMake(0.,0.,320.,240.) andVD:vd];
> > > +    vout_display_t *vd = [[value objectAtIndex:0] pointerValue];
> > > +    vout_window_t *wnd = [[value objectAtIndex:1] pointerValue];
> > > +
> > > +    struct vout_display_sys_t *sys = vd->sys;
> > > +    sys->glESView = [[self alloc] initWithFrame:CGRectMake(0.,0.,320.,240.) andVD:vd window:wnd];
> > > }
> > >
> > > -- (id)initWithFrame:(CGRect)frame andVD:(vout_display_t*)vd
> > > +- (id)initWithFrame:(CGRect)frame andVD:(vout_display_t*)vd window:(vout_window_t*)wnd
> > > {
> > >     _appActive = ([UIApplication sharedApplication].applicationState == UIApplicationStateActive);
> > >     if (unlikely(!_appActive))
> > > @@ -403,7 +405,7 @@ static void GLESSwap(vlc_gl_t *gl)
> > >
> > >     self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
> > >
> > > -    if (![self fetchViewContainer])
> > > +    if (![self bindToWindow: wnd])
> > >     {
> > >         [_eaglContext release];
> > >         [self release];
> > > @@ -431,11 +433,11 @@ static void GLESSwap(vlc_gl_t *gl)
> > >     return self;
> > > }
> > >
> > > -- (BOOL)fetchViewContainer
> > > +- (BOOL)bindToWindow:(vout_window_t*)wnd
> > > {
> > >     @try {
> > > +        UIView *viewContainer = wnd->handle.nsobject;
> > >         /* get the object we will draw into */
> > > -        UIView *viewContainer = var_InheritAddress (_voutDisplay, "drawable-nsobject");
> > >         if (unlikely(viewContainer == nil)) {
> > >             msg_Err(_voutDisplay, "provided view container is nil");
> > >             return NO;
> > > @@ -462,20 +464,10 @@ static void GLESSwap(vlc_gl_t *gl)
> > >
> > >         [_viewContainer addSubview:self];
> > >
> > > -        /* add tap gesture recognizer for DVD menus and stuff */
> > > -        _tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
> > > -                                                                 action:@selector(tapRecognized:)];
> > > -        if (_viewContainer.window
> > > -         && _viewContainer.window.rootViewController
> > > -         && _viewContainer.window.rootViewController.view)
> > > -            [_viewContainer.superview addGestureRecognizer:_tapRecognizer];
> > > -        _tapRecognizer.cancelsTouchesInView = NO;
> > >         return YES;
> > >     } @catch (NSException *exception) {
> > >         msg_Err(_voutDisplay, "Handling the view container failed due to an Obj-C exception (%s, %s", [exception.name UTF8String], [exception.reason UTF8String]);
> > >         vout_display_sys_t *sys = _voutDisplay->sys;
> > > -        if (_tapRecognizer)
> > > -            [_tapRecognizer release];
> > >         return NO;
> > >     }
> > > }
> > > @@ -484,9 +476,6 @@ static void GLESSwap(vlc_gl_t *gl)
> > > {
> > >     [[NSNotificationCenter defaultCenter] removeObserver:self];
> > >
> > > -    [_tapRecognizer.view removeGestureRecognizer:_tapRecognizer];
> > > -    [_tapRecognizer release];
> > > -
> > >     [self removeFromSuperview];
> > >     [_viewContainer release];
> > >
> > > @@ -677,27 +666,6 @@ static void GLESSwap(vlc_gl_t *gl)
> > >     vlc_mutex_unlock(&_mutex);
> > > }
> > >
> > > -- (void)tapRecognized:(UITapGestureRecognizer *)tapRecognizer
> > > -{
> > > -    vlc_mutex_lock(&_mutex);
> > > -    if (!_voutDisplay)
> > > -    {
> > > -        vlc_mutex_unlock(&_mutex);
> > > -        return;
> > > -    }
> > > -
> > > -    UIGestureRecognizerState state = [tapRecognizer state];
> > > -    CGPoint touchPoint = [tapRecognizer locationInView:self];
> > > -    CGFloat scaleFactor = self.contentScaleFactor;
> > > -    vout_display_SendMouseMovedDisplayCoordinates(_voutDisplay,
> > > -                                                  (int)touchPoint.x * scaleFactor, (int)touchPoint.y * scaleFactor);
> > > -
> > > -    vout_display_SendEventMousePressed(_voutDisplay, MOUSE_BUTTON_LEFT);
> > > -    vout_display_SendEventMouseReleased(_voutDisplay, MOUSE_BUTTON_LEFT);
> > > -
> > > -    vlc_mutex_unlock(&_mutex);
> > > -}
> > > -
> > > - (void)updateVoutCfg:(const vout_display_cfg_t *)cfg withVGL:(vout_display_opengl_t *)vgl
> > > {
> > >     if (memcmp(&_cfg, cfg, sizeof(vout_display_cfg_t)) == 0)
> > > @@ -775,9 +743,11 @@ static void GLESSwap(vlc_gl_t *gl)
> > >     return YES;
> > > }
> > >
> > > -- (BOOL)acceptsFirstResponder
> > > +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
> > > {
> > > -    return YES;
> > > +    /* Disable events for this view, as the vout_window view will be the one
> > > +     * handling them. */
> > > +    return nil;
> > > }
> > >
> > > @end
> > > —
> >
> >
> > Rest LGTM.
> >
> > Cheers,
> >
> > Felix
> >
> > _______________________________________________
> > vlc-devel mailing list
> > To unsubscribe or modify your subscription options:
> > https://mailman.videolan.org/listinfo/vlc-devel
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list