| 1 | // |
|---|
| 2 | // SUSystemProfiler.m |
|---|
| 3 | // Sparkle |
|---|
| 4 | // |
|---|
| 5 | // Created by Andy Matuschak on 12/22/07. |
|---|
| 6 | // Copyright 2007 Andy Matuschak. All rights reserved. |
|---|
| 7 | // Adapted from Sparkle+, by Tom Harrington. |
|---|
| 8 | // |
|---|
| 9 | |
|---|
| 10 | #import "SUSystemProfiler.h" |
|---|
| 11 | |
|---|
| 12 | #import "SUHost.h" |
|---|
| 13 | #import <sys/sysctl.h> |
|---|
| 14 | |
|---|
| 15 | @implementation SUSystemProfiler |
|---|
| 16 | + (SUSystemProfiler *)sharedSystemProfiler |
|---|
| 17 | { |
|---|
| 18 | static SUSystemProfiler *sharedSystemProfiler = nil; |
|---|
| 19 | if (!sharedSystemProfiler) |
|---|
| 20 | sharedSystemProfiler = [[self alloc] init]; |
|---|
| 21 | return sharedSystemProfiler; |
|---|
| 22 | } |
|---|
| 23 | |
|---|
| 24 | - (NSDictionary *)modelTranslationTable |
|---|
| 25 | { |
|---|
| 26 | NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"SUModelTranslation" ofType:@"plist"]; |
|---|
| 27 | return [[[NSDictionary alloc] initWithContentsOfFile:path] autorelease]; |
|---|
| 28 | } |
|---|
| 29 | |
|---|
| 30 | - (NSMutableArray *)systemProfileArrayForHost:(SUHost *)host |
|---|
| 31 | { |
|---|
| 32 | NSDictionary *modelTranslation = [self modelTranslationTable]; |
|---|
| 33 | |
|---|
| 34 | // Gather profile information and append it to the URL. |
|---|
| 35 | NSMutableArray *profileArray = [NSMutableArray array]; |
|---|
| 36 | NSArray *profileDictKeys = [NSArray arrayWithObjects:@"key", @"displayKey", @"value", @"displayValue", nil]; |
|---|
| 37 | int error = 0 ; |
|---|
| 38 | int value = 0 ; |
|---|
| 39 | unsigned long length = sizeof(value) ; |
|---|
| 40 | |
|---|
| 41 | // OS version |
|---|
| 42 | NSString *currentSystemVersion = [SUHost systemVersionString]; |
|---|
| 43 | if (currentSystemVersion != nil) |
|---|
| 44 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"osVersion",@"OS Version",currentSystemVersion,currentSystemVersion,nil] forKeys:profileDictKeys]]; |
|---|
| 45 | |
|---|
| 46 | // CPU type (decoder info for values found here is in mach/machine.h) |
|---|
| 47 | error = sysctlbyname("hw.cputype", &value, &length, NULL, 0); |
|---|
| 48 | int cpuType = -1; |
|---|
| 49 | if (error == 0) { |
|---|
| 50 | cpuType = value; |
|---|
| 51 | NSString *visibleCPUType; |
|---|
| 52 | switch(value) { |
|---|
| 53 | case 7: visibleCPUType=@"Intel"; break; |
|---|
| 54 | case 18: visibleCPUType=@"PowerPC"; break; |
|---|
| 55 | default: visibleCPUType=@"Unknown"; break; |
|---|
| 56 | } |
|---|
| 57 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"cputype",@"CPU Type", [NSNumber numberWithInt:value], visibleCPUType,nil] forKeys:profileDictKeys]]; |
|---|
| 58 | } |
|---|
| 59 | error = sysctlbyname("hw.cpu64bit_capable", &value, &length, NULL, 0); |
|---|
| 60 | if(error != 0) |
|---|
| 61 | error = sysctlbyname("hw.optional.x86_64", &value, &length, NULL, 0); //x86 specific |
|---|
| 62 | if(error != 0) |
|---|
| 63 | error = sysctlbyname("hw.optional.64bitops", &value, &length, NULL, 0); //PPC specific |
|---|
| 64 | |
|---|
| 65 | BOOL is64bit = NO; |
|---|
| 66 | |
|---|
| 67 | if (error == 0) { |
|---|
| 68 | is64bit = value == 1; |
|---|
| 69 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"cpu64bit", @"CPU is 64-Bit?", [NSNumber numberWithBool:is64bit], is64bit ? @"Yes" : @"No", nil] forKeys:profileDictKeys]]; |
|---|
| 70 | } |
|---|
| 71 | error = sysctlbyname("hw.cpusubtype", &value, &length, NULL, 0); |
|---|
| 72 | if (error == 0) { |
|---|
| 73 | NSString *visibleCPUSubType; |
|---|
| 74 | if (cpuType == 7) { |
|---|
| 75 | // Intel |
|---|
| 76 | visibleCPUSubType = is64bit ? @"Intel Core 2" : @"Intel Core"; // If anyone knows how to tell a Core Duo from a Core Solo, please email tph@atomicbird.com |
|---|
| 77 | } else if (cpuType == 18) { |
|---|
| 78 | // PowerPC |
|---|
| 79 | switch(value) { |
|---|
| 80 | case 9: visibleCPUSubType=@"G3"; break; |
|---|
| 81 | case 10: case 11: visibleCPUSubType=@"G4"; break; |
|---|
| 82 | case 100: visibleCPUSubType=@"G5"; break; |
|---|
| 83 | default: visibleCPUSubType=@"Other"; break; |
|---|
| 84 | } |
|---|
| 85 | } else { |
|---|
| 86 | visibleCPUSubType = @"Other"; |
|---|
| 87 | } |
|---|
| 88 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"cpusubtype",@"CPU Subtype", [NSNumber numberWithInt:value], visibleCPUSubType,nil] forKeys:profileDictKeys]]; |
|---|
| 89 | } |
|---|
| 90 | error = sysctlbyname("hw.model", NULL, &length, NULL, 0); |
|---|
| 91 | if (error == 0) { |
|---|
| 92 | char *cpuModel; |
|---|
| 93 | cpuModel = (char *)malloc(sizeof(char) * length); |
|---|
| 94 | error = sysctlbyname("hw.model", cpuModel, &length, NULL, 0); |
|---|
| 95 | if (error == 0) { |
|---|
| 96 | NSString *rawModelName = [NSString stringWithUTF8String:cpuModel]; |
|---|
| 97 | NSString *visibleModelName = [modelTranslation objectForKey:rawModelName]; |
|---|
| 98 | if (visibleModelName == nil) |
|---|
| 99 | visibleModelName = rawModelName; |
|---|
| 100 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"model",@"Mac Model", rawModelName, visibleModelName, nil] forKeys:profileDictKeys]]; |
|---|
| 101 | } |
|---|
| 102 | if (cpuModel != NULL) |
|---|
| 103 | free(cpuModel); |
|---|
| 104 | } |
|---|
| 105 | |
|---|
| 106 | // Number of CPUs |
|---|
| 107 | error = sysctlbyname("hw.ncpu", &value, &length, NULL, 0); |
|---|
| 108 | if (error == 0) |
|---|
| 109 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"ncpu",@"Number of CPUs", [NSNumber numberWithInt:value], [NSNumber numberWithInt:value],nil] forKeys:profileDictKeys]]; |
|---|
| 110 | |
|---|
| 111 | // User preferred language |
|---|
| 112 | NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; |
|---|
| 113 | NSArray *languages = [defs objectForKey:@"AppleLanguages"]; |
|---|
| 114 | if (languages && ([languages count] > 0)) |
|---|
| 115 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"lang",@"Preferred Language", [languages objectAtIndex:0], [languages objectAtIndex:0],nil] forKeys:profileDictKeys]]; |
|---|
| 116 | |
|---|
| 117 | // Application sending the request |
|---|
| 118 | NSString *appName = [host name]; |
|---|
| 119 | if (appName) |
|---|
| 120 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"appName",@"Application Name", appName, appName,nil] forKeys:profileDictKeys]]; |
|---|
| 121 | NSString *appVersion = [host version]; |
|---|
| 122 | if (appVersion) |
|---|
| 123 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"appVersion",@"Application Version", appVersion, appVersion,nil] forKeys:profileDictKeys]]; |
|---|
| 124 | |
|---|
| 125 | // Number of displays? |
|---|
| 126 | // CPU speed |
|---|
| 127 | OSErr err; |
|---|
| 128 | SInt32 gestaltInfo; |
|---|
| 129 | err = Gestalt(gestaltProcClkSpeedMHz,&gestaltInfo); |
|---|
| 130 | if (err == noErr) |
|---|
| 131 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"cpuFreqMHz",@"CPU Speed (GHz)", [NSNumber numberWithInt:gestaltInfo], [NSNumber numberWithDouble:gestaltInfo/1000.0],nil] forKeys:profileDictKeys]]; |
|---|
| 132 | |
|---|
| 133 | // amount of RAM |
|---|
| 134 | err = Gestalt(gestaltPhysicalRAMSizeInMegabytes,&gestaltInfo); |
|---|
| 135 | if (err == noErr) |
|---|
| 136 | [profileArray addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"ramMB",@"Memory (MB)", [NSNumber numberWithInt:gestaltInfo], [NSNumber numberWithInt:gestaltInfo],nil] forKeys:profileDictKeys]]; |
|---|
| 137 | |
|---|
| 138 | return profileArray; |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | @end |
|---|