Closed GoogleCodeExporter closed 9 years ago
See conversation in email list. Patch is below. I have attached a tar file of the binary Localizable.strings strings, to untar in the HardwareGrowler directory. YA diff -r 193986cc6493 Extras/HardwareGrowler/NetworkNotifier.m --- a/Extras/HardwareGrowler/NetworkNotifier.m Mon Nov 07 10:48:13 2011 -0600 +++ b/Extras/HardwareGrowler/NetworkNotifier.m Wed Feb 29 15:20:50 2012 -0800 @@ -3,6 +3,7 @@ // HardwareGrowler // // Created by Ingmar Stein on 18.02.05. +// Modified by Yves Arrouye on 22.02.11 to support MacBook Airs. // Copyright 2005 The Growl Project. All rights reserved. // Copyright (C) 2004 Scott Lamb <slamb@slamb.org> // @@ -32,6 +33,16 @@ /** A reference to the SystemConfiguration dynamic store. */ static SCDynamicStoreRef dynStore; +/** Keys to watch. Entries 1 and 2 will be filled in with the appropriate keys for the interfaces we are watching. Ideally, this module would be changed to support an arbitraty number of interfaces of each type, but this will fix the issues about reporting Airport as Ethernet on MacBook Air machines and that is all we care about right now. */ +CFStringRef keys[3] = { + CFSTR("State:/Network/Global/IPv4") +}; +static int keysFirstInterfaceEntry = 1; +int keysNumEntries = 1; + +int airportKey = -1; +int ethernetKey = -1; + /** Our run loop source for notification. */ static CFRunLoopSourceRef rlSrc; @@ -44,11 +55,11 @@ // This is all made by looking through Darwin's src/network_cmds/ifconfig.tproj. // There's no pretty way to get media stuff; I've stripped it down to the essentials // for what I'm doing. - + size_t length = strlen(interface); if (length >= IFNAMSIZ) NSLog(@"Interface name too long"); - + int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { NSLog(@"Can't open datagram socket"); @@ -57,21 +68,21 @@ struct ifmediareq ifmr; memset(&ifmr, 0, sizeof(ifmr)); strncpy(ifmr.ifm_name, interface, sizeof(ifmr.ifm_name)); - + if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { // Media not supported. close(s); return NULL; } - + close(s); - + // Now ifmr.ifm_current holds the selected type (probably auto-select) // ifmr.ifm_active holds details (100baseT <full-duplex> or similar) // We only want the ifm_active bit. - + const char *type = "Unknown"; - + // We'll only look in the Ethernet list. I don't care about anything else. struct ifmedia_description *desc; for (desc = ifm_subtype_ethernet_descriptions; desc->ifmt_string; ++desc) { @@ -80,9 +91,9 @@ break; } } - + NSMutableString *options = nil; - + // And fill in the duplex settings. for (desc = ifm_shared_option_descriptions; desc->ifmt_string; desc++) { if (ifmr.ifm_active & desc->ifmt_word) { @@ -93,33 +104,37 @@ } } } - + NSString *media; if (options) { media = [NSString stringWithFormat:@"%s <%@>", - type, - options]; + type, + options]; } else { media = [NSString stringWithUTF8String:type]; } - + return media; } - (void)linkStatusChange:(NSDictionary *)newValue { int newActive = [[newValue objectForKey:@"Active"] intValue]; int oldActive = [[(NSDictionary*)ethernetStatus objectForKey:@"Active"] intValue]; - + + NSString *ifName = [NSString stringWithFormat:@"en%d", ethernetKey - keysFirstInterfaceEntry]; + if (newActive && !oldActive) { - NSString *media = [self getMediaForInterface:"en0"]; - NSString *desc = [NSString stringWithFormat: - NSLocalizedString(@"Interface:\ten0\nMedia:\t%@", "The %@ will be replaced by a description of the Ethernet media such as '100BT/full-duplex'"), + NSString *media = [self getMediaForInterface:[ifName UTF8String]]; + NSString *desc = [NSString stringWithFormat: + NSLocalizedString(@"Interface:\t%@\nMedia:\t%@", "The first %@ will bereplaced by the interface name, e.g. en0; the second %@ will be replaced by a description of the Ethernet media such as '100BT/full-duplex'"), media]; AppController_linkUp((CFStringRef)desc); } else if (!newActive && oldActive) { - AppController_linkDown((CFStringRef)NSLocalizedString(@"Interface:\ten0", nil)); + NSString *desc = [NSString stringWithFormat: + NSLocalizedString(@"Interface:\t%@", "The %@ will be replaced by the interface name, e.g. en0"), ifName]; + AppController_linkDown((CFStringRef)desc); } - + if (ethernetStatus) CFRelease(ethernetStatus); ethernetStatus = newValue ? CFRetain(newValue) : NULL; @@ -164,8 +179,8 @@ for (unsigned i=0U; i<9; ++i) { if ((a & types[i].netmask) == types[i].network) { return [[NSBundle bundleForClass:[self class]] localizedStringForKey:types[i].type - value:types[i].type - table:nil]; + value:types[i].type + table:nil]; } } } @@ -192,16 +207,16 @@ } - (void)airportStatusChange:(NSDictionary *)newValue { -// NSLog(CFSTR("AirPort event")); - + // NSLog(CFSTR("AirPort event")); + CFDataRef newBSSID = NULL; if (newValue) newBSSID = (CFDataRef)[newValue objectForKey:@"BSSID"]; - + CFDataRef oldBSSID = NULL; if (airportStatus) oldBSSID = CFDictionaryGetValue(airportStatus, CFSTR("BSSID")); - + if (newValue && oldBSSID != newBSSID && !(newBSSID && oldBSSID && CFEqual(oldBSSID, newBSSID))) { NSNumber *linkStatus = [newValue objectForKey:@"Link Status"]; NSNumber *powerStatus = [newValue objectForKey:@"Power Status"]; @@ -227,10 +242,10 @@ } } } - + if (airportStatus) CFRelease(airportStatus); - + if (newValue) airportStatus = CFRetain(newValue); else @@ -239,13 +254,11 @@ static void scCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) { NetworkNotifier *self = info; - + CFIndex count = CFArrayGetCount(changedKeys); for (CFIndex i=0; i<count; ++i) { CFStringRef key = CFArrayGetValueAtIndex(changedKeys, i); - if (CFStringCompare(key, - CFSTR("State:/Network/Interface/en0/Link"), - 0) == kCFCompareEqualTo) { + if (ethernetKey >= 0 && CFStringCompare(key, keys[ethernetKey], 0) == kCFCompareEqualTo) { CFDictionaryRef newValue = SCDynamicStoreCopyValue(store, key); [self linkStatusChange:(NSDictionary *)newValue]; if (newValue) @@ -257,9 +270,7 @@ [self ipAddressChange:(NSDictionary *)newValue]; if (newValue) CFRelease(newValue); - } else if (CFStringCompare(key, - CFSTR("State:/Network/Interface/en1/AirPort"), - 0) == kCFCompareEqualTo) { + } else if (airportKey >= 0 && CFStringCompare(key, keys[airportKey], 0) == kCFCompareEqualTo) { CFDictionaryRef newValue = SCDynamicStoreCopyValue(store, key); [self airportStatusChange:(NSDictionary *)newValue]; if (newValue) @@ -272,7 +283,7 @@ if (!(self = [super init])) return nil; SCDynamicStoreContext context = {0, self, NULL, NULL, NULL}; - + dynStore = SCDynamicStoreCreate(kCFAllocatorDefault, CFBundleGetIdentifier(CFBundleGetMainBundle()), scCallback, @@ -282,16 +293,93 @@ [self release]; return nil; } + + rlSrc = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, dynStore, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), rlSrc, kCFRunLoopDefaultMode); + CFRelease(rlSrc); - const CFStringRef keys[3] = { - CFSTR("State:/Network/Interface/en0/Link"), - CFSTR("State:/Network/Global/IPv4"), - CFSTR("State:/Network/Interface/en1/AirPort") - }; - CFArrayRef watchedKeys = CFArrayCreate(kCFAllocatorDefault, - (const void **)keys, - 3, - &kCFTypeArrayCallBacks); + // Are we going to notify about existing interfaces? + + Boolean notifyAboutExistingHardware = false; + + Boolean keyExistsAndHasValidFormat; + if (CFPreferencesGetAppBooleanValue(CFSTR("ShowExisting"), CFSTR("com.growl.hardwaregrowler"), &keyExistsAndHasValidFormat)) { + notifyAboutExistingHardware = true; + } + + // Look at network interfaces. Determine for each whether they are Ethernet or Airport. + // The proper way to do this is probably to look at system preferences. We will however + // cheat here and just enumerate the en* interfaces. + + airportStatus = ethernetStatus = NULL; + + NSDictionary *interfaceDict = (__bridge_transfer NSDictionary *) SCDynamicStoreCopyValue(dynStore, CFSTR("State:/Network/Interface")); + if (interfaceDict) { + NSArray *interfaceNames = [interfaceDict objectForKey:@"Interfaces"]; + if (interfaceNames) { + for (NSString *ifName in interfaceNames) { + + // Let's not look at any interface that is not Ethernet or Airpot. + + if (![ifName hasPrefix:@"en"] || [ifName length] < 3 || !isdigit([ifName characterAtIndex:2])) { + continue; + } + + // Alright, we can proceed. We will look for Airport first, as both Airport + // and Ethernet interfaces can have a link (indicating their status). + + CFStringRef key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("State:/Network/Interface/%@/AirPort"), ifName); + CFDictionaryRef status = SCDynamicStoreCopyValue(dynStore, key); + + if (status) { + if (!airportStatus) { + if (notifyAboutExistingHardware) { + [self airportStatusChange:(__bridge NSDictionary *)status]; + [self ipAddressChange:(__bridge NSDictionary *)status]; + CFRelease(status); + } else { + airportStatus = status; + } + + keys[airportKey = keysNumEntries++] = CFRetain(key); + } + + CFRelease(key); + continue; + } + CFRelease(key); + + + key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("State:/Network/Interface/%@/Link"), ifName); + status = SCDynamicStoreCopyValue(dynStore, key); + + if (status) { + if (!ethernetStatus) { + if (notifyAboutExistingHardware) { + [self linkStatusChange:(__bridge NSDictionary *)status]; + [self ipAddressChange:(__bridge NSDictionary *)status]; + CFRelease(status); + } else { + ethernetStatus = status; + } + + keys[ethernetKey = keysNumEntries++] = CFRetain(key); + } + + CFRelease(key); + continue; + } + CFRelease(key); + } + } + } + + // Register the keys to watch. + + CFArrayRef watchedKeys = CFArrayCreate(kCFAllocatorDefault, + (const void **)keys, + keysNumEntries, + &kCFTypeArrayCallBacks); if (!SCDynamicStoreSetNotificationKeys(dynStore, watchedKeys, NULL)) { @@ -304,13 +392,7 @@ return nil; } CFRelease(watchedKeys); - - rlSrc = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, dynStore, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), rlSrc, kCFRunLoopDefaultMode); - CFRelease(rlSrc); - - airportStatus = SCDynamicStoreCopyValue(dynStore, CFSTR("State:/Network/Interface/en1/AirPort")); - ethernetStatus = SCDynamicStoreCopyValue(dynStore, CFSTR("State:/Network/Interface/en0/Link")); + return self; } @@ -324,6 +406,11 @@ if (ethernetStatus) CFRelease(ethernetStatus); + if (keys[1]) + CFRelease(keys[1]); + if (keys[2]) + CFRelease(keys[2]); + [super dealloc]; } diff -r 193986cc6493 Extras/HardwareGrowler/ar.lproj/Localizable.strings Binary file Extras/HardwareGrowler/ar.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/cs.lproj/Localizable.strings Binary file Extras/HardwareGrowler/cs.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/de.lproj/Localizable.strings Binary file Extras/HardwareGrowler/de.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/el.lproj/Localizable.strings Binary file Extras/HardwareGrowler/el.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/en.lproj/Localizable.strings Binary file Extras/HardwareGrowler/en.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/it.lproj/Localizable.strings Binary file Extras/HardwareGrowler/it.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/ja.lproj/Localizable.strings Binary file Extras/HardwareGrowler/ja.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/ko.lproj/Localizable.strings Binary file Extras/HardwareGrowler/ko.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/lv.lproj/Localizable.strings Binary file Extras/HardwareGrowler/lv.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/nl.lproj/Localizable.strings Binary file Extras/HardwareGrowler/nl.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/ro.lproj/Localizable.strings --- a/Extras/HardwareGrowler/ro.lproj/Localizable.strings Mon Nov 07 10:48:13 2011 -0600 +++ b/Extras/HardwareGrowler/ro.lproj/Localizable.strings Wed Feb 29 15:20:50 2012 -0800 @@ -17,13 +17,13 @@ "FireWire Device Disconnected" = "Dispozitiv cu cablu deconectat "; "FireWire Disconnection" = "Deconectare cablu"; "Group Network Notifications" = "Grup rețea de notificări"; -"Interface:\ten0" = "Interfață:\ten0"; -"Interface:\ten0\nMedia:\t%@" = "Interfață:\ten0\nMedia:\t%@"; +"Interface:\t%@" = "Interfață:%@"; +"Interface:\t%@\nMedia:\t%@" = "Interfață:%@\nMedia:\t%@"; "IP Acquired" = "IP primit"; "IP address acquired" = "Adresă IP primită"; "IP address released" = "Adresă IP expediată"; "IP Released" = "IP expediat"; -"Joined network.\nSSID:\t\t%@\nBSSID:\t%@" = "Rețea conectată.\nSSID:\t\t%1$@\nBSSID:\t%2$@"; +"Joined network.\nSSID:\t%@\nBSSID:\t%@" = "Rețea conectată.\nSSID:\t%1$@\nBSSID:\t%2$@"; "Left network %@." = "Rețea părăsită %@."; "Link-local" = "Legătură-locală"; "Loopback" = "Revenire la forma inițială"; diff -r 193986cc6493 Extras/HardwareGrowler/sk.lproj/Localizable.strings Binary file Extras/HardwareGrowler/sk.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/sv.lproj/Localizable.strings Binary file Extras/HardwareGrowler/sv.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/zh-Hans.lproj/Localizable.strings Binary file Extras/HardwareGrowler/zh-Hans.lproj/Localizable.strings has changed diff -r 193986cc6493 Extras/HardwareGrowler/zh-Hant.lproj/Localizable.strings Binary file Extras/HardwareGrowler/zh-Hant.lproj/Localizable.strings has changed
Original issue reported on code.google.com by yves.arr...@gmail.com on 1 Mar 2012 at 12:27
yves.arr...@gmail.com
Attached file with ALL the strings.
Original comment by yves.arr...@gmail.com on 1 Mar 2012 at 12:29
Attachments:
Original issue reported on code.google.com by
yves.arr...@gmail.com
on 1 Mar 2012 at 12:27