IORegistryController.m [plain text]
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1998-2003 Apple Computer, Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#import "IORegistryController.h"
@implementation IORegistryController
- init {
if (self = [super init]) {
int plane;
_rootNode = [[IORegOutlineViewNode alloc] initWithName:@"Root" value:@"Root"];
_detailRootNode = [[IORegDetailOutlineViewNode alloc] init];
if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"IORegistryPlane"] intValue] == 1) {
plane = kIOService_Plane;
} else {
plane = kIOUSB_Plane;
}
_infoGatherer = [[IORegInfoGatherer alloc] initWithListener:self rootNode:_rootNode plane:plane];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(detailDrawerDidOpen:) name:NSDrawerDidOpenNotification object:IORegDetailedOutputDrawer];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSDrawerDidOpenNotification object:IORegDetailedOutputDrawer];
[_rootNode release];
[_detailRootNode release];
[_infoGatherer release];
[super dealloc];
}
- (void)awakeFromNib {
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"IORegistryDontAutoRefresh"] == YES) {
[RefreshCheckBox setState:NSOffState];
//enable/disable button [RefreshButton setEnabled:YES];
} else {
[RefreshCheckBox setState:NSOnState];
//enable/disable button [RefreshButton setEnabled:NO];
}
if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"IORegistryPlane"] intValue] == 1) {
[PlanePopUpButton selectItemAtIndex:1];
} else {
[PlanePopUpButton selectItemAtIndex:0];
}
[IORegOutputOV setTarget:self];
[IORegOutputOV setAction:@selector(ioregItemSingleClicked:)];
[IORegOutputOV setDoubleAction:@selector(ioregItemDoubleClicked:)];
[IORegDetailedOutput setTarget:IORegDetailedOutput];
[IORegDetailedOutput setDoubleAction:@selector(itemDoubleClicked)];
[self expandOutlineViewItems];
}
- (IBAction)Refresh:(id)sender {
[_detailRootNode removeAllChildren];
[IORegDetailedOutput reloadData];
[_infoGatherer refreshData:YES];
}
- (IBAction)SaveOutput:(id)sender {
NSSavePanel *sp = [NSSavePanel savePanel];
int result;
[sp setRequiredFileType:@"txt"];
result = [sp runModalForDirectory:NSHomeDirectory() file:@"IORegistry"];
if (result == NSOKButton) {
NSString *finalString = [_rootNode stringRepresentationOfValues:0];
if (![finalString writeToFile:[sp filename] atomically:YES encoding:NSUTF8StringEncoding error:NULL])
NSBeep();
}
}
- (IBAction)ToggleAutoRefresh:(id)sender {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([sender state] == NSOffState) {
[defaults setBool:YES forKey:@"IORegistryDontAutoRefresh"];
//enable/disable button [RefreshButton setEnabled:YES];
} else {
[defaults setBool:NO forKey:@"IORegistryDontAutoRefresh"];
//enable/disable button [RefreshButton setEnabled:NO];
[self Refresh:self];
}
}
- (IBAction)TogglePlane:(id)sender {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([sender indexOfSelectedItem] == 0) {
[defaults setObject:[NSNumber numberWithInt:0] forKey:@"IORegistryPlane"];
[_infoGatherer setPlane:0];
} else if ([sender indexOfSelectedItem] == 1) {
[defaults setObject:[NSNumber numberWithInt:1] forKey:@"IORegistryPlane"];
[_infoGatherer setPlane:1];
}
[self Refresh:self];
}
- (void)ioRegInfoGathererInformationDidChange:(IORegInfoGatherer *)aGatherer {
[IORegOutputOV reloadData];
[self expandOutlineViewItems];
}
- (void)expandOutlineViewItems {
NSEnumerator *enumerator;
id thisNode;
enumerator = [[_rootNode children] objectEnumerator];
while (thisNode = [enumerator nextObject]) {
if ([PlanePopUpButton indexOfSelectedItem] == 0) {
[IORegOutputOV expandItem:thisNode expandChildren:YES];
} else {
NSEnumerator *childEnumerator = [[thisNode children] objectEnumerator];
id thisChild;
[IORegOutputOV expandItem:thisNode];
while(thisChild = [childEnumerator nextObject]) {
[IORegOutputOV expandItem:thisChild];
}
}
}
}
- (id)outlineView:(NSOutlineView *)ov child:(NSInteger)index ofItem:(id)item
{
if (ov == IORegOutputOV) {
if (item == nil) {
return [_rootNode childAtIndex:index];
}
return [(OutlineViewNode *)item childAtIndex:index];
} else if (ov = IORegDetailedOutput) {
if (item == nil) {
return [_detailRootNode childAtIndex:index];
}
return [(OutlineViewNode *)item childAtIndex:index];
}
return nil;
}
- (BOOL)outlineView:(NSOutlineView *)ov isItemExpandable:(id)item
{
return [item isExpandable];
}
- (NSInteger)outlineView:(NSOutlineView *)ov numberOfChildrenOfItem:(id)item
{
if (ov == IORegOutputOV) {
if (item == nil) {
return [_rootNode childrenCount];
}
return [item childrenCount];
} else if (ov = IORegDetailedOutput) {
if (item == nil) {
return [_detailRootNode childrenCount];
}
return [item childrenCount];
}
return 0;
}
- (id)outlineView:(NSOutlineView *)ov objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
if (ov == IORegOutputOV) {
return [item value];
} else if (ov = IORegDetailedOutput) {
if ([[tableColumn identifier] intValue] == 0) {
return [(OutlineViewNode *)item name];
} else if ([[tableColumn identifier] intValue] == 1) {
return [(IORegDetailOutlineViewNode *)item type];
} else if ([[tableColumn identifier] intValue] == 2) {
return [item value];
}
}
return nil;
}
- (void)outlineViewSelectionDidChange:(NSNotification *)aNotification {
if ([aNotification object] == IORegOutputOV) {
[_detailRootNode removeAllChildren];
[IORegDetailedOutput reloadData];
}
}
- (void)ioregItemSingleClicked:(id)sender {
if ([IORegDetailedOutputDrawer state] == NSDrawerOpenState) {
IORegOutlineViewNode *item = [sender itemAtRow:[sender selectedRow]];
if ([item representedDevice] != IO_OBJECT_NULL) {
NSMutableDictionary *propertiesDict;
if (IORegistryEntryCreateCFProperties( [item representedDevice], (CFMutableDictionaryRef *)&propertiesDict, kCFAllocatorDefault, 0 ) == 0) {
[_detailRootNode removeAllChildren];
[self populateNode:_detailRootNode withContentsOfDictionary:propertiesDict];
[IORegDetailedOutput reloadData];
CFRelease(propertiesDict);
}
}
}
}
- (void)ioregItemDoubleClicked:(id)sender {
[sender itemDoubleClicked];
}
- (void)populateNode:(IORegDetailOutlineViewNode *)node withKey:(NSString *)key value:(id)value {
IORegDetailOutlineViewNode * aNewNode;
if (CFGetTypeID(value) == CFStringGetTypeID()) {
aNewNode = [[IORegDetailOutlineViewNode alloc] initWithName:(NSString *)key value:(NSString *)value];
[aNewNode setType:@"String"];
[node addChild:aNewNode];
[aNewNode release];
} else if (CFGetTypeID(value) == CFNumberGetTypeID()) {
switch (CFNumberGetType((CFNumberRef)value)) {
case kCFNumberSInt32Type:
aNewNode = [[IORegDetailOutlineViewNode alloc] initWithName:(NSString *)key value:[NSString stringWithFormat:@" break;
case kCFNumberSInt64Type:
aNewNode = [[IORegDetailOutlineViewNode alloc] initWithName:(NSString *)key value:[NSString stringWithFormat:@" break;
default:
aNewNode = [[IORegDetailOutlineViewNode alloc] initWithName:(NSString *)key value:[NSString stringWithFormat:@" }
[aNewNode setType:@"Number"];
[node addChild:aNewNode];
[aNewNode release];
} else if (CFGetTypeID(value) == CFDataGetTypeID()) {
aNewNode = [[IORegDetailOutlineViewNode alloc] initWithName:(NSString *)key value:[value description]];
[node addChild:aNewNode];
[aNewNode release];
} else if (CFGetTypeID(value) == CFDictionaryGetTypeID()) {
aNewNode = [[IORegDetailOutlineViewNode alloc] initWithName:(NSString *)key value:@""];
[aNewNode setType:@"Dictionary"];
[self populateNode:aNewNode withContentsOfDictionary:value];
[node addChild:aNewNode];
[aNewNode release];
} else if (CFGetTypeID(value) == CFArrayGetTypeID()) {
aNewNode = [[IORegDetailOutlineViewNode alloc] initWithName:(NSString *)key value:@""];
[aNewNode setType:@"Array"];
[self populateNode:aNewNode withContentsOfArray:value];
[node addChild:aNewNode];
[aNewNode release];
} else if (CFGetTypeID(value) == CFBooleanGetTypeID()) {
if ( CFBooleanGetValue( (CFBooleanRef) value) )
aNewNode = [[IORegDetailOutlineViewNode alloc] initWithName:(NSString *)key value:@"Yes"];
else
aNewNode = [[IORegDetailOutlineViewNode alloc] initWithName:(NSString *)key value:@"No"];
[aNewNode setType:@"Boolean"];
[node addChild:aNewNode];
[aNewNode release];
}
}
- (void)populateNode:(IORegDetailOutlineViewNode *)node withContentsOfDictionary:(NSDictionary *)dictionary {
NSMutableArray * keys = [[dictionary allKeys] mutableCopy];
NSEnumerator * enumerator;
NSString * key;
[keys sortUsingSelector:@selector(caseInsensitiveCompare:)];
enumerator = [keys objectEnumerator];
while (key = [enumerator nextObject]) {
[self populateNode:node withKey:key value:[dictionary objectForKey:key]];
}
[keys release];
}
- (void)populateNode:(IORegDetailOutlineViewNode *)node withContentsOfArray:(NSArray *)array {
NSEnumerator * enumerator = [array objectEnumerator];
id value;
int counter = 0;
while (value = [enumerator nextObject]) {
[self populateNode:node withKey:[NSString stringWithFormat:@" counter++;
}
}
- (void)detailDrawerDidOpen:(NSNotification *)notification {
[self ioregItemSingleClicked:IORegOutputOV];
}
@end