Refresh rate switching

I wrote my first C program today.



I had tried to use cscreen to switch refresh rates on my Mac mini/Sony XBR5 combo, but it kept switching to 1080i with -r 60 switch. I did some poking around and came to the (now) obvious conclusion that CGDisplayBestModeForParameters() doesn’t take interlaced/progressive into account. Poop.



The program below looks for a new display mode with the same resolution and bit depth as the current display mode, while ignoring interlaced modes. It only changes the refresh rate (in theory).



/*<br />
 * refresh.c<br />
 *<br />
 * Copyright (c) 2010 Robin Gridley<br />
 */<br />
<br />
#include <ApplicationServices/ApplicationServices.h><br />
<br />
int main(int argc, char *argv[]) {<br />
	<br />
	double refresh;<br />
	double cur_refresh;<br />
	int i;<br />
	<br />
	CFNumberRef width;<br />
	CFNumberRef height;<br />
	CFNumberRef depth;<br />
	CFNumberRef cur_width;<br />
	CFNumberRef cur_height;<br />
	CFNumberRef cur_depth;<br />
	CFArrayRef modes;<br />
	CFDictionaryRef mode;<br />
	CGDisplayConfigRef config;<br />
	<br />
	if (argc != 3) {<br />
		printf("Usage: refresh -r <rate>
");<br />
		return 0;<br />
	}<br />
	<br />
	refresh = strtod(argv[2], 0);<br />
	<br />
	mode = CGDisplayCurrentMode(kCGDirectMainDisplay);<br />
		<br />
	cur_width = CFDictionaryGetValue(mode, kCGDisplayWidth);		<br />
	cur_height = CFDictionaryGetValue(mode, kCGDisplayHeight);<br />
	cur_depth = CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel);<br />
	<br />
	modes = CGDisplayAvailableModes(kCGDirectMainDisplay);<br />
	<br />
	for (i = 0; i < CFArrayGetCount(modes); i++) {<br />
		<br />
		mode = CFArrayGetValueAtIndex(modes, i);<br />
		<br />
		CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayRefreshRate), kCFNumberDoubleType, &cur_refresh);<br />
		<br />
		width = CFDictionaryGetValue(mode, kCGDisplayWidth);		<br />
		height = CFDictionaryGetValue(mode, kCGDisplayHeight);<br />
		depth = CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel);<br />
		<br />
		if ( ! CFDictionaryContainsKey(mode, kCGDisplayModeIsInterlaced) && <br />
		    CFNumberCompare(cur_width, width, NULL) == kCFCompareEqualTo && <br />
		    CFNumberCompare(cur_height, height, NULL) == kCFCompareEqualTo && <br />
		    CFNumberCompare(cur_depth, depth, NULL) == kCFCompareEqualTo && <br />
		    cur_refresh == refresh) {<br />
		    <br />
			CGBeginDisplayConfiguration(&config);<br />
			CGConfigureDisplayMode(config, kCGDirectMainDisplay, mode);<br />
			CGCompleteDisplayConfiguration(config, kCGConfigureForSession);<br />
			break;<br />
		}<br />
	}<br />
}



Save it as refresh.c and use the following command to compile it:


gcc -framework ApplicationServices -o refresh refresh.c



Or download it [here](http://unknown-host.com/refresh/).

Usage example:


refresh -r 24



So after writing this, I have to ask: why doesn't Plex do this automatically? Is there some techinical issue preventing this from happening? Or is it just a lack of spare time?

Because Elan hasn't released a build with the refresh rate switching I wrote last week. :) Previously it was lack of time (and a 24p TV).

I've taken a similar approach to you. Basically now Plex will check to see if a matching refresh rate is available for the currently playing video at the same resolution, and switch to that if possible. However I'm using the 10.6 API, so this will only be available on 10.6. I don't think resolution change is a good idea, better just to run at your highest resolution and let Plex / OS X handle the scaling.

-Ryan


I started with the 10.6 API, since my mini is running 10.6.3, but I couldn't figure out a way to detect if the display mode is interlaced. Unfortunately, on my setup, when you loop over the array returned by CGDisplayCopyAllDisplayModes(), the first matching 1920x1080 @ 60Hz mode is interlaced. :(

I like how Apple deprecates all of the old functions, provides new 10.6 specific functions, but doesn't bother to document them. I was stuck poking through header files.

Great work from both of you. Looking forward to this being implemented


That's a good point. Have you asked on the quartz-api mailing list? I'll check in with them if you haven't.


I have not. Thanks!

Any news regarding this issue?



Lack of auto refresh rate switching on Plex is the only thing preventing me from switching from my Windows based HTPC to the Mac Mini.

Yeah, where’s the binary to test this… :wink:



Thanks in advance!

My code is for a command line program that can be used as part of a script to switch refresh rates.



I imagine you won’t see anything from tokyovigilante’s work until Plex 9 is released. Speaking of which, what did the quartz-api mailing list have to say about detecting (and skipping) interlaced modes?


Nothing sadly, I fear it's been left out of the CGDisplay API. I may fall pack to the 10.5 API if I can't work it out.

-Ryan

Ah, voila.


kDisplayModeInterlacedFlag = 0x00000040

it’s great to read that there is work going on on the refresh rate issue. Do you think that this will be inckuded in Plex 0.9?


Yes. In fact it's in there already. ;)

tokyovigilante thank you for this great future within Plex nine and thank you for all your hard work, just as all developers of Plex.

Much appreciated by my girlfriend and also myself. We will wait patiently for Plex .9



Awesome.


Great to hear that! Just bought a new Mac Mini for use as my new HTPC running plex. Been trying to setup manual scripts to change refresh rates with some success but haven't managed to set interlaced/progressive.

i.e. When using scripts to change to 1920 x 1080 24Hz it would choose Progessive but with 50Hz and 60Hz it would always choose Interlaced. Even though I can manually set 50Hz and 60Hz in System Preferences and it uses Progressive Mode.

But, think I'll just wait for Plex v9 for this functionality.

Keep up the great work!

Cheers


See first post. The program I wrote will allow you to setup your scripts and avoid them switching back to interlaced.

Doh! How did I miss that :huh:



Will give that a go tonight, cheers!



Nice coding, works perfectly!

Many thanks

Next version of Plex 9 maybe?



Edit:



The new library and Plex for iOS are awesome. I’m watching Dragnet on my iPhone. :smiley: