2015-04-05 05:36:53 +02:00
/ * RetroArch - A frontend for libretro .
* Copyright ( C ) 2013 -2014 - Jason Fetters
2017-01-22 13:40:32 +01:00
* Copyright ( C ) 2011 -2017 - Daniel De Matteis
2015-04-05 05:36:53 +02:00
*
* RetroArch is free software : you can redistribute it and / or modify it under the terms
* of the GNU General Public License as published by the Free Software Found -
* ation , either version 3 of the License , or ( at your option ) any later version .
*
* RetroArch 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 General Public License for more details .
*
* You should have received a copy of the GNU General Public License along with RetroArch .
* If not , see < http : // www . gnu . org / licenses / > .
* /
# import < AvailabilityMacros . h >
# include < sys / stat . h >
2015-04-20 12:52:16 +02:00
# include "cocoa_common.h"
2016-06-05 07:01:04 +02:00
# ifdef HAVE_COCOA
2016-06-07 16:47:48 +02:00
# include "../ui_cocoa.h"
2016-06-05 07:01:04 +02:00
# endif
2016-09-08 11:59:44 +02:00
# include < retro_assert . h >
2016-06-08 07:41:59 +02:00
# include "../../../verbosity.h"
2015-04-05 05:36:53 +02:00
/ * Define compatibility symbols and categories . * /
# ifdef HAVE_AVFOUNDATION
# include < AVFoundation / AVCaptureSession . h >
# include < AVFoundation / AVCaptureDevice . h >
# include < AVFoundation / AVCaptureOutput . h >
# include < AVFoundation / AVCaptureInput . h >
# include < AVFoundation / AVMediaFormat . h >
# ifdef HAVE_OPENGLES
# include < CoreVideo / CVOpenGLESTextureCache . h >
# else
# include < CoreVideo / CVOpenGLTexture . h >
# endif
# endif
2015-12-05 17:20:11 +01:00
# include "../../../location/location_driver.h"
# include "../../../camera/camera_driver.h"
2015-12-05 17:15:32 +01:00
2019-01-26 13:18:32 -10:00
# ifdef HAVE_COCOATOUCH
# import "GCDWebUploader.h"
# import "WebServer.h"
# endif
2015-04-20 20:39:39 +02:00
static CocoaView * g_instance ;
2015-04-05 05:36:53 +02:00
2015-04-20 00:38:55 +02:00
# if defined ( HAVE_COCOA )
2015-04-12 16:50:39 +02:00
void * nsview_get _ptr ( void )
{
2018-11-04 09:29:40 -07:00
return g_instance ;
2018-05-13 09:50:47 -07:00
}
2015-04-05 05:36:53 +02:00
# endif
2015-04-12 16:50:39 +02:00
/ * forward declarations * /
2015-04-19 17:40:10 +02:00
void cocoagl_gfx _ctx _update ( void ) ;
2015-04-12 16:50:39 +02:00
void * glkitview_init ( void ) ;
2015-04-05 05:36:53 +02:00
2019-01-26 13:18:32 -10:00
# ifdef HAVE_COCOATOUCH
@ interface CocoaView ( ) < GCDWebUploaderDelegate > {
}
@ end
# endif
2015-04-20 20:39:39 +02:00
@ implementation CocoaView
2016-10-05 02:00:11 +02:00
# if defined ( HAVE_COCOA )
# include "../../../input/drivers/cocoa_input.h"
- ( void ) scrollWheel : ( NSEvent * ) theEvent {
cocoa_input _data _t * apple = ( cocoa_input _data _t * ) input_driver _get _data ( ) ;
( void ) apple ;
}
# endif
2015-04-20 20:39:39 +02:00
+ ( CocoaView * ) get
2015-04-05 05:36:53 +02:00
{
if ( ! g_instance )
2015-04-20 20:39:39 +02:00
g_instance = [ CocoaView new ] ;
2015-04-05 05:36:53 +02:00
return g_instance ;
}
- ( id ) init
{
self = [ super init ] ;
2015-04-20 00:38:55 +02:00
# if defined ( HAVE_COCOA )
2015-04-05 05:36:53 +02:00
[ self setAutoresizingMask : NSViewWidthSizable | NSViewHeightSizable ] ;
2018-11-04 09:29:40 -07:00
ui_window _cocoa _t cocoa_view ;
cocoa_view . data = ( CocoaView * ) self ;
2016-06-04 08:45:20 +02:00
[ self registerForDraggedTypes : [ NSArray arrayWithObjects : NSColorPboardType , NSFilenamesPboardType , nil ] ] ;
2015-04-20 00:38:55 +02:00
# elif defined ( HAVE_COCOATOUCH )
2015-04-12 16:50:39 +02:00
self . view = ( __bridge GLKView * ) glkitview_init ( ) ;
2019-01-26 13:18:32 -10:00
# if TARGET_OS _IOS
2015-04-05 05:36:53 +02:00
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( showPauseIndicator ) name : UIApplicationWillEnterForegroundNotification object : nil ] ;
2019-01-26 13:18:32 -10:00
# endif
2015-04-05 05:36:53 +02:00
# endif
return self ;
}
2015-04-20 00:38:55 +02:00
# if defined ( HAVE_COCOA )
2015-04-05 05:36:53 +02:00
- ( void ) setFrame : ( NSRect ) frameRect
{
[ super setFrame : frameRect ] ;
2018-11-04 09:29:40 -07:00
2015-04-19 17:40:10 +02:00
cocoagl_gfx _ctx _update ( ) ;
2015-04-05 05:36:53 +02:00
}
/ * Stop the annoying sound when pressing a key . * /
- ( BOOL ) acceptsFirstResponder
{
return YES ;
}
- ( BOOL ) isFlipped
{
return YES ;
}
- ( void ) keyDown : ( NSEvent * ) theEvent
{
}
2016-06-03 19:21:22 +02:00
- ( NSDragOperation ) draggingEntered : ( id < NSDraggingInfo > ) sender
{
NSDragOperation sourceDragMask = [ sender draggingSourceOperationMask ] ;
NSPasteboard * pboard = [ sender draggingPasteboard ] ;
if ( [ [ pboard types ] containsObject : NSFilenamesPboardType ] )
{
if ( sourceDragMask & NSDragOperationCopy )
return NSDragOperationCopy ;
}
return NSDragOperationNone ;
}
- ( BOOL ) performDragOperation : ( id < NSDraggingInfo > ) sender
{
NSPasteboard * pboard = [ sender draggingPasteboard ] ;
if ( [ [ pboard types ] containsObject : NSURLPboardType ] )
{
NSURL * fileURL = [ NSURL URLFromPasteboard : pboard ] ;
NSString * s = [ fileURL path ] ;
if ( s ! = nil )
{
RARCH_LOG ( "Drop name is: %s\n" , [ s UTF8String ] ) ;
}
}
return YES ;
}
- ( void ) draggingExited : ( id < NSDraggingInfo > ) sender
{
[ self setNeedsDisplay : YES ] ;
}
2019-01-26 13:18:32 -10:00
# elif TARGET_OS _IOS
2018-11-27 09:29:30 -10:00
- ( UIRectEdge ) preferredScreenEdgesDeferringSystemGestures
{
return UIRectEdgeBottom ;
}
- ( BOOL ) prefersHomeIndicatorAutoHidden
{
return NO ;
}
- ( void ) viewWillTransitionToSize : ( CGSize ) size withTransitionCoordinator : ( id < UIViewControllerTransitionCoordinator > ) coordinator {
[ super viewWillTransitionToSize : size withTransitionCoordinator : coordinator ] ;
if ( @ available ( iOS 11 , * ) ) {
[ coordinator animateAlongsideTransition : ^ ( id < UIViewControllerTransitionCoordinatorContext > _Nonnull context ) {
[ self adjustViewFrameForSafeArea ] ;
} completion : ^ ( id < UIViewControllerTransitionCoordinatorContext > _Nonnull context ) {
} ] ;
}
}
- ( void ) adjustViewFrameForSafeArea {
// This is for adjusting the view frame to account for the notch in iPhone X phones
if ( @ available ( iOS 11 , * ) ) {
RAScreen * screen = ( __bridge RAScreen * ) get_chosen _screen ( ) ;
CGRect screenSize = [ screen bounds ] ;
UIEdgeInsets inset = [ [ UIApplication sharedApplication ] delegate ] . window . safeAreaInsets ;
UIInterfaceOrientation orientation = [ [ UIApplication sharedApplication ] statusBarOrientation ] ;
CGRect newFrame = screenSize ;
if ( orientation = = UIInterfaceOrientationPortrait ) {
newFrame = CGRectMake ( screenSize . origin . x , screenSize . origin . y + inset . top , screenSize . size . width , screenSize . size . height - inset . top ) ;
} else if ( orientation = = UIInterfaceOrientationLandscapeLeft ) {
newFrame = CGRectMake ( screenSize . origin . x , screenSize . origin . y , screenSize . size . width - inset . right , screenSize . size . height ) ;
} else if ( orientation = = UIInterfaceOrientationLandscapeRight ) {
newFrame = CGRectMake ( screenSize . origin . x + inset . left , screenSize . origin . y , screenSize . size . width - inset . left , screenSize . size . height ) ;
}
self . view . frame = newFrame ;
}
}
2015-04-05 05:36:53 +02:00
- ( void ) showPauseIndicator
{
g_pause _indicator _view . alpha = 1.0 f ;
[ NSObject cancelPreviousPerformRequestsWithTarget : g_instance ] ;
[ g_instance performSelector : @ selector ( hidePauseButton ) withObject : g_instance afterDelay : 3.0 f ] ;
}
- ( void ) viewWillLayoutSubviews
{
2015-11-05 22:11:46 +01:00
float width = 0.0 f , height = 0.0 f , tenpctw , tenpcth ;
2015-11-14 22:25:48 +01:00
RAScreen * screen = ( __bridge RAScreen * ) get_chosen _screen ( ) ;
2018-11-04 09:29:40 -07:00
UIInterfaceOrientation orientation = self . interfaceOrientation ;
2015-11-05 22:13:49 +01:00
CGRect screenSize = [ screen bounds ] ;
2015-11-05 22:11:46 +01:00
SEL selector = NSSelectorFromString ( BOXSTRING ( "coordinateSpace" ) ) ;
if ( [ screen respondsToSelector : selector ] )
{
screenSize = [ [ screen coordinateSpace ] bounds ] ;
width = CGRectGetWidth ( screenSize ) ;
height = CGRectGetHeight ( screenSize ) ;
}
else
{
width = ( ( int ) orientation < 3 ) ? CGRectGetWidth ( screenSize ) : CGRectGetHeight ( screenSize ) ;
height = ( ( int ) orientation < 3 ) ? CGRectGetHeight ( screenSize ) : CGRectGetWidth ( screenSize ) ;
}
tenpctw = width / 10.0 f ;
tenpcth = height / 10.0 f ;
2015-04-05 05:36:53 +02:00
g_pause _indicator _view . frame = CGRectMake ( tenpctw * 4.0 f , 0.0 f , tenpctw * 2.0 f , tenpcth ) ;
[ g_pause _indicator _view viewWithTag : 1 ] . frame = CGRectMake ( 0 , 0 , tenpctw * 2.0 f , tenpcth ) ;
2018-11-27 09:29:30 -10:00
[ self adjustViewFrameForSafeArea ] ;
2015-04-05 05:36:53 +02:00
}
2016-01-18 22:15:19 +01:00
# define ALMOST_INVISIBLE ( .021 f )
2015-04-05 05:36:53 +02:00
- ( void ) hidePauseButton
{
[ UIView animateWithDuration : 0.2
animations : ^ { g_pause _indicator _view . alpha = ALMOST_INVISIBLE ; }
completion : ^ ( BOOL finished ) { }
] ;
}
/ * NOTE : This version runs on iOS6 + . * /
- ( NSUInteger ) supportedInterfaceOrientations
{
2016-05-02 14:54:08 +02:00
return ( NSUInteger ) apple_frontend _settings . orientation_flags ;
2015-04-05 05:36:53 +02:00
}
/ * NOTE : This version runs on iOS2 - iOS5 , but not iOS6 + . * /
- ( BOOL ) shouldAutorotateToInterfaceOrientation : ( UIInterfaceOrientation ) interfaceOrientation
{
switch ( interfaceOrientation )
{
case UIInterfaceOrientationPortrait :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskPortrait ) ;
case UIInterfaceOrientationPortraitUpsideDown :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskPortraitUpsideDown ) ;
case UIInterfaceOrientationLandscapeLeft :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskLandscapeLeft ) ;
case UIInterfaceOrientationLandscapeRight :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskLandscapeRight ) ;
default :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskAll ) ;
}
return YES ;
}
# endif
2019-01-26 13:18:32 -10:00
# ifdef HAVE_COCOATOUCH
- ( void ) viewDidAppear : ( BOOL ) animated
{
# if TARGET_OS _IOS
/ * Pause Menus . * /
[ self showPauseIndicator ] ;
if ( @ available ( iOS 11.0 , * ) ) {
[ self setNeedsUpdateOfHomeIndicatorAutoHidden ] ;
}
# elif TARGET_OS _TV
# endif
}
- ( void ) viewWillAppear : ( BOOL ) animated {
[ super viewWillAppear : animated ] ;
# if TARGET_OS _TV
[ [ WebServer sharedInstance ] startUploader ] ;
[ WebServer sharedInstance ] . webUploader . delegate = self ;
# endif
}
# pragma mark GCDWebServerDelegate
- ( void ) webServerDidCompleteBonjourRegistration : ( GCDWebServer * ) server {
NSMutableString * servers = [ [ NSMutableString alloc ] init ] ;
if ( server . serverURL ! = nil ) {
[ servers appendString : [ NSString stringWithFormat : @ "%@" , server . serverURL ] ] ;
}
if ( servers . length > 0 ) {
[ servers appendString : @ "\n\n" ] ;
}
if ( server . bonjourServerURL ! = nil ) {
[ servers appendString : [ NSString stringWithFormat : @ "%@" , server . bonjourServerURL ] ] ;
}
# if TARGET_OS _TV
UIAlertController * alert = [ UIAlertController alertControllerWithTitle : @ "Web Server Started" message : [ NSString stringWithFormat : @ "To transfer files from your computer, go to one of these addresses on your web browser:\n\n%@" , servers ] preferredStyle : UIAlertControllerStyleAlert ] ;
[ alert addAction : [ UIAlertAction actionWithTitle : @ "OK" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * _Nonnull action ) {
} ] ] ;
[ self presentViewController : alert animated : YES completion : ^ {
} ] ;
# elif TARGET_OS _IOS
UIAlertController * alert = [ UIAlertController alertControllerWithTitle : @ "Web Server Started" message : [ NSString stringWithFormat : @ "To transfer ROMs from your computer, go to one of these addresses on your web browser:\n\n%@" , servers ] preferredStyle : UIAlertControllerStyleAlert ] ;
[ alert addAction : [ UIAlertAction actionWithTitle : @ "Stop Server" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * _Nonnull action ) {
[ [ WebServer sharedInstance ] webUploader ] . delegate = nil ;
[ [ WebServer sharedInstance ] stopUploader ] ;
} ] ] ;
[ self presentViewController : alert animated : YES completion : ^ {
} ] ;
# endif
}
# endif // end HAVE_COCOATOUCH
2015-04-05 05:36:53 +02:00
# ifdef HAVE_AVFOUNDATION
2015-11-17 08:01:33 +01:00
# include "../../gfx/common/gl_common.h"
2015-04-05 05:36:53 +02:00
# ifndef GL_BGRA
# define GL_BGRA 0 x80E1
# endif
# ifdef HAVE_OPENGLES
# define RCVOpenGLTextureCacheCreateTextureFromImage CVOpenGLESTextureCacheCreateTextureFromImage
# define RCVOpenGLTextureGetName CVOpenGLESTextureGetName
# define RCVOpenGLTextureCacheFlush CVOpenGLESTextureCacheFlush
# define RCVOpenGLTextureCacheCreate CVOpenGLESTextureCacheCreate
# define RCVOpenGLTextureRef CVOpenGLESTextureRef
# define RCVOpenGLTextureCacheRef CVOpenGLESTextureCacheRef
# if COREVIDEO_USE _EAGLCONTEXT _CLASS _IN _API
# define RCVOpenGLGetCurrentContext ( ) ( CVEAGLContext ) ( g_context )
# else
# define RCVOpenGLGetCurrentContext ( ) ( __bridge void * ) ( g_context )
# endif
# else
# define RCVOpenGLTextureCacheCreateTextureFromImage CVOpenGLTextureCacheCreateTextureFromImage
# define RCVOpenGLTextureGetName CVOpenGLTextureGetName
# define RCVOpenGLTextureCacheFlush CVOpenGLTextureCacheFlush
# define RCVOpenGLTextureCacheCreate CVOpenGLTextureCacheCreate
# define RCVOpenGLTextureRef CVOpenGLTextureRef
# define RCVOpenGLTextureCacheRef CVOpenGLTextureCacheRef
# define RCVOpenGLGetCurrentContext ( ) CGLGetCurrentContext ( ) , CGLGetPixelFormat ( CGLGetCurrentContext ( ) )
# endif
static AVCaptureSession * _session ;
static NSString * _sessionPreset ;
RCVOpenGLTextureCacheRef textureCache ;
GLuint outputTexture ;
static bool newFrame = false ;
2016-01-18 22:10:16 +01:00
static void event_process _camera _frame ( void * pbuf_ptr )
2015-04-05 05:36:53 +02:00
{
CVReturn ret ;
RCVOpenGLTextureRef renderTexture ;
2016-01-18 22:10:16 +01:00
CVPixelBufferRef pixelBuffer = ( CVPixelBufferRef ) pbuf_ptr ;
size_t width = CVPixelBufferGetWidth ( pixelBuffer ) ;
size_t height = CVPixelBufferGetHeight ( pixelBuffer ) ;
2015-04-05 05:36:53 +02:00
CVPixelBufferLockBaseAddress ( pixelBuffer , 0 ) ;
( void ) width ;
( void ) height ;
/ * TODO - rewrite all this .
*
* create a texture from our render target .
* textureCache will be what you previously
* made with RCVOpenGLTextureCacheCreate .
* /
# ifdef HAVE_OPENGLES
ret = RCVOpenGLTextureCacheCreateTextureFromImage ( kCFAllocatorDefault ,
textureCache , pixelBuffer , NULL , GL_TEXTURE _2D ,
GL_RGBA , ( GLsizei ) width , ( GLsizei ) height ,
GL_BGRA , GL_UNSIGNED _BYTE , 0 , & renderTexture ) ;
# else
ret = RCVOpenGLTextureCacheCreateTextureFromImage ( kCFAllocatorDefault ,
textureCache , pixelBuffer , 0 , & renderTexture ) ;
# endif
if ( ! renderTexture || ret )
{
RARCH_ERR ( "[apple_camera]: RCVOpenGLTextureCacheCreateTextureFromImage failed.\n" ) ;
return ;
}
outputTexture = RCVOpenGLTextureGetName ( renderTexture ) ;
2017-11-10 03:55:10 +01:00
gl_bind _texture ( outputTexture , GL_CLAMP _TO _EDGE , GL_LINEAR , GL_LINEAR ) ;
2015-04-05 05:36:53 +02:00
CVPixelBufferUnlockBaseAddress ( pixelBuffer , 0 ) ;
[ [ NSNotificationCenter defaultCenter ] postNotificationName : @ "NewCameraTextureReady" object : nil ] ;
newFrame = true ;
glBindTexture ( GL_TEXTURE _2D , 0 ) ;
RCVOpenGLTextureCacheFlush ( textureCache , 0 ) ;
CFRelease ( renderTexture ) ;
CFRelease ( pixelBuffer ) ;
pixelBuffer = 0 ;
}
- ( void ) captureOutput : ( AVCaptureOutput * ) captureOutput
didOutputSampleBuffer : ( CMSampleBufferRef ) sampleBuffer
fromConnection : ( AVCaptureConnection * ) connection
{
2015-04-12 17:13:14 +02:00
/ * TODO : Don ' t post if event queue is full * /
2015-04-05 05:36:53 +02:00
CVPixelBufferRef pixelBuffer = ( CVPixelBufferRef ) CVPixelBufferRetain ( CMSampleBufferGetImageBuffer ( sampleBuffer ) ) ;
event_process _camera _frame ( pixelBuffer ) ;
}
/ * TODO - add void param to onCameraInit so we can pass g_context . * /
- ( void ) onCameraInit
{
NSError * error ;
AVCaptureVideoDataOutput * dataOutput ;
AVCaptureDeviceInput * input ;
AVCaptureDevice * videoDevice ;
CVReturn ret = RCVOpenGLTextureCacheCreate ( kCFAllocatorDefault , NULL ,
RCVOpenGLGetCurrentContext ( ) , NULL , & textureCache ) ;
( void ) ret ;
2015-04-12 17:13:14 +02:00
/ * Setup Capture Session . * /
2015-04-05 05:36:53 +02:00
_session = [ [ AVCaptureSession alloc ] init ] ;
[ _session beginConfiguration ] ;
2015-04-12 17:13:14 +02:00
/ * TODO : dehardcode this based on device capabilities * /
2015-04-05 05:36:53 +02:00
_sessionPreset = AVCaptureSessionPreset640x480 ;
2015-04-12 17:13:14 +02:00
/ * Set preset session size . * /
2015-04-05 05:36:53 +02:00
[ _session setSessionPreset : _sessionPreset ] ;
2015-04-12 17:13:14 +02:00
/ * Creata a video device and input from that Device . Add the input to the capture session . * /
2015-04-05 05:36:53 +02:00
videoDevice = ( AVCaptureDevice * ) [ AVCaptureDevice defaultDeviceWithMediaType : AVMediaTypeVideo ] ;
if ( videoDevice = = nil )
2016-09-08 11:59:44 +02:00
retro_assert ( 0 ) ;
2015-04-05 05:36:53 +02:00
2015-04-12 17:13:14 +02:00
/ * Add the device to the session . * /
2015-04-05 05:36:53 +02:00
input = ( AVCaptureDeviceInput * ) [ AVCaptureDeviceInput deviceInputWithDevice : videoDevice error : & error ] ;
2015-04-13 16:00:56 +02:00
2015-04-05 05:36:53 +02:00
if ( error )
{
RARCH_ERR ( "video device input %s\n" , error . localizedDescription . UTF8String ) ;
2016-09-08 11:59:44 +02:00
retro_assert ( 0 ) ;
2015-04-05 05:36:53 +02:00
}
[ _session addInput : input ] ;
/ * Create the output for the capture session . * /
dataOutput = ( AVCaptureVideoDataOutput * ) [ [ AVCaptureVideoDataOutput alloc ] init ] ;
[ dataOutput setAlwaysDiscardsLateVideoFrames : NO ] ; / * Probably want to set this to NO when recording . * /
[ dataOutput setVideoSettings : [ NSDictionary dictionaryWithObject : [ NSNumber numberWithInt : kCVPixelFormatType_32BGRA ] forKey : ( id ) kCVPixelBufferPixelFormatTypeKey ] ] ;
/ * Set dispatch to be on the main thread so OpenGL can do things with the data . * /
[ dataOutput setSampleBufferDelegate : self queue : dispatch_get _main _queue ( ) ] ;
[ _session addOutput : dataOutput ] ;
[ _session commitConfiguration ] ;
}
- ( void ) onCameraStart
{
[ _session startRunning ] ;
}
- ( void ) onCameraStop
{
[ _session stopRunning ] ;
}
- ( void ) onCameraFree
{
RCVOpenGLTextureCacheFlush ( textureCache , 0 ) ;
CFRelease ( textureCache ) ;
}
# endif
2015-04-20 11:41:33 +02:00
# ifdef HAVE_CORELOCATION
2015-04-05 05:36:53 +02:00
# include < CoreLocation / CoreLocation . h >
static CLLocationManager * locationManager ;
static bool locationChanged ;
static CLLocationDegrees currentLatitude ;
static CLLocationDegrees currentLongitude ;
static CLLocationAccuracy currentHorizontalAccuracy ;
static CLLocationAccuracy currentVerticalAccuracy ;
- ( bool ) onLocationHasChanged
{
bool hasChanged = locationChanged ;
if ( hasChanged )
locationChanged = false ;
return hasChanged ;
}
- ( void ) locationManager : ( CLLocationManager * ) manager didUpdateToLocation : ( CLLocation * ) newLocation fromLocation : ( CLLocation * ) oldLocation
{
2015-04-13 16:00:56 +02:00
locationChanged = true ;
currentLatitude = newLocation . coordinate . latitude ;
currentLongitude = newLocation . coordinate . longitude ;
2015-04-05 05:36:53 +02:00
currentHorizontalAccuracy = newLocation . horizontalAccuracy ;
2015-04-13 16:00:56 +02:00
currentVerticalAccuracy = newLocation . verticalAccuracy ;
2015-04-05 05:36:53 +02:00
RARCH_LOG ( "didUpdateToLocation - latitude %f, longitude %f\n" , ( float ) currentLatitude , ( float ) currentLongitude ) ;
}
- ( void ) locationManager : ( CLLocationManager * ) manager didUpdateLocations : ( NSArray * ) locations
{
2015-04-13 16:00:56 +02:00
CLLocation * location = ( CLLocation * ) [ locations objectAtIndex : ( [ locations count ] - 1 ) ] ;
2015-04-05 05:36:53 +02:00
2015-04-13 16:00:56 +02:00
locationChanged = true ;
currentLatitude = [ location coordinate ] . latitude ;
currentLongitude = [ location coordinate ] . longitude ;
2015-04-05 05:36:53 +02:00
currentHorizontalAccuracy = location . horizontalAccuracy ;
2015-04-13 16:00:56 +02:00
currentVerticalAccuracy = location . verticalAccuracy ;
2015-04-05 05:36:53 +02:00
RARCH_LOG ( "didUpdateLocations - latitude %f, longitude %f\n" , ( float ) currentLatitude , ( float ) currentLongitude ) ;
}
- ( void ) locationManager : ( CLLocationManager * ) manager didFailWithError : ( NSError * ) error
{
RARCH_LOG ( "didFailWithError - %s\n" , [ [ error localizedDescription ] UTF8String ] ) ;
}
- ( void ) locationManagerDidPauseLocationUpdates : ( CLLocationManager * ) manager
{
RARCH_LOG ( "didPauseLocationUpdates\n" ) ;
}
- ( void ) locationManagerDidResumeLocationUpdates : ( CLLocationManager * ) manager
{
RARCH_LOG ( "didResumeLocationUpdates\n" ) ;
}
- ( void ) onLocationInit
{
2015-04-12 17:13:14 +02:00
/ * Create the location manager
* if this object does not already have one .
* /
2015-04-05 05:36:53 +02:00
if ( locationManager = = nil )
2015-04-13 16:00:56 +02:00
locationManager = [ [ CLLocationManager alloc ] init ] ;
locationManager . delegate = self ;
2015-04-05 05:36:53 +02:00
locationManager . desiredAccuracy = kCLLocationAccuracyBest ;
2015-04-13 16:00:56 +02:00
locationManager . distanceFilter = kCLDistanceFilterNone ;
2015-04-05 05:36:53 +02:00
[ locationManager startUpdatingLocation ] ;
}
# endif
@ end
# ifdef HAVE_AVFOUNDATION
typedef struct apple_camera
{
void * empty ;
} applecamera_t ;
static void * apple_camera _init ( const char * device , uint64_t caps , unsigned width , unsigned height )
{
applecamera_t * applecamera ;
2015-07-12 07:53:46 +02:00
if ( ( caps & ( UINT64_C ( 1 ) < < RETRO_CAMERA _BUFFER _OPENGL _TEXTURE ) ) = = 0 )
2015-04-05 05:36:53 +02:00
{
RARCH_ERR ( "applecamera returns OpenGL texture.\n" ) ;
return NULL ;
}
applecamera = ( applecamera_t * ) calloc ( 1 , sizeof ( applecamera_t ) ) ;
if ( ! applecamera )
return NULL ;
2015-04-20 20:39:39 +02:00
[ [ CocoaView get ] onCameraInit ] ;
2015-04-05 05:36:53 +02:00
return applecamera ;
}
static void apple_camera _free ( void * data )
{
applecamera_t * applecamera = ( applecamera_t * ) data ;
2015-04-20 20:39:39 +02:00
[ [ CocoaView get ] onCameraFree ] ;
2015-04-05 05:36:53 +02:00
if ( applecamera )
free ( applecamera ) ;
applecamera = NULL ;
}
static bool apple_camera _start ( void * data )
{
( void ) data ;
2015-04-20 20:39:39 +02:00
[ [ CocoaView get ] onCameraStart ] ;
2015-04-05 05:36:53 +02:00
return true ;
}
static void apple_camera _stop ( void * data )
{
2015-04-20 20:39:39 +02:00
[ [ CocoaView get ] onCameraStop ] ;
2015-04-05 05:36:53 +02:00
}
static bool apple_camera _poll ( void * data , retro_camera _frame _raw _framebuffer _t frame_raw _cb ,
retro_camera _frame _opengl _texture _t frame_gl _cb )
{
( void ) data ;
( void ) frame_raw _cb ;
if ( frame_gl _cb && newFrame )
{
2015-04-12 17:01:05 +02:00
/ * FIXME : Identity for now .
* Use proper texture matrix as returned by iOS Camera ( if at all ? ) . * /
2015-04-05 05:36:53 +02:00
static const float affine [ ] = {
1.0 f , 0.0 f , 0.0 f ,
0.0 f , 1.0 f , 0.0 f ,
0.0 f , 0.0 f , 1.0 f
} ;
frame_gl _cb ( outputTexture , GL_TEXTURE _2D , affine ) ;
newFrame = false ;
}
return true ;
}
2015-04-20 11:44:28 +02:00
camera_driver _t camera_avfoundation = {
2015-04-05 05:36:53 +02:00
apple_camera _init ,
apple_camera _free ,
apple_camera _start ,
apple_camera _stop ,
apple_camera _poll ,
2015-04-19 20:46:49 +02:00
"avfoundation" ,
2015-04-05 05:36:53 +02:00
} ;
# endif
2015-04-20 11:41:33 +02:00
# ifdef HAVE_CORELOCATION
2015-04-05 05:36:53 +02:00
typedef struct apple_location
{
void * empty ;
} applelocation_t ;
static void * apple_location _init ( void )
{
applelocation_t * applelocation = ( applelocation_t * ) calloc ( 1 , sizeof ( applelocation_t ) ) ;
if ( ! applelocation )
return NULL ;
2015-04-20 20:39:39 +02:00
[ [ CocoaView get ] onLocationInit ] ;
2015-04-05 05:36:53 +02:00
return applelocation ;
}
static void apple_location _set _interval ( void * data , unsigned interval_update _ms , unsigned interval_distance )
{
( void ) data ;
locationManager . distanceFilter = interval_distance ? interval_distance : kCLDistanceFilterNone ;
}
static void apple_location _free ( void * data )
{
applelocation_t * applelocation = ( applelocation_t * ) data ;
/ * TODO - free location manager ? * /
if ( applelocation )
free ( applelocation ) ;
applelocation = NULL ;
}
static bool apple_location _start ( void * data )
{
( void ) data ;
[ locationManager startUpdatingLocation ] ;
return true ;
}
static void apple_location _stop ( void * data )
{
( void ) data ;
[ locationManager stopUpdatingLocation ] ;
}
static bool apple_location _get _position ( void * data , double * lat , double * lon , double * horiz_accuracy ,
double * vert_accuracy )
{
( void ) data ;
2015-04-20 20:39:39 +02:00
bool ret = [ [ CocoaView get ] onLocationHasChanged ] ;
2015-04-05 05:36:53 +02:00
if ( ! ret )
goto fail ;
* lat = currentLatitude ;
* lon = currentLongitude ;
* horiz_accuracy = currentHorizontalAccuracy ;
* vert_accuracy = currentVerticalAccuracy ;
return true ;
fail :
* lat = 0.0 ;
* lon = 0.0 ;
* horiz_accuracy = 0.0 ;
* vert_accuracy = 0.0 ;
return false ;
}
2015-04-20 11:41:33 +02:00
location_driver _t location_corelocation = {
2015-04-05 05:36:53 +02:00
apple_location _init ,
apple_location _free ,
apple_location _start ,
apple_location _stop ,
apple_location _get _position ,
apple_location _set _interval ,
2015-04-20 11:41:33 +02:00
"corelocation" ,
2015-04-05 05:36:53 +02:00
} ;
# endif