diff options
Diffstat (limited to 'platform/darwin/src')
-rw-r--r-- | platform/darwin/src/MGLCircleStyleLayer.h | 32 | ||||
-rw-r--r-- | platform/darwin/src/MGLCircleStyleLayer.mm | 42 | ||||
-rw-r--r-- | platform/darwin/src/MGLStyle.mm | 7 | ||||
-rw-r--r-- | platform/darwin/src/MGLStyleLayer.mm.ejs | 2 | ||||
-rw-r--r-- | platform/darwin/src/NSDate+MGLAdditions.h | 1 | ||||
-rw-r--r-- | platform/darwin/src/NSExpression+MGLAdditions.mm | 2 | ||||
-rw-r--r-- | platform/darwin/src/headless_backend_cgl.cpp | 64 | ||||
-rw-r--r-- | platform/darwin/src/headless_backend_eagl.mm | 44 | ||||
-rw-r--r-- | platform/darwin/src/headless_display_cgl.cpp | 52 | ||||
-rw-r--r-- | platform/darwin/src/image.mm | 22 | ||||
-rw-r--r-- | platform/darwin/src/logging_nslog.mm (renamed from platform/darwin/src/log_nslog.mm) | 2 | ||||
-rw-r--r-- | platform/darwin/src/nsthread.mm | 2 | ||||
-rw-r--r-- | platform/darwin/src/reachability.m | 469 | ||||
-rw-r--r-- | platform/darwin/src/string_nsstring.mm | 2 |
14 files changed, 219 insertions, 524 deletions
diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h index 2d88a664ba..8c95b72123 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.h +++ b/platform/darwin/src/MGLCircleStyleLayer.h @@ -94,6 +94,38 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslateAnchor) { */ @property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleRadius; +#if TARGET_OS_IPHONE +/** + The stroke color of the circle. + + The default value of this property is an `MGLStyleValue` object containing `UIColor.blackColor`. Set this property to `nil` to reset it to the default value. + */ +@property (nonatomic, null_resettable) MGLStyleValue<MGLColor *> *circleStrokeColor; +#else +/** + The stroke color of the circle. + + The default value of this property is an `MGLStyleValue` object containing `NSColor.blackColor`. Set this property to `nil` to reset it to the default value. + */ +@property (nonatomic, null_resettable) MGLStyleValue<MGLColor *> *circleStrokeColor; +#endif + +/** + The opacity of the circle's stroke. + + The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleStrokeOpacity; + +/** + The width of the circle's stroke. Strokes are placed outside of the `circleRadius`. + + This property is measured in points. + + The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleStrokeWidth; + /** The geometry's offset. diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm index 266f2d836e..e8ee2bca7e 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.mm +++ b/platform/darwin/src/MGLCircleStyleLayer.mm @@ -194,6 +194,48 @@ namespace mbgl { return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue); } +- (void)setCircleStrokeColor:(MGLStyleValue<MGLColor *> *)circleStrokeColor { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(circleStrokeColor); + self.rawLayer->setCircleStrokeColor(mbglValue); +} + +- (MGLStyleValue<MGLColor *> *)circleStrokeColor { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getCircleStrokeColor() ?: self.rawLayer->getDefaultCircleStrokeColor(); + return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue); +} + +- (void)setCircleStrokeOpacity:(MGLStyleValue<NSNumber *> *)circleStrokeOpacity { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleStrokeOpacity); + self.rawLayer->setCircleStrokeOpacity(mbglValue); +} + +- (MGLStyleValue<NSNumber *> *)circleStrokeOpacity { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getCircleStrokeOpacity() ?: self.rawLayer->getDefaultCircleStrokeOpacity(); + return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue); +} + +- (void)setCircleStrokeWidth:(MGLStyleValue<NSNumber *> *)circleStrokeWidth { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleStrokeWidth); + self.rawLayer->setCircleStrokeWidth(mbglValue); +} + +- (MGLStyleValue<NSNumber *> *)circleStrokeWidth { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getCircleStrokeWidth() ?: self.rawLayer->getDefaultCircleStrokeWidth(); + return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue); +} + - (void)setCircleTranslate:(MGLStyleValue<NSValue *> *)circleTranslate { MGLAssertStyleLayerIsValid(); diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index c2ae75ed9c..9ea9e760f5 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -36,7 +36,6 @@ #include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/style/sources/vector_source.hpp> #include <mbgl/style/sources/raster_source.hpp> -#include <mbgl/mbgl.hpp> #if TARGET_OS_IPHONE #import "UIImage+MGLAdditions.h" @@ -71,7 +70,11 @@ static_assert(mbgl::util::default_styles::currentVersion == MGLStyleDefaultVersi } \ \ + (NSURL *)name##StyleURL##WithVersion:(NSInteger)version { \ - return [NSURL URLWithString:[@"mapbox://styles/mapbox/" #fileName "-v" stringByAppendingFormat:@"%li", (long)version]]; \ + if (mbgl::util::default_styles::currentVersion == version) { \ + return [NSURL URLWithString:@(mbgl::util::default_styles::name.url)]; \ + } else { \ + return [NSURL URLWithString:[@"mapbox://styles/mapbox/" #fileName "-v" stringByAppendingFormat:@"%li", (long)version]]; \ + } \ } MGL_DEFINE_STYLE(streets, streets) diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs index 6178eaad51..baeed3b882 100644 --- a/platform/darwin/src/MGLStyleLayer.mm.ejs +++ b/platform/darwin/src/MGLStyleLayer.mm.ejs @@ -14,7 +14,7 @@ #import "MGLStyleValue_Private.h" #import "MGL<%- camelize(type) %>StyleLayer.h" -#include <mbgl/style/layers/<%- type %>_layer.hpp> +#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp> <% if (containsEnumerationProperties) { -%> namespace mbgl { diff --git a/platform/darwin/src/NSDate+MGLAdditions.h b/platform/darwin/src/NSDate+MGLAdditions.h index a116ef32de..918aae233f 100644 --- a/platform/darwin/src/NSDate+MGLAdditions.h +++ b/platform/darwin/src/NSDate+MGLAdditions.h @@ -1,6 +1,5 @@ #import <Foundation/Foundation.h> -#include <mbgl/mbgl.hpp> #include <mbgl/util/chrono.hpp> @interface NSDate (MGLAdditions) diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 392a6d7f5b..25a2945cfb 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -72,7 +72,7 @@ NSNumber *number = (NSNumber *)value; if ((strcmp([number objCType], @encode(char)) == 0) || (strcmp([number objCType], @encode(BOOL)) == 0)) { - return mbglValue.get<bool>(); + return uint64_t(mbglValue.get<bool>()); } else if ( strcmp([number objCType], @encode(double)) == 0 || strcmp([number objCType], @encode(float)) == 0) { return mbglValue.get<double>(); diff --git a/platform/darwin/src/headless_backend_cgl.cpp b/platform/darwin/src/headless_backend_cgl.cpp index 4ca567f55c..7069738fb1 100644 --- a/platform/darwin/src/headless_backend_cgl.cpp +++ b/platform/darwin/src/headless_backend_cgl.cpp @@ -1,6 +1,7 @@ -#include <mbgl/platform/default/headless_backend.hpp> -#include <mbgl/platform/default/headless_display.hpp> +#include <mbgl/gl/headless_backend.hpp> +#include <mbgl/gl/headless_display.hpp> +#include <OpenGL/OpenGL.h> #include <CoreFoundation/CoreFoundation.h> #include <string> @@ -8,6 +9,33 @@ namespace mbgl { +struct CGLImpl : public HeadlessBackend::Impl { + CGLImpl(CGLContextObj glContext_) : glContext(glContext_) { + } + + ~CGLImpl() { + CGLDestroyContext(glContext); + } + + void activateContext() final { + CGLError error = CGLSetCurrentContext(glContext); + if (error != kCGLNoError) { + throw std::runtime_error(std::string("Switching OpenGL context failed:") + + CGLErrorString(error) + "\n"); + } + } + + void deactivateContext() final { + CGLError error = CGLSetCurrentContext(nullptr); + if (error != kCGLNoError) { + throw std::runtime_error(std::string("Removing OpenGL context failed:") + + CGLErrorString(error) + "\n"); + } + } + + CGLContextObj glContext = nullptr; +}; + gl::glProc HeadlessBackend::initializeExtension(const char* name) { static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); if (!framework) { @@ -21,8 +49,18 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) { return reinterpret_cast<gl::glProc>(symbol); } +bool HeadlessBackend::hasDisplay() { + if (!display) { + display.reset(new HeadlessDisplay); + } + return bool(display); +} + void HeadlessBackend::createContext() { - CGLError error = CGLCreateContext(display->pixelFormat, nullptr, &glContext); + assert(!hasContext()); + + CGLContextObj glContext = nullptr; + CGLError error = CGLCreateContext(display->attribute<CGLPixelFormatObj>(), nullptr, &glContext); if (error != kCGLNoError) { throw std::runtime_error(std::string("Error creating GL context object:") + CGLErrorString(error) + "\n"); @@ -33,26 +71,8 @@ void HeadlessBackend::createContext() { throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") + CGLErrorString(error) + "\n"); } -} - -void HeadlessBackend::destroyContext() { - CGLDestroyContext(glContext); -} - -void HeadlessBackend::activateContext() { - CGLError error = CGLSetCurrentContext(glContext); - if (error != kCGLNoError) { - throw std::runtime_error(std::string("Switching OpenGL context failed:") + - CGLErrorString(error) + "\n"); - } -} -void HeadlessBackend::deactivateContext() { - CGLError error = CGLSetCurrentContext(nullptr); - if (error != kCGLNoError) { - throw std::runtime_error(std::string("Removing OpenGL context failed:") + - CGLErrorString(error) + "\n"); - } + impl.reset(new CGLImpl(glContext)); } } // namespace mbgl diff --git a/platform/darwin/src/headless_backend_eagl.mm b/platform/darwin/src/headless_backend_eagl.mm index 0a1ae706b8..bd4a202ec5 100644 --- a/platform/darwin/src/headless_backend_eagl.mm +++ b/platform/darwin/src/headless_backend_eagl.mm @@ -1,4 +1,4 @@ -#include <mbgl/platform/default/headless_backend.hpp> +#include <mbgl/gl/headless_backend.hpp> #include <mbgl/gl/extension.hpp> @@ -8,6 +8,27 @@ namespace mbgl { +struct EAGLImpl : public HeadlessBackend::Impl { + EAGLImpl(EAGLContext* glContext_) : glContext(glContext_) { + [reinterpret_cast<EAGLContext*>(glContext) retain]; + reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES; + } + + ~EAGLImpl() { + [glContext release]; + } + + void activateContext() { + [EAGLContext setCurrentContext:glContext]; + } + + void deactivateContext() { + [EAGLContext setCurrentContext:nil]; + } + + EAGLContext* glContext = nullptr; +}; + gl::glProc HeadlessBackend::initializeExtension(const char* name) { static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles")); if (!framework) { @@ -21,26 +42,17 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) { return reinterpret_cast<gl::glProc>(symbol); } +bool HeadlessBackend::hasDisplay() { + return true; +} + void HeadlessBackend::createContext() { - glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + EAGLContext* glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; if (glContext == nil) { throw std::runtime_error("Error creating GL context object"); } - [reinterpret_cast<EAGLContext*>(glContext) retain]; - reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES; -} - -void HeadlessBackend::destroyContext() { - [reinterpret_cast<EAGLContext*>(glContext) release]; - glContext = nil; -} - -void HeadlessBackend::activateContext() { - [EAGLContext setCurrentContext:reinterpret_cast<EAGLContext*>(glContext)]; -} -void HeadlessBackend::deactivateContext() { - [EAGLContext setCurrentContext:nil]; + impl.reset(new EAGLImpl(glContext)); } } // namespace mbgl diff --git a/platform/darwin/src/headless_display_cgl.cpp b/platform/darwin/src/headless_display_cgl.cpp new file mode 100644 index 0000000000..90d187d3db --- /dev/null +++ b/platform/darwin/src/headless_display_cgl.cpp @@ -0,0 +1,52 @@ +#include <mbgl/gl/headless_display.hpp> + +#include <OpenGL/OpenGL.h> + +#include <stdexcept> +#include <string> + +namespace mbgl { + +class HeadlessDisplay::Impl { +public: + Impl(); + ~Impl(); + CGLPixelFormatObj pixelFormat = nullptr; +}; + +HeadlessDisplay::Impl::Impl() { + // TODO: test if OpenGL 4.1 with GL_ARB_ES2_compatibility is supported + // If it is, use kCGLOGLPVersion_3_2_Core and enable that extension. + CGLPixelFormatAttribute attributes[] = { + kCGLPFAOpenGLProfile, + static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_Legacy), + static_cast<CGLPixelFormatAttribute>(0) + }; + + GLint num; + CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num); + if (error != kCGLNoError) { + throw std::runtime_error(std::string("Error choosing pixel format:") + CGLErrorString(error) + "\n"); + } + if (num <= 0) { + throw std::runtime_error("No pixel formats found."); + } +} + +HeadlessDisplay::Impl::~Impl() { + CGLDestroyPixelFormat(pixelFormat); +} + +template <> +CGLPixelFormatObj HeadlessDisplay::attribute() const { + return impl->pixelFormat; +} + +HeadlessDisplay::HeadlessDisplay() + : impl(std::make_unique<Impl>()) { +} + +HeadlessDisplay::~HeadlessDisplay() { +} + +} // namespace mbgl diff --git a/platform/darwin/src/image.mm b/platform/darwin/src/image.mm index 066535a58c..3a707d4a36 100644 --- a/platform/darwin/src/image.mm +++ b/platform/darwin/src/image.mm @@ -11,7 +11,7 @@ namespace mbgl { std::string encodePNG(const PremultipliedImage& src) { - CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, src.data.get(), src.size(), NULL); + CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, src.data.get(), src.bytes(), NULL); if (!provider) { return ""; } @@ -22,9 +22,10 @@ std::string encodePNG(const PremultipliedImage& src) { return ""; } - CGImageRef image = CGImageCreate(src.width, src.height, 8, 32, 4 * src.width, color_space, - kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast, provider, NULL, false, - kCGRenderingIntentDefault); + CGImageRef image = + CGImageCreate(src.size.width, src.size.height, 8, 32, 4 * src.size.width, color_space, + kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast, provider, NULL, + false, kCGRenderingIntentDefault); if (!image) { CGColorSpaceRelease(color_space); CGDataProviderRelease(provider); @@ -92,11 +93,12 @@ PremultipliedImage decodeImage(const std::string &source_data) { throw std::runtime_error("CGColorSpaceCreateDeviceRGB failed"); } - PremultipliedImage result{ static_cast<uint16_t>(CGImageGetWidth(image)), - static_cast<uint16_t>(CGImageGetHeight(image)) }; + PremultipliedImage result({ static_cast<uint32_t>(CGImageGetWidth(image)), + static_cast<uint32_t>(CGImageGetHeight(image)) }); - CGContextRef context = CGBitmapContextCreate(result.data.get(), result.width, result.height, 8, result.stride(), - color_space, kCGImageAlphaPremultipliedLast); + CGContextRef context = + CGBitmapContextCreate(result.data.get(), result.size.width, result.size.height, 8, + result.stride(), color_space, kCGImageAlphaPremultipliedLast); if (!context) { CGColorSpaceRelease(color_space); CGImageRelease(image); @@ -107,7 +109,9 @@ PremultipliedImage decodeImage(const std::string &source_data) { CGContextSetBlendMode(context, kCGBlendModeCopy); - CGRect rect = {{ 0, 0 }, { static_cast<CGFloat>(result.width), static_cast<CGFloat>(result.height) }}; + CGRect rect = { { 0, 0 }, + { static_cast<CGFloat>(result.size.width), + static_cast<CGFloat>(result.size.height) } }; CGContextDrawImage(context, rect, image); CGContextRelease(context); diff --git a/platform/darwin/src/log_nslog.mm b/platform/darwin/src/logging_nslog.mm index 49583ae3c4..dd428f56b1 100644 --- a/platform/darwin/src/log_nslog.mm +++ b/platform/darwin/src/logging_nslog.mm @@ -1,4 +1,4 @@ -#include <mbgl/platform/log.hpp> +#include <mbgl/util/logging.hpp> #include <mbgl/util/enum.hpp> #import <Foundation/Foundation.h> diff --git a/platform/darwin/src/nsthread.mm b/platform/darwin/src/nsthread.mm index eee6d6991b..6caa1be43e 100644 --- a/platform/darwin/src/nsthread.mm +++ b/platform/darwin/src/nsthread.mm @@ -1,6 +1,6 @@ #import <Foundation/Foundation.h> -#include <mbgl/platform/platform.hpp> +#include <mbgl/util/platform.hpp> #include <pthread.h> diff --git a/platform/darwin/src/reachability.m b/platform/darwin/src/reachability.m deleted file mode 100644 index 8abcf5ae6d..0000000000 --- a/platform/darwin/src/reachability.m +++ /dev/null @@ -1,469 +0,0 @@ -/* - Copyright (c) 2011, Tony Million. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -#import <mbgl/platform/darwin/reachability.h> - -#import <sys/socket.h> -#import <netinet/in.h> -#import <netinet6/in6.h> -#import <arpa/inet.h> -#import <ifaddrs.h> -#import <netdb.h> - - -NSString *const kMGLReachabilityChangedNotification = @"kMGLReachabilityChangedNotification"; - - -@interface MGLReachability () - -@property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef; -@property (nonatomic, strong) dispatch_queue_t reachabilitySerialQueue; -@property (nonatomic, strong) id reachabilityObject; - --(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags; --(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags; - -@end - - -static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags) -{ - return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c", -#if TARGET_OS_IPHONE - (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', -#else - 'X', -#endif - (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', - (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', - (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', - (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', - (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', - (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', - (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', - (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-']; -} - -// Start listening for reachability notifications on the current run loop -static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) -{ -#pragma unused (target) - - MGLReachability *reachability = ((__bridge MGLReachability*)info); - - // We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool, - // but what the heck eh? - @autoreleasepool - { - [reachability reachabilityChanged:flags]; - } -} - - -@implementation MGLReachability - -#pragma mark - Class Constructor Methods - -+(instancetype)reachabilityWithHostName:(NSString*)hostname -{ - return [MGLReachability reachabilityWithHostname:hostname]; -} - -+(instancetype)reachabilityWithHostname:(NSString*)hostname -{ - SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]); - if (ref) - { - id reachability = [[self alloc] initWithReachabilityRef:ref]; - - return reachability; - } - - return nil; -} - -+(instancetype)reachabilityWithAddress:(void *)hostAddress -{ - SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); - if (ref) - { - id reachability = [[self alloc] initWithReachabilityRef:ref]; - - return reachability; - } - - return nil; -} - -+(instancetype)reachabilityForInternetConnection -{ - struct sockaddr_in zeroAddress; - bzero(&zeroAddress, sizeof(zeroAddress)); - zeroAddress.sin_len = sizeof(zeroAddress); - zeroAddress.sin_family = AF_INET; - - return [self reachabilityWithAddress:&zeroAddress]; -} - -+(instancetype)reachabilityForLocalWiFi -{ - struct sockaddr_in localWifiAddress; - bzero(&localWifiAddress, sizeof(localWifiAddress)); - localWifiAddress.sin_len = sizeof(localWifiAddress); - localWifiAddress.sin_family = AF_INET; - // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0 - localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); - - return [self reachabilityWithAddress:&localWifiAddress]; -} - - -// Initialization methods - --(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref -{ - self = [super init]; - if (self != nil) - { - self.reachableOnWWAN = YES; - self.reachabilityRef = ref; - - // We need to create a serial queue. - // We allocate this once for the lifetime of the notifier. - - self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL); - } - - return self; -} - --(void)dealloc -{ - [self stopNotifier]; - - if(self.reachabilityRef) - { - CFRelease(self.reachabilityRef); - self.reachabilityRef = nil; - } - - self.reachableBlock = nil; - self.unreachableBlock = nil; - self.reachabilitySerialQueue = nil; -} - -#pragma mark - Notifier Methods - -// Notifier -// NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD -// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS. -// INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want) - --(BOOL)startNotifier -{ - // allow start notifier to be called multiple times - if(self.reachabilityObject && (self.reachabilityObject == self)) - { - return YES; - } - - - SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL }; - context.info = (__bridge void *)self; - - if(SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context)) - { - // Set it as our reachability queue, which will retain the queue - if(SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue)) - { - // this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves - // woah - self.reachabilityObject = self; - return YES; - } - else - { -#ifdef DEBUG - NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError())); -#endif - - // UH OH - FAILURE - stop any callbacks! - SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); - } - } - else - { -#ifdef DEBUG - NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError())); -#endif - } - - // if we get here we fail at the internet - self.reachabilityObject = nil; - return NO; -} - --(void)stopNotifier -{ - // First stop, any callbacks! - SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); - - // Unregister target from the GCD serial dispatch queue. - SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL); - - self.reachabilityObject = nil; -} - -#pragma mark - reachability tests - -// This is for the case where you flick the airplane mode; -// you end up getting something like this: -//Reachability: WR ct----- -//Reachability: -- ------- -//Reachability: WR ct----- -//Reachability: -- ------- -// We treat this as 4 UNREACHABLE triggers - really apple should do better than this - -#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) - --(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags -{ - BOOL connectionUP = YES; - - if(!(flags & kSCNetworkReachabilityFlagsReachable)) - connectionUP = NO; - - if( (flags & testcase) == testcase ) - connectionUP = NO; - -#if TARGET_OS_IPHONE - if(flags & kSCNetworkReachabilityFlagsIsWWAN) - { - // We're on 3G. - if(!self.reachableOnWWAN) - { - // We don't want to connect when on 3G. - connectionUP = NO; - } - } -#endif - - return connectionUP; -} - --(BOOL)isReachable -{ - SCNetworkReachabilityFlags flags; - - if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) - return NO; - - return [self isReachableWithFlags:flags]; -} - --(BOOL)isReachableViaWWAN -{ -#if TARGET_OS_IPHONE - - SCNetworkReachabilityFlags flags = 0; - - if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) - { - // Check we're REACHABLE - if(flags & kSCNetworkReachabilityFlagsReachable) - { - // Now, check we're on WWAN - if(flags & kSCNetworkReachabilityFlagsIsWWAN) - { - return YES; - } - } - } -#endif - - return NO; -} - --(BOOL)isReachableViaWiFi -{ - SCNetworkReachabilityFlags flags = 0; - - if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) - { - // Check we're reachable - if((flags & kSCNetworkReachabilityFlagsReachable)) - { -#if TARGET_OS_IPHONE - // Check we're NOT on WWAN - if((flags & kSCNetworkReachabilityFlagsIsWWAN)) - { - return NO; - } -#endif - return YES; - } - } - - return NO; -} - - -// WWAN may be available, but not active until a connection has been established. -// WiFi may require a connection for VPN on Demand. --(BOOL)isConnectionRequired -{ - return [self connectionRequired]; -} - --(BOOL)connectionRequired -{ - SCNetworkReachabilityFlags flags; - - if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) - { - return (flags & kSCNetworkReachabilityFlagsConnectionRequired); - } - - return NO; -} - -// Dynamic, on demand connection? --(BOOL)isConnectionOnDemand -{ - SCNetworkReachabilityFlags flags; - - if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) - { - return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && - (flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand))); - } - - return NO; -} - -// Is user intervention required? --(BOOL)isInterventionRequired -{ - SCNetworkReachabilityFlags flags; - - if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) - { - return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && - (flags & kSCNetworkReachabilityFlagsInterventionRequired)); - } - - return NO; -} - - -#pragma mark - reachability status stuff - --(NetworkStatus)currentReachabilityStatus -{ - if([self isReachable]) - { - if([self isReachableViaWiFi]) - return ReachableViaWiFi; - -#if TARGET_OS_IPHONE - return ReachableViaWWAN; -#endif - } - - return NotReachable; -} - --(SCNetworkReachabilityFlags)reachabilityFlags -{ - SCNetworkReachabilityFlags flags = 0; - - if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) - { - return flags; - } - - return 0; -} - --(NSString*)currentReachabilityString -{ - NetworkStatus temp = [self currentReachabilityStatus]; - - if(temp == ReachableViaWWAN) - { - // Updated for the fact that we have CDMA phones now! - return NSLocalizedString(@"Cellular", @""); - } - if (temp == ReachableViaWiFi) - { - return NSLocalizedString(@"WiFi", @""); - } - - return NSLocalizedString(@"No Connection", @""); -} - --(NSString*)currentReachabilityFlags -{ - return reachabilityFlags([self reachabilityFlags]); -} - -#pragma mark - Callback function calls this method - --(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags -{ - if([self isReachableWithFlags:flags]) - { - if(self.reachableBlock) - { - self.reachableBlock(self); - } - } - else - { - if(self.unreachableBlock) - { - self.unreachableBlock(self); - } - } - - // this makes sure the change notification happens on the MAIN THREAD - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:kMGLReachabilityChangedNotification - object:self]; - }); -} - -#pragma mark - Debug Description - -- (NSString *) description -{ - NSString *description = [NSString stringWithFormat:@"<%@: %#x (%@)>", - NSStringFromClass([self class]), (unsigned int) self, [self currentReachabilityFlags]]; - return description; -} - -@end diff --git a/platform/darwin/src/string_nsstring.mm b/platform/darwin/src/string_nsstring.mm index 9bf199afc0..08f9aeccef 100644 --- a/platform/darwin/src/string_nsstring.mm +++ b/platform/darwin/src/string_nsstring.mm @@ -1,6 +1,6 @@ #import <Foundation/Foundation.h> -#include <mbgl/platform/platform.hpp> +#include <mbgl/util/platform.hpp> namespace mbgl { namespace platform { |