PDA

View Full Version : DMGetNameByAVID deprecated in 10.4


AnotherJake
2005.05.06, 03:53 PM
I've been using it for a long time to get the name of the connected monitors. In Displays.h it says it's been deprecated in 10.4. I can't seem to find a replacement. Does anybody know what to use instead?

AnotherJake
2005.05.10, 02:12 AM
Since Apple seems to be tossing Display Manager in the circular file and I still haven't found a way to get the proper name ( e.g. "Apple Display" or "Studio Display 21", etc. ) of any connected displays I'll try to get by without it. I'll iterate over them as they are returned from CGGetActiveDisplayList and just label them in order as "Main Display", "Display 2", "Display 3", and so on, since CGDirectDisplay.h says the first one returned in the array is the main display. Not perfect, but I guess it'll have to suffice unless someone has a better idea...

OneSadCookie
2005.05.10, 02:54 AM
You can get the information you want from the IOKit. I haven't quite figured it out yet, but I'll take a closer look when I get home. The function you need (IODisplayCreateInfoDictionary) is declared in /System/Library/Frameworks/IOKit.framework/Headers/graphics/IOGraphicsLib.h

OneSadCookie
2005.05.10, 05:07 AM
OK, here's a little program that'll loop through your framebuffers and print the names of the displays attached to each:

#include <stdio.h>
#include <stdlib.h>

#include <IOKit/IOKitLib.h>
#include <IOKit/graphics/IOGraphicsLib.h>

#define QUIT_IF(condition) \
if (condition) \
{ \
printf("%s on line %d of %s\n", #condition, __LINE__, __FILE__); \
exit(EXIT_FAILURE); \
}

#define QUIT_ON_IOERROR(x) QUIT_IF((x) != kIOReturnSuccess)
#define QUIT_ON_NULL(x) QUIT_IF((x) == NULL)

int main(int argc, const char *argv[])
{
kern_return_t result;

CFMutableDictionaryRef matching_dictionary;
matching_dictionary = IOServiceMatching(IOFRAMEBUFFER_CONFORMSTO);
QUIT_ON_NULL(matching_dictionary);

io_iterator_t iterator;
result = IOServiceGetMatchingServices(
kIOMasterPortDefault,
matching_dictionary,
&iterator);
QUIT_ON_IOERROR(result);

io_service_t service;
service = (io_service_t)IOIteratorNext(iterator);
while (service != 0)
{
CFDictionaryRef display_dictionary;
display_dictionary = IODisplayCreateInfoDictionary(
service,
kIODisplayOnlyPreferredName);
QUIT_ON_NULL(display_dictionary);

//CFShow(display_dictionary);

CFDictionaryRef product_names_dictionary;
product_names_dictionary = CFDictionaryGetValue(
display_dictionary,
CFSTR(kDisplayProductName));
if (product_names_dictionary != NULL)
{
QUIT_IF(CFDictionaryGetCount(product_names_diction ary) != 1);

CFStringRef product_name;
CFDictionaryGetKeysAndValues(
product_names_dictionary,
NULL,
(const void**)&product_name);
QUIT_ON_NULL(product_name);

CFShow(product_name);
}

service = (io_service_t)IOIteratorNext(iterator);
}

IOObjectRelease(iterator);
}


The question now is, how to associate this information with a CGDirectDisplayID?

OneSadCookie
2005.05.10, 08:06 AM
... and I can't find any way to. Maybe, just maybe, by messing with undocumented CGS APIs there might be a way, but I can't find one. Fat lot of use that is :(

Matrix
2005.05.10, 10:43 AM
How about CGDisplayIOServicePort? I've never used the IOKit before, but that function does take a DisplayID and returns a io_service_t

Could be helpful,
Adam Zegelin

AnotherJake
2005.05.10, 11:09 AM
YES! Much thanks to both of you!

- (void)printMainDisplayName
{
CFDictionaryRef display_dictionary, product_names_dictionary;
io_service_t service;
CFStringRef product_name;

service = CGDisplayIOServicePort(kCGDirectMainDisplay);
display_dictionary = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
product_names_dictionary = CFDictionaryGetValue(display_dictionary, CFSTR(kDisplayProductName));
CFDictionaryGetKeysAndValues( product_names_dictionary, NULL, (const void**)&product_name);
CFShow(product_name);
}

I haven't written it for multiple displays or error conditions (give me a break, I just woke up and wanted to try it out), but I can plug in CGDirectDisplayID's all day so that won't be a problem. Looks like this case is closed. :D

OneSadCookie
2005.05.10, 05:14 PM
Ah, from CGDisplayConfiguration.h. I didn't look there :(

Excellent, case closed!

Note that if you're in Cocoa, CFStringRef == NSString*, and CFDictionaryRef == NSDictionary*, so you can write the code a bit more nicely than you have ;)

AnotherJake
2005.05.10, 06:03 PM
Note that if you're in Cocoa, CFStringRef == NSString*, and CFDictionaryRef == NSDictionary*, so you can write the code a bit more nicely than you have ;)
Okay, here's my attempt at making it prettier for Cocoa and more useful at the same time. Give it a display id and it'll give you a name. If any errors occur it should merely return "Unknown Display". I tested it and it seems to work great, but I don't know if the code is "correct". ;)

#import <IOKit/graphics/IOGraphicsLib.h>
- (NSString *)getDisplayNameUsingID:(CGDirectDisplayID)display
{
NSDictionary *displayDictionary, *productNamesDictionary;
io_service_t service;
NSString *displayName;

service = CGDisplayIOServicePort(display);
displayDictionary = (NSDictionary *)IODisplayCreateInfoDictionary(service,
kIODisplayOnlyPreferredName);
if (displayDictionary != NULL)
{
productNamesDictionary = [displayDictionary
valueForKey:@kDisplayProductName];
if (productNamesDictionary != NULL)
displayName = [[productNamesDictionary allValues] objectAtIndex:0];
}
if (displayName != NULL)
return displayName;
else
return @"Unknown Display";
}

OneSadCookie
2005.05.10, 06:52 PM
I don't think you should be autoreleasing the displayName should you?

Otherwise, looks good.

AnotherJake
2005.05.10, 07:00 PM
I think you're right since I didn't alloc init displayName, so I removed the autorelease. Thanks.