Backport AVKit-based wxMediaCtrl to fix build under OS X 10.12
Allow building wxOSX using 10.12 SDK which doesn't include QTKit support any longer. See https://github.com/wxWidgets/wxWidgets/pull/341
This commit is contained in:
194
configure
vendored
194
configure
vendored
@@ -1238,6 +1238,7 @@ enable_svg
|
||||
enable_webkit
|
||||
enable_webview
|
||||
enable_graphics_ctx
|
||||
enable_qtkit
|
||||
enable_clipboard
|
||||
enable_dnd
|
||||
enable_controls
|
||||
@@ -2169,6 +2170,7 @@ Optional Features:
|
||||
--enable-webkit use wxWebKitCtrl (Mac-only, use wxWebView instead)
|
||||
--enable-webview use wxWebView library
|
||||
--enable-graphics_ctx use graphics context 2D drawing API
|
||||
--disable-qtkit force AVFoundation instead of QTKit (requires OS X 10.7+)
|
||||
--enable-clipboard use wxClipboard class
|
||||
--enable-dnd use Drag'n'Drop classes
|
||||
--disable-controls disable compilation of all standard controls
|
||||
@@ -3339,6 +3341,97 @@ fi
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_cxx_try_run
|
||||
|
||||
# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
|
||||
# -------------------------------------------------------
|
||||
# Tests whether HEADER exists, giving a warning if it cannot be compiled using
|
||||
# the include files in INCLUDES and setting the cache variable VAR
|
||||
# accordingly.
|
||||
ac_fn_c_check_header_mongrel ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
if eval \${$3+:} false; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
$as_echo_n "checking for $2... " >&6; }
|
||||
if eval \${$3+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
else
|
||||
# Is the header compilable?
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
|
||||
$as_echo_n "checking $2 usability... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
#include <$2>
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
ac_header_compiler=yes
|
||||
else
|
||||
ac_header_compiler=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
|
||||
$as_echo "$ac_header_compiler" >&6; }
|
||||
|
||||
# Is the header present?
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
|
||||
$as_echo_n "checking $2 presence... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <$2>
|
||||
_ACEOF
|
||||
if ac_fn_c_try_cpp "$LINENO"; then :
|
||||
ac_header_preproc=yes
|
||||
else
|
||||
ac_header_preproc=no
|
||||
fi
|
||||
rm -f conftest.err conftest.i conftest.$ac_ext
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
|
||||
$as_echo "$ac_header_preproc" >&6; }
|
||||
|
||||
# So? What about this header?
|
||||
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
|
||||
yes:no: )
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
|
||||
$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
|
||||
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
|
||||
;;
|
||||
no:yes:* )
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
|
||||
$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
|
||||
$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
|
||||
$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
|
||||
$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
|
||||
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
|
||||
( $as_echo "## ----------------------------------------- ##
|
||||
## Report this to wx-dev@lists.wxwidgets.org ##
|
||||
## ----------------------------------------- ##"
|
||||
) | sed "s/^/$as_me: WARNING: /" >&2
|
||||
;;
|
||||
esac
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
$as_echo_n "checking for $2... " >&6; }
|
||||
if eval \${$3+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
eval "$3=\$ac_header_compiler"
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
fi
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_header_mongrel
|
||||
cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
@@ -10923,6 +11016,51 @@ fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $result" >&5
|
||||
$as_echo "$result" >&6; }
|
||||
|
||||
else
|
||||
|
||||
enablestring=disable
|
||||
defaultval=
|
||||
if test -z "$defaultval"; then
|
||||
if test x"$enablestring" = xdisable; then
|
||||
defaultval=yes
|
||||
else
|
||||
defaultval=no
|
||||
fi
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --${enablestring:-enable}-qtkit" >&5
|
||||
$as_echo_n "checking for --${enablestring:-enable}-qtkit... " >&6; }
|
||||
# Check whether --enable-qtkit was given.
|
||||
if test "${enable_qtkit+set}" = set; then :
|
||||
enableval=$enable_qtkit;
|
||||
if test "$enableval" = yes; then
|
||||
wx_cv_use_qtkit='wxOSX_USE_QTKIT=yes'
|
||||
else
|
||||
wx_cv_use_qtkit='wxOSX_USE_QTKIT=no'
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
wx_cv_use_qtkit='wxOSX_USE_QTKIT=${'DEFAULT_wxOSX_USE_QTKIT":-$defaultval}"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
eval "$wx_cv_use_qtkit"
|
||||
|
||||
if test x"$enablestring" = xdisable; then
|
||||
if test $wxOSX_USE_QTKIT = no; then
|
||||
result=yes
|
||||
else
|
||||
result=no
|
||||
fi
|
||||
else
|
||||
result=$wxOSX_USE_QTKIT
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $result" >&5
|
||||
$as_echo "$result" >&6; }
|
||||
|
||||
fi
|
||||
|
||||
|
||||
@@ -37365,7 +37503,61 @@ fi
|
||||
fi
|
||||
|
||||
elif test "$wxUSE_MAC" = 1; then
|
||||
GST_LIBS="-framework QTKit"
|
||||
if test "$wxUSE_OSX_IPHONE" = 1; then
|
||||
GST_LIBS="-framework AVFoundation -framework CoreMedia"
|
||||
else
|
||||
|
||||
old_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="-x objective-c++ $CPPFLAGS"
|
||||
if test "$wxOSX_USE_QTKIT" = "no"; then
|
||||
$as_echo "#define wxOSX_USE_QTKIT 0" >>confdefs.h
|
||||
|
||||
GST_LIBS="-framework AVFoundation -framework CoreMedia"
|
||||
else
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "QTKit/QTKit.h" "ac_cv_header_QTKit_QTKit_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_QTKit_QTKit_h" = xyes; then :
|
||||
|
||||
GST_LIBS="-framework QTKit"
|
||||
|
||||
else
|
||||
|
||||
$as_echo "#define wxOSX_USE_QTKIT 0" >>confdefs.h
|
||||
|
||||
wxOSX_USE_QTKIT=no
|
||||
GST_LIBS="-framework AVFoundation -framework CoreMedia"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
if test "$wxOSX_USE_QTKIT" = "no"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if AVKit is availble" >&5
|
||||
$as_echo_n "checking if AVKit is availble... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include "AvailabilityMacros.h"
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
|
||||
// AVKit available
|
||||
#else
|
||||
choke me
|
||||
#endif
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
GST_LIBS="$GST_LIBS -framework AVKit"
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
CPPFLAGS="$old_CPPFLAGS"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $USE_MEDIA = 1; then
|
||||
|
50
configure.in
50
configure.in
@@ -838,6 +838,8 @@ dnl wxDC is implemented in terms of wxGraphicsContext in wxOSX so the latter
|
||||
dnl can't be disabled, don't even provide an option to do it
|
||||
if test "$wxUSE_MAC" != 1; then
|
||||
WX_ARG_FEATURE(graphics_ctx,[ --enable-graphics_ctx use graphics context 2D drawing API], wxUSE_GRAPHICS_CONTEXT)
|
||||
else
|
||||
WX_ARG_DISABLE(qtkit, [ --disable-qtkit force AVFoundation instead of QTKit (requires OS X 10.7+)], wxOSX_USE_QTKIT)
|
||||
fi
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
@@ -7590,10 +7592,50 @@ if test "$wxUSE_MEDIACTRL" = "yes" -o "$wxUSE_MEDIACTRL" = "auto"; then
|
||||
USE_MEDIA=0
|
||||
fi
|
||||
|
||||
elif test "$wxUSE_MAC" = 1; then
|
||||
dnl We always have the necessary libraries under Mac
|
||||
dnl but we need to link with it explicitly.
|
||||
GST_LIBS="-framework QTKit"
|
||||
elif test "$wxUSE_MAC" = 1; then
|
||||
if test "$wxUSE_OSX_IPHONE" = 1; then
|
||||
dnl this will also be used for cocoa in the future
|
||||
GST_LIBS="-framework AVFoundation -framework CoreMedia"
|
||||
else
|
||||
dnl We always have the necessary libraries under Mac
|
||||
dnl but we need to link with it explicitly.
|
||||
dnl QTKit is no longer available as of 10.12 SDK
|
||||
|
||||
old_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="-x objective-c++ $CPPFLAGS"
|
||||
if test "$wxOSX_USE_QTKIT" = "no"; then
|
||||
dnl Do not test for QTKit if has been disabled from the command line
|
||||
AC_DEFINE(wxOSX_USE_QTKIT,0)
|
||||
GST_LIBS="-framework AVFoundation -framework CoreMedia"
|
||||
else
|
||||
dnl check if QTKit is available, otherwise force AVFoundation usage
|
||||
AC_CHECK_HEADER([QTKit/QTKit.h],
|
||||
[
|
||||
GST_LIBS="-framework QTKit"
|
||||
],
|
||||
[
|
||||
AC_DEFINE(wxOSX_USE_QTKIT,0)
|
||||
wxOSX_USE_QTKIT=no
|
||||
GST_LIBS="-framework AVFoundation -framework CoreMedia"
|
||||
])
|
||||
fi
|
||||
if test "$wxOSX_USE_QTKIT" = "no"; then
|
||||
dnl AVKit is only available since OS X 10.9
|
||||
AC_MSG_CHECKING([if AVKit is availble])
|
||||
AC_TRY_COMPILE(
|
||||
[#include "AvailabilityMacros.h"],
|
||||
[
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
|
||||
// AVKit available
|
||||
#else
|
||||
choke me
|
||||
#endif
|
||||
],
|
||||
GST_LIBS="$GST_LIBS -framework AVKit"
|
||||
)
|
||||
fi
|
||||
CPPFLAGS="$old_CPPFLAGS"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $USE_MEDIA = 1; then
|
||||
|
@@ -656,6 +656,8 @@ wxOSX:
|
||||
- Fix conversion of wxBitmap to wxImage in 64 bit builds.
|
||||
- Fix length of text in wxTextDataObject.
|
||||
- Fix using wxHTTP and wxFTP from worker thread.
|
||||
- Compilation fix for wxMediaCtrl under 10.12 (Tobias Taschner)
|
||||
- Added --disable-qtkit to force usage of AVFoundation under 10.7-10.11 (Tobias Taschner)
|
||||
- Fix wxFileDialog::GetFilterIndex() for file open dialogs (phsilva).
|
||||
- Fix wxSearchCtrl appearance under 10.10 (John Roberts).
|
||||
- Fix handling of "Cancel" button in wxSearchCtrl (John Roberts).
|
||||
|
@@ -871,6 +871,11 @@
|
||||
*/
|
||||
#define wxUSE_WEBKIT 0
|
||||
|
||||
/*
|
||||
* wxMediaCtrl on OS X
|
||||
*/
|
||||
#undef wxOSX_USE_QTKIT
|
||||
|
||||
/*
|
||||
* Objective-C class name uniquifying
|
||||
*/
|
||||
|
@@ -1,10 +1,10 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/cocoa/mediactrl.cpp
|
||||
// Name: src/osx/cocoa/mediactrl.mm
|
||||
// Purpose: Built-in Media Backends for Cocoa
|
||||
// Author: Ryan Norton <wxprojects@comcast.net>
|
||||
// Author: Ryan Norton <wxprojects@comcast.net>, Stefan Csomor
|
||||
// Modified by:
|
||||
// Created: 02/03/05
|
||||
// Copyright: (c) 2004-2005 Ryan Norton, (c) 2005 David Elliot
|
||||
// Copyright: (c) 2004-2005 Ryan Norton, (c) 2005 David Elliot, (c) Stefan Csomor
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -36,10 +36,34 @@
|
||||
|
||||
#include "wx/osx/private.h"
|
||||
|
||||
#ifndef wxOSX_USE_QTKIT
|
||||
#if wxOSX_USE_IPHONE
|
||||
#define wxOSX_USE_QTKIT 0
|
||||
#define wxOSX_USE_AVFOUNDATION 1
|
||||
#else
|
||||
#define wxOSX_USE_QTKIT 1
|
||||
#define wxOSX_USE_AVFOUNDATION 0
|
||||
#endif
|
||||
#else
|
||||
#if wxOSX_USE_QTKIT
|
||||
#define wxOSX_USE_AVFOUNDATION 0
|
||||
#else
|
||||
#define wxOSX_USE_AVFOUNDATION 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if wxOSX_USE_AVFOUNDATION && wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
|
||||
#define wxOSX_USE_AVKIT 1
|
||||
#else
|
||||
#define wxOSX_USE_AVKIT 0
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
// BACKEND DECLARATIONS
|
||||
//===========================================================================
|
||||
|
||||
#if wxOSX_USE_QTKIT
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// wxQTMediaBackend
|
||||
@@ -147,9 +171,9 @@ private:
|
||||
-(void)dealloc
|
||||
{
|
||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||
[nc removeObserver:self];
|
||||
[nc removeObserver:self];
|
||||
|
||||
[super dealloc];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(wxQTMediaBackend*) backend
|
||||
@@ -173,17 +197,17 @@ private:
|
||||
|
||||
- (void)movieRateChanged:(NSNotification *)notification
|
||||
{
|
||||
NSDictionary *userInfo = [notification userInfo];
|
||||
|
||||
NSNumber *newRate = [userInfo objectForKey:QTMovieRateDidChangeNotificationParameter];
|
||||
NSDictionary *userInfo = [notification userInfo];
|
||||
|
||||
if ([newRate intValue] == 0)
|
||||
{
|
||||
m_backend->QueuePauseEvent();
|
||||
}
|
||||
NSNumber *newRate = [userInfo objectForKey:QTMovieRateDidChangeNotificationParameter];
|
||||
|
||||
if ([newRate intValue] == 0)
|
||||
{
|
||||
m_backend->QueuePauseEvent();
|
||||
}
|
||||
else if ( [self isPlaying] == NO )
|
||||
{
|
||||
m_backend->QueuePlayEvent();
|
||||
m_backend->QueuePlayEvent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,12 +231,12 @@ private:
|
||||
|
||||
-(BOOL)isPlaying
|
||||
{
|
||||
if ([self rate] == 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
if ([self rate] == 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -433,6 +457,547 @@ void wxQTMediaBackend::DoShowPlayerControls(wxMediaCtrlPlayerControls flags)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if wxOSX_USE_AVFOUNDATION
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// wxAVMediaBackend
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
#if wxOSX_USE_AVKIT
|
||||
#import <AVKit/AVKit.h>
|
||||
#endif
|
||||
|
||||
class WXDLLIMPEXP_FWD_MEDIA wxAVMediaBackend;
|
||||
|
||||
static void *AVSPPlayerItemStatusContext = &AVSPPlayerItemStatusContext;
|
||||
static void *AVSPPlayerRateContext = &AVSPPlayerRateContext;
|
||||
|
||||
@interface wxAVPlayer : AVPlayer {
|
||||
|
||||
AVPlayerLayer *playerLayer;
|
||||
|
||||
wxAVMediaBackend* m_backend;
|
||||
}
|
||||
|
||||
-(BOOL)isPlaying;
|
||||
|
||||
@property (retain) AVPlayerLayer *playerLayer;
|
||||
|
||||
@end
|
||||
|
||||
class WXDLLIMPEXP_MEDIA wxAVMediaBackend : public wxMediaBackendCommonBase
|
||||
{
|
||||
public:
|
||||
|
||||
wxAVMediaBackend();
|
||||
~wxAVMediaBackend();
|
||||
|
||||
virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
|
||||
wxWindowID id,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size,
|
||||
long style,
|
||||
const wxValidator& validator,
|
||||
const wxString& name);
|
||||
|
||||
virtual bool Play();
|
||||
virtual bool Pause();
|
||||
virtual bool Stop();
|
||||
|
||||
virtual bool Load(const wxString& fileName);
|
||||
virtual bool Load(const wxURI& location);
|
||||
|
||||
virtual wxMediaState GetState();
|
||||
|
||||
virtual bool SetPosition(wxLongLong where);
|
||||
virtual wxLongLong GetPosition();
|
||||
virtual wxLongLong GetDuration();
|
||||
|
||||
virtual void Move(int x, int y, int w, int h);
|
||||
wxSize GetVideoSize() const;
|
||||
|
||||
virtual double GetPlaybackRate();
|
||||
virtual bool SetPlaybackRate(double dRate);
|
||||
|
||||
virtual double GetVolume();
|
||||
virtual bool SetVolume(double dVolume);
|
||||
|
||||
void Cleanup();
|
||||
void FinishLoad();
|
||||
|
||||
virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
|
||||
private:
|
||||
void DoShowPlayerControls(wxMediaCtrlPlayerControls flags);
|
||||
|
||||
wxSize m_bestSize; //Original movie size
|
||||
wxAVPlayer* m_player; //AVPlayer handle/instance
|
||||
|
||||
wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS(wxAVMediaBackend);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// wxAVMediaBackend
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
@implementation wxAVPlayer
|
||||
|
||||
@synthesize playerLayer;
|
||||
|
||||
- (id) init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
[self addObserver:self forKeyPath:@"currentItem.status"
|
||||
options:NSKeyValueObservingOptionNew context:AVSPPlayerItemStatusContext];
|
||||
[self addObserver:self forKeyPath:@"rate"
|
||||
options:NSKeyValueObservingOptionNew context:AVSPPlayerRateContext];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[playerLayer release];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
[self removeObserver:self forKeyPath:@"rate" context:AVSPPlayerRateContext];
|
||||
[self removeObserver:self forKeyPath:@"currentItem.status" context:AVSPPlayerItemStatusContext];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
if (context == AVSPPlayerItemStatusContext)
|
||||
{
|
||||
id val = [change objectForKey:NSKeyValueChangeNewKey];
|
||||
if ( val != [NSNull null ] )
|
||||
{
|
||||
AVPlayerStatus status = (AVPlayerStatus) [ val integerValue];
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case AVPlayerItemStatusUnknown:
|
||||
break;
|
||||
case AVPlayerItemStatusReadyToPlay:
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self selector:@selector(playerItemDidReachEnd:)
|
||||
name:AVPlayerItemDidPlayToEndTimeNotification object:self.currentItem];
|
||||
m_backend->FinishLoad();
|
||||
break;
|
||||
case AVPlayerItemStatusFailed:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (context == AVSPPlayerRateContext)
|
||||
{
|
||||
NSNumber* newRate = [change objectForKey:NSKeyValueChangeNewKey];
|
||||
if ([newRate intValue] == 0)
|
||||
{
|
||||
m_backend->QueuePauseEvent();
|
||||
}
|
||||
else if ( [self isPlaying] == NO )
|
||||
{
|
||||
m_backend->QueuePlayEvent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
||||
}
|
||||
}
|
||||
|
||||
-(wxAVMediaBackend*) backend
|
||||
{
|
||||
return m_backend;
|
||||
}
|
||||
|
||||
-(void) setBackend:(wxAVMediaBackend*) backend
|
||||
{
|
||||
m_backend = backend;
|
||||
}
|
||||
|
||||
- (void)playerItemDidReachEnd:(NSNotification *)notification
|
||||
{
|
||||
if ( m_backend )
|
||||
{
|
||||
if ( m_backend->SendStopEvent() )
|
||||
m_backend->QueueFinishEvent();
|
||||
}
|
||||
}
|
||||
|
||||
-(BOOL)isPlaying
|
||||
{
|
||||
if ([self rate] == 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#if wxOSX_USE_IPHONE
|
||||
|
||||
@interface wxAVView : UIView
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation wxAVView
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
static BOOL initialized = NO;
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = YES;
|
||||
wxOSXIPhoneClassAddWXMethods( self );
|
||||
}
|
||||
}
|
||||
|
||||
+ (Class)layerClass
|
||||
{
|
||||
return [AVPlayerLayer class];
|
||||
}
|
||||
|
||||
- (id) initWithFrame:(CGRect)rect player:(wxAVPlayer*) player
|
||||
{
|
||||
if ( !(self=[super initWithFrame:rect]) )
|
||||
return nil;
|
||||
|
||||
AVPlayerLayer* playerLayer = (AVPlayerLayer*) [self layer];
|
||||
[playerLayer setPlayer: player];
|
||||
[player setPlayerLayer:playerLayer];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (AVPlayerLayer*) playerLayer
|
||||
{
|
||||
return (AVPlayerLayer*) [self layer];
|
||||
}
|
||||
@end
|
||||
|
||||
#else
|
||||
|
||||
#if wxOSX_USE_AVKIT
|
||||
|
||||
@interface wxAVPlayerView : AVPlayerView
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation wxAVPlayerView
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
static BOOL initialized = NO;
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = YES;
|
||||
wxOSXCocoaClassAddWXMethods( self );
|
||||
}
|
||||
}
|
||||
|
||||
- (id) initWithFrame:(NSRect)rect player:(wxAVPlayer*) player
|
||||
{
|
||||
if ( !(self=[super initWithFrame:rect]) )
|
||||
return nil;
|
||||
|
||||
self.player = player;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (AVPlayerLayer*) playerLayer
|
||||
{
|
||||
return (AVPlayerLayer*) [[[self layer] sublayers] firstObject];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif // wxOSX_USE_AVKIT
|
||||
|
||||
@interface wxAVView : NSView
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation wxAVView
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
static BOOL initialized = NO;
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = YES;
|
||||
wxOSXCocoaClassAddWXMethods( self );
|
||||
}
|
||||
}
|
||||
|
||||
- (id) initWithFrame:(NSRect)rect player:(AVPlayer*) player
|
||||
{
|
||||
if ( !(self=[super initWithFrame:rect]) )
|
||||
return nil;
|
||||
|
||||
[self setWantsLayer:YES];
|
||||
AVPlayerLayer* playerlayer = [[AVPlayerLayer playerLayerWithPlayer: player] retain];
|
||||
[player setPlayerLayer:playerlayer];
|
||||
|
||||
[playerlayer setFrame:[[self layer] bounds]];
|
||||
[playerlayer setAutoresizingMask:kCALayerWidthSizable | kCALayerHeightSizable];
|
||||
[[self layer] addSublayer:playerlayer];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (AVPlayerLayer*) playerLayer
|
||||
{
|
||||
return (AVPlayerLayer*) [[[self layer] sublayers] firstObject];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxAVMediaBackend, wxMediaBackend);
|
||||
|
||||
wxAVMediaBackend::wxAVMediaBackend() :
|
||||
m_player(nil),
|
||||
m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
wxAVMediaBackend::~wxAVMediaBackend()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
|
||||
wxWindowID wid,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size,
|
||||
long style,
|
||||
const wxValidator& validator,
|
||||
const wxString& name)
|
||||
{
|
||||
wxMediaCtrl* mediactrl = (wxMediaCtrl*) inctrl;
|
||||
|
||||
mediactrl->DontCreatePeer();
|
||||
|
||||
if ( !mediactrl->wxControl::Create(
|
||||
parent, wid, pos, size,
|
||||
wxWindow::MacRemoveBordersFromStyle(style),
|
||||
validator, name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_player = [[wxAVPlayer alloc] init];
|
||||
[m_player setBackend:this];
|
||||
|
||||
NSRect r = wxOSXGetFrameForControl( mediactrl, pos , size ) ;
|
||||
|
||||
WXWidget view = NULL;
|
||||
#if wxOSX_USE_AVKIT
|
||||
if ( NSClassFromString(@"AVPlayerView") )
|
||||
{
|
||||
view = [[wxAVPlayerView alloc] initWithFrame: r player:m_player];
|
||||
[(wxAVPlayerView*) view setControlsStyle:AVPlayerViewControlsStyleNone];
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( view == NULL )
|
||||
{
|
||||
view = [[wxAVView alloc] initWithFrame: r player:m_player];
|
||||
}
|
||||
|
||||
#if wxOSX_USE_IPHONE
|
||||
wxWidgetIPhoneImpl* impl = new wxWidgetIPhoneImpl(mediactrl,view);
|
||||
#else
|
||||
wxWidgetCocoaImpl* impl = new wxWidgetCocoaImpl(mediactrl,view);
|
||||
#endif
|
||||
mediactrl->SetPeer(impl);
|
||||
|
||||
m_ctrl = mediactrl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::Load(const wxString& fileName)
|
||||
{
|
||||
return Load(
|
||||
wxURI(
|
||||
wxString( wxT("file://") ) + fileName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::Load(const wxURI& location)
|
||||
{
|
||||
wxCFStringRef uri(location.BuildURI());
|
||||
NSURL *url = [NSURL URLWithString: uri.AsNSString()];
|
||||
|
||||
AVAsset* asset = [AVAsset assetWithURL:url];
|
||||
if (! asset )
|
||||
return false;
|
||||
|
||||
if ( [asset isPlayable] )
|
||||
{
|
||||
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
|
||||
[m_player replaceCurrentItemWithPlayerItem:playerItem];
|
||||
|
||||
return playerItem != nil;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxAVMediaBackend::FinishLoad()
|
||||
{
|
||||
DoShowPlayerControls(m_interfaceflags);
|
||||
|
||||
AVPlayerItem *playerItem = [m_player currentItem];
|
||||
|
||||
CGSize s = [playerItem presentationSize];
|
||||
m_bestSize = wxSize(s.width, s.height);
|
||||
|
||||
NotifyMovieLoaded();
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::Play()
|
||||
{
|
||||
[m_player play];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::Pause()
|
||||
{
|
||||
[m_player pause];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::Stop()
|
||||
{
|
||||
[m_player pause];
|
||||
[m_player seekToTime:kCMTimeZero];
|
||||
return true;
|
||||
}
|
||||
|
||||
double wxAVMediaBackend::GetVolume()
|
||||
{
|
||||
return [m_player volume];
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::SetVolume(double dVolume)
|
||||
{
|
||||
[m_player setVolume:dVolume];
|
||||
return true;
|
||||
}
|
||||
double wxAVMediaBackend::GetPlaybackRate()
|
||||
{
|
||||
return [m_player rate];
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::SetPlaybackRate(double dRate)
|
||||
{
|
||||
[m_player setRate:dRate];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::SetPosition(wxLongLong where)
|
||||
{
|
||||
[m_player seekToTime:CMTimeMakeWithSeconds(where.GetValue() / 1000.0, 1)
|
||||
toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wxLongLong wxAVMediaBackend::GetPosition()
|
||||
{
|
||||
return CMTimeGetSeconds([m_player currentTime])*1000.0;
|
||||
}
|
||||
|
||||
wxLongLong wxAVMediaBackend::GetDuration()
|
||||
{
|
||||
AVPlayerItem *playerItem = [m_player currentItem];
|
||||
|
||||
if ([playerItem status] == AVPlayerItemStatusReadyToPlay)
|
||||
return CMTimeGetSeconds([[playerItem asset] duration])*1000.0;
|
||||
else
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
wxMediaState wxAVMediaBackend::GetState()
|
||||
{
|
||||
if ( [m_player isPlaying] )
|
||||
return wxMEDIASTATE_PLAYING;
|
||||
else
|
||||
{
|
||||
if ( GetPosition() == 0 )
|
||||
return wxMEDIASTATE_STOPPED;
|
||||
else
|
||||
return wxMEDIASTATE_PAUSED;
|
||||
}
|
||||
}
|
||||
|
||||
void wxAVMediaBackend::Cleanup()
|
||||
{
|
||||
[m_player pause];
|
||||
[m_player release];
|
||||
m_player = nil;
|
||||
}
|
||||
|
||||
wxSize wxAVMediaBackend::GetVideoSize() const
|
||||
{
|
||||
return m_bestSize;
|
||||
}
|
||||
|
||||
void wxAVMediaBackend::Move(int x, int y, int w, int h)
|
||||
{
|
||||
// as we have a native player, no need to move the video area
|
||||
}
|
||||
|
||||
bool wxAVMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
|
||||
{
|
||||
if ( m_interfaceflags != flags )
|
||||
DoShowPlayerControls(flags);
|
||||
|
||||
m_interfaceflags = flags;
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxAVMediaBackend::DoShowPlayerControls(wxMediaCtrlPlayerControls flags)
|
||||
{
|
||||
#if wxOSX_USE_AVKIT
|
||||
NSView* view = m_ctrl->GetHandle();
|
||||
if ( [view isKindOfClass:[wxAVPlayerView class]] )
|
||||
{
|
||||
wxAVPlayerView* playerView = (wxAVPlayerView*) view;
|
||||
if (flags == wxMEDIACTRLPLAYERCONTROLS_NONE )
|
||||
playerView.controlsStyle = AVPlayerViewControlsStyleNone;
|
||||
else
|
||||
playerView.controlsStyle = AVPlayerViewControlsStyleDefault;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//in source file that contains stuff you don't directly use
|
||||
#include "wx/html/forcelnk.h"
|
||||
FORCE_LINK_ME(basewxmediabackends);
|
||||
|
Reference in New Issue
Block a user