2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #define BOOL XBMC_BOOL
23 #include "Application.h"
25 #include "GUIUserMessages.h"
26 #include "utils/log.h"
30 #if defined(TARGET_DARWIN)
31 #if defined(TARGET_DARWIN_IOS)
32 #import <Foundation/Foundation.h>
33 #import <UIKit/UIKit.h>
34 #import <mach/mach_host.h>
35 #import <sys/sysctl.h>
37 #import <Cocoa/Cocoa.h>
38 #import <CoreFoundation/CoreFoundation.h>
39 #import <IOKit/ps/IOPowerSources.h>
40 #import <IOKit/ps/IOPSKeys.h>
44 #import "DarwinUtils.h"
64 iPhone4, //from here on list devices with retina support (e.x. mainscreen scale == 2.0)
83 // platform strings are based on http://theiphonewiki.com/wiki/Models
84 enum iosPlatform getIosPlatform()
86 #if defined(TARGET_DARWIN_IOS)
87 // Gets a string with the device model
89 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
90 char *machine = new char[size];
91 sysctlbyname("hw.machine", machine, &size, NULL, 0);
92 NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
95 if ([platform isEqualToString:@"iPhone1,1"]) return iPhone2G;
96 if ([platform isEqualToString:@"iPhone1,2"]) return iPhone3G;
97 if ([platform isEqualToString:@"iPhone2,1"]) return iPhone3GS;
98 if ([platform isEqualToString:@"iPhone3,1"]) return iPhone4;
99 if ([platform isEqualToString:@"iPhone3,2"]) return iPhone4;
100 if ([platform isEqualToString:@"iPhone3,3"]) return iPhone4CDMA;
101 if ([platform isEqualToString:@"iPhone4,1"]) return iPhone4S;
102 if ([platform isEqualToString:@"iPhone5,1"]) return iPhone5;
103 if ([platform isEqualToString:@"iPhone5,2"]) return iPhone5GSMCDMA;
104 if ([platform isEqualToString:@"iPhone5,3"]) return iPhone5CGSM;
105 if ([platform isEqualToString:@"iPhone5,4"]) return iPhone5CGlobal;
106 if ([platform isEqualToString:@"iPhone6,1"]) return iPhone5SGSM;
107 if ([platform isEqualToString:@"iPhone6,2"]) return iPhone5SGlobal;
109 if ([platform isEqualToString:@"iPod1,1"]) return iPodTouch1G;
110 if ([platform isEqualToString:@"iPod2,1"]) return iPodTouch2G;
111 if ([platform isEqualToString:@"iPod3,1"]) return iPodTouch3G;
112 if ([platform isEqualToString:@"iPod4,1"]) return iPodTouch4G;
113 if ([platform isEqualToString:@"iPod5,1"]) return iPodTouch5G;
115 if ([platform isEqualToString:@"iPad1,1"]) return iPad;
116 if ([platform isEqualToString:@"iPad1,2"]) return iPad;
117 if ([platform isEqualToString:@"iPad2,1"]) return iPad2WIFI;
118 if ([platform isEqualToString:@"iPad2,2"]) return iPad2;
119 if ([platform isEqualToString:@"iPad2,3"]) return iPad2CDMA;
120 if ([platform isEqualToString:@"iPad2,4"]) return iPad2;
121 if ([platform isEqualToString:@"iPad2,5"]) return iPadMiniWIFI;
122 if ([platform isEqualToString:@"iPad2,6"]) return iPadMini;
123 if ([platform isEqualToString:@"iPad2,7"]) return iPadMiniGSMCDMA;
124 if ([platform isEqualToString:@"iPad3,1"]) return iPad3WIFI;
125 if ([platform isEqualToString:@"iPad3,2"]) return iPad3GSMCDMA;
126 if ([platform isEqualToString:@"iPad3,3"]) return iPad3;
127 if ([platform isEqualToString:@"iPad3,4"]) return iPad4WIFI;
128 if ([platform isEqualToString:@"iPad3,5"]) return iPad4;
129 if ([platform isEqualToString:@"iPad3,6"]) return iPad4GSMCDMA;
130 if ([platform isEqualToString:@"AppleTV2,1"]) return AppleTV2;
132 return iDeviceUnknown;
135 bool DarwinIsAppleTV2(void)
137 static enum iosPlatform platform = iDeviceUnknown;
138 #if defined(TARGET_DARWIN_IOS)
139 if( platform == iDeviceUnknown )
141 platform = getIosPlatform();
144 return (platform == AppleTV2);
147 bool DarwinHasRetina(void)
149 static enum iosPlatform platform = iDeviceUnknown;
151 #if defined(TARGET_DARWIN_IOS)
152 if( platform == iDeviceUnknown )
154 platform = getIosPlatform();
157 return (platform >= iPhone4);
160 const char *GetDarwinOSReleaseString(void)
162 static std::string osreleaseStr;
163 if (osreleaseStr.empty())
166 sysctlbyname("kern.osrelease", NULL, &size, NULL, 0);
167 char *osrelease = new char[size];
168 sysctlbyname("kern.osrelease", osrelease, &size, NULL, 0);
169 osreleaseStr = osrelease;
172 return osreleaseStr.c_str();
175 const char *GetDarwinVersionString(void)
177 return [[[NSProcessInfo processInfo] operatingSystemVersionString] UTF8String];
180 float GetIOSVersion(void)
184 #if defined(TARGET_DARWIN_IOS)
185 version = [[[UIDevice currentDevice] systemVersion] floatValue];
193 int GetDarwinFrameworkPath(bool forPython, char* path, uint32_t *pathsize)
196 // see if we can figure out who we are
202 // a) XBMC frappliance running under ATV2
203 Class XBMCfrapp = NSClassFromString(@"XBMCATV2Detector");
204 if (XBMCfrapp != NULL)
206 pathname = [[NSBundle bundleForClass:XBMCfrapp] pathForResource:@"Frameworks" ofType:@""];
207 strcpy(path, [pathname UTF8String]);
208 *pathsize = strlen(path);
209 //CLog::Log(LOGDEBUG, "DarwinFrameworkPath(a) -> %s", path);
213 // b) XBMC application running under IOS
214 pathname = [[NSBundle mainBundle] executablePath];
215 if (pathname && strstr([pathname UTF8String], "XBMC.app/XBMC"))
217 strcpy(path, [pathname UTF8String]);
218 // Move backwards to last "/"
219 for (int n=strlen(path)-1; path[n] != '/'; n--)
221 strcat(path, "Frameworks");
222 *pathsize = strlen(path);
223 //CLog::Log(LOGDEBUG, "DarwinFrameworkPath(c) -> %s", path);
227 // d) XBMC application running under OSX
228 pathname = [[NSBundle mainBundle] privateFrameworksPath];
229 if (pathname && strstr([pathname UTF8String], "Contents"))
231 // check for 'Contents' if we are running as real xbmc.app
232 strcpy(path, [pathname UTF8String]);
233 *pathsize = strlen(path);
234 //CLog::Log(LOGDEBUG, "DarwinFrameworkPath(d) -> %s", path);
238 // e) XBMC OSX binary running under xcode or command-line
239 // but only if it's not for python. In this case, let python
240 // use it's internal compiled paths.
243 strcpy(path, PREFIX_USR_PATH);
244 strcat(path, "/lib");
245 *pathsize = strlen(path);
246 //CLog::Log(LOGDEBUG, "DarwinFrameworkPath(e) -> %s", path);
253 int GetDarwinExecutablePath(char* path, uint32_t *pathsize)
256 // see if we can figure out who we are
259 // a) XBMC frappliance running under ATV2
260 Class XBMCfrapp = NSClassFromString(@"XBMCATV2Detector");
261 if (XBMCfrapp != NULL)
263 pathname = [[NSBundle bundleForClass:XBMCfrapp] pathForResource:@"XBMC" ofType:@""];
264 strcpy(path, [pathname UTF8String]);
265 *pathsize = strlen(path);
266 //CLog::Log(LOGDEBUG, "DarwinExecutablePath(a) -> %s", path);
270 // b) XBMC application running under IOS
271 // c) XBMC application running under OSX
272 pathname = [[NSBundle mainBundle] executablePath];
273 strcpy(path, [pathname UTF8String]);
274 *pathsize = strlen(path);
275 //CLog::Log(LOGDEBUG, "DarwinExecutablePath(b/c) -> %s", path);
280 const char* DarwinGetXbmcRootFolder(void)
282 static std::string rootFolder = "";
283 if ( rootFolder.length() == 0)
285 if (DarwinIsIosSandboxed())
287 // when we are sandbox make documents our root
288 // so that user can access everything he needs
289 // via itunes sharing
290 rootFolder = "Documents";
294 rootFolder = "Library/Preferences";
297 return rootFolder.c_str();
300 bool DarwinIsIosSandboxed(void)
305 uint32_t path_size = 2*MAXPATHLEN;
306 char given_path[2*MAXPATHLEN];
309 memset(given_path, 0x0, path_size);
310 /* Get Application directory */
311 result = GetDarwinExecutablePath(given_path, &path_size);
314 // we re sandboxed if we are installed in /var/mobile/Applications
315 if (strlen("/var/mobile/Applications/") < path_size &&
316 strncmp(given_path, "/var/mobile/Applications/", strlen("/var/mobile/Applications/")) == 0)
325 bool DarwinHasVideoToolboxDecoder(void)
327 static int DecoderAvailable = -1;
329 if (DecoderAvailable == -1)
331 Class XBMCfrapp = NSClassFromString(@"XBMCATV2Detector");
332 if (XBMCfrapp != NULL)
334 // atv2 has seatbelt profile key removed so nothing to do here
335 DecoderAvailable = 1;
339 /* When XBMC is started from a sandbox directory we have to check the sysctl values */
340 if (DarwinIsIosSandboxed())
342 uint64_t proc_enforce = 0;
343 uint64_t vnode_enforce = 0;
344 size_t size = sizeof(vnode_enforce);
346 sysctlbyname("security.mac.proc_enforce", &proc_enforce, &size, NULL, 0);
347 sysctlbyname("security.mac.vnode_enforce", &vnode_enforce, &size, NULL, 0);
349 if (vnode_enforce && proc_enforce)
351 DecoderAvailable = 1;
352 CLog::Log(LOGINFO, "VideoToolBox decoder not available. Use : sysctl -w security.mac.proc_enforce=0; sysctl -w security.mac.vnode_enforce=0\n");
356 DecoderAvailable = 1;
357 CLog::Log(LOGINFO, "VideoToolBox decoder available\n");
362 DecoderAvailable = 1;
367 return (DecoderAvailable == 1);
370 int DarwinBatteryLevel(void)
372 float batteryLevel = 0;
373 #if defined(TARGET_DARWIN_IOS)
374 if(!DarwinIsAppleTV2())
375 batteryLevel = [[UIDevice currentDevice] batteryLevel];
377 CFTypeRef powerSourceInfo = IOPSCopyPowerSourcesInfo();
378 CFArrayRef powerSources = IOPSCopyPowerSourcesList(powerSourceInfo);
380 CFDictionaryRef powerSource = NULL;
381 const void *powerSourceVal;
383 for (int i = 0 ; i < CFArrayGetCount(powerSources) ; i++)
385 powerSource = IOPSGetPowerSourceDescription(powerSourceInfo, CFArrayGetValueAtIndex(powerSources, i));
386 if (!powerSource) break;
388 powerSourceVal = (CFStringRef)CFDictionaryGetValue(powerSource, CFSTR(kIOPSNameKey));
393 powerSourceVal = CFDictionaryGetValue(powerSource, CFSTR(kIOPSCurrentCapacityKey));
394 CFNumberGetValue((CFNumberRef)powerSourceVal, kCFNumberSInt32Type, &curLevel);
396 powerSourceVal = CFDictionaryGetValue(powerSource, CFSTR(kIOPSMaxCapacityKey));
397 CFNumberGetValue((CFNumberRef)powerSourceVal, kCFNumberSInt32Type, &maxLevel);
399 batteryLevel = (double)curLevel/(double)maxLevel;
402 return batteryLevel * 100;
405 void DarwinSetScheduling(int message)
408 struct sched_param param;
409 pthread_t this_pthread_self = pthread_self();
411 int32_t result = pthread_getschedparam(this_pthread_self, &policy, ¶m );
413 policy = SCHED_OTHER;
414 thread_extended_policy_data_t theFixedPolicy={true};
416 if (message == GUI_MSG_PLAYBACK_STARTED && g_application.m_pPlayer->IsPlayingVideo())
419 theFixedPolicy.timeshare = false;
422 result = thread_policy_set(pthread_mach_thread_np(this_pthread_self),
423 THREAD_EXTENDED_POLICY,
424 (thread_policy_t)&theFixedPolicy,
425 THREAD_EXTENDED_POLICY_COUNT);
427 result = pthread_setschedparam(this_pthread_self, policy, ¶m );
430 bool DarwinCFStringRefToStringWithEncoding(CFStringRef source, std::string &destination, CFStringEncoding encoding)
432 const char *cstr = CFStringGetCStringPtr(source, encoding);
435 CFIndex strLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(source) + 1,
437 char *allocStr = (char*)malloc(strLen);
442 if(!CFStringGetCString(source, allocStr, strLen, encoding))
444 free((void*)allocStr);
448 destination = allocStr;
449 free((void*)allocStr);
458 bool DarwinCFStringRefToString(CFStringRef source, std::string &destination)
460 return DarwinCFStringRefToStringWithEncoding(source, destination, CFStringGetSystemEncoding());
463 bool DarwinCFStringRefToUTF8String(CFStringRef source, std::string &destination)
465 return DarwinCFStringRefToStringWithEncoding(source, destination, kCFStringEncodingUTF8);