Lead

Apr 20 10 8:24 PM

Tags : :

Originally Posted by EricN on February 8, 2010 at 8:05pm


This is a clumsy approach to scripting screen rotation — I may have to learn Cocoa to do it right. I've got a couple ideas to make it a bit better, but for a general display rotation utility, this approach is probably a dead end. Fortunately, most of the code may be reused to build a e-reader rotation utility. 


Unfortunately, I've have to implement a clumsy workaround since AppleScript does not appear capable of accessing the display rotation controls in "System Preferences".  So at the beginning of the script, I put in some dialog boxes to help the user provide access to those controls for the script. The script will require the user to help it out every once and a while, so, as it stands, it is not very practical, but it does work. 


In order to use the script, one must first install Daniel Griscom's smsutil (download below or from his site as a part  of his SMSLib). Put the AppleScript below in the AppleScript Editor (Utilities folder), and alter the first line of the script to include a path to the smsutil  utility. Then run the script and follow the direction provided in the dialog boxes. To quit the script just hit the stop button in the AppleScript Editor. Remember, any User Interface script, like this one, requires you to "Enable access for assistive devices". You will find the check box for that at the bottom of the "Universal Access" panes in System Preferences.


Oh, yes. I've designed the script to work with a regular Mac Book as well. I assume that the MacBook screen is set at an angle of 60º to the base, and adjust the screen rotation calculations so as to keep the screen readable. To use the script with a MacBook, alter the third line of the script.



set smsutilPath to "/User/Home/library/Blah Blah Blah/smsutil" -- Path to utility smsutil.

set orientCheckDelay to 1.0 -- Number of seconds between each time the script updates the computer's orientation.


set typeComputer to "modbook" -- Is the computer a "MacBook" or "Modbook"?

set displayWidth to 32.5 -- Display width in centimeters.

set displayHeight to 22.7 -- Display height in centimeters.

set displayDiagonal to (displayWidth ^ 2 + displayHeight ^ 2) ^ 0.5


set cosMacAdjust to 0.5 -- cosine of apx. angle of a MacBook screen tilt (60 degrees).

set sinMacAdjust to 0.8660254 -- sine of apx. angle of a MacBook screen tilt (60 degrees).


set sinIgnore to 0.2 -- sine of angle off flat before script considers rotating the display (~12 degrees).


----------- Calculate sine and cosine of Flip Angle -----------

set sinFlip to displayHeight / displayDiagonal

set cosFlip to displayWidth / displayDiagonal


-------- Determine Model ID and Graphics Chip for System --------

set systemInfo to systemsInfo()

if item 2 of systemInfo is not "NVIDIA GeForce 9400M" and (offset of "pro" in (item 1 of systemInfo) = 0) then

tell application "System Events"

activate

display alert "Your system does not support display rotation."

quit

end tell

return

end if


------ Provide escape sequences for spaces in path of smsutil ------

set TID to text item delimiters

set text item delimiters to " "

set aList to every text item of (smsutilPath as text)

set text item delimiters to "\\ "

set smsutilPath to aList as text

set text item delimiters to TID


---------- Find initial display orientation ------------

set displayOrient to getDisOrient()

set displayOrientOld to displayOrient


repeat

log {displayOrientOld, displayOrient}


--------- If old and new orientation not the same, rotate display ---------

if displayOrient is not equal to displayOrientOld then

set displayOrientOld to ChangeDisOrient(displayOrient)

--set displayOrientOld to displayOrient

end if


------- If rotating yields an error, then run work around --------

if displayOrientOld is less than 0 then

set displayOrientOld to rotationError()


------- If work around yields an error, then quit --------

if displayOrientOld is less than 0 then

tell application "System Events"

activate

display alert "Display Rotation is apparently Not Possible." & return message "Perhaps your system does not support display rotation."

quit

end tell

return

else

tell application "System Events" to quit

end if

end if


--------------- Get six force vectors from the SMS ---------------

set theOutput to do shell script (smsutilPath & " -i0.025 -c6")


---------- Convert the force vector text to a list -----------

set TID to text item delimiters

set text item delimiters to return

set vectorList to every text item of (theOutput as text)

set text item delimiters to space

repeat with i from 1 to count of vectorList

set item i of vectorList to every text item of item i of vectorList

end repeat

set text item delimiters to TID


------------- Find vector magnitudes ---------------

set vectorMags to {}

repeat with i from 1 to count of vectorList

set xCoord to item 1 of item i of vectorList

set yCoord to item 2 of item i of vectorList

set zCoord to item 3 of item i of vectorList

set the end of vectorMags to (xCoord ^ 2 + yCoord ^ 2 + zCoord ^ 2) ^ 0.5

end repeat


--------------- Find an average vector --------------

-------- Ignoring shock-type force vectors --------

set avVector to {0, 0, 0}

set m to 0

repeat with i from 1 to count of vectorList

if (item i of vectorMags) is greater than 0.7 and (item i of vectorMags) is less than 1.3 then

repeat with j from 1 to 3

set item j of avVector to (item j of avVector) + (item j of item i of vectorList) / (item i of vectorMags)


end repeat

set m to m + 1

end if

end repeat

repeat with j from 1 to 3

set item j of avVector to (item j of avVector) / m

end repeat


------- Set x,y,z coordinates ---------

----- adjusting for odd SMS's ------

set xCoord to (item 1 of avVector)

set yCoord to item 2 of avVector

set zCoord to (item 3 of avVector)

if item 1 of systemInfo is "MacBook5,2" then

set xCoord to -xCoord

set zCoord to -zCoord

end if


------- For a MacBook, set the rotation around the screen--------

------- which is assumed to be at a set angle to the base --------

ignoring case

if typeComputer is "Macbook" then

set yCoord to cosMacAdjust * yCoord + sinMacAdjust * zCoord

set zCoord to -sinMacAdjust * yCoord + cosMacAdjust * zCoord

end if

end ignoring



-------------- Calculate orientation --------------

set longMag to (xCoord ^ 2 + yCoord ^ 2) ^ 0.5

set displayOrient to 0

if longMag is greater than sinIgnore then


if yCoord / longMag is greater than sinFlip then

set displayOrient to 0

else

if yCoord / longMag is less than -sinFlip then

set displayOrient to 180

else

if xCoord / longMag is greater than cosFlip then

set displayOrient to 270

else

if xCoord / longMag is less than -cosFlip then

set displayOrient to 90

end if

end if

end if

end if

end if


--- Pause for a bit before repeating ---

delay orientCheckDelay


end repeat


---- Get System information: Model ID and Graphic chip set ----

on systemsInfo()

set TID to text item delimiters

set text item delimiters to ": "

set theModel to do shell script "/usr/sbin/system_profiler SPHardwareDataType | grep " & quoted form of "Model Identifier:"

set theModel to text item 2 of theModel

set theGraphics to do shell script "/usr/sbin/system_profiler SPDisplaysDataType | grep " & quoted form of "Chipset Model:"

set theGraphics to text item 2 of theGraphics

set text item delimiters to TID

return {theModel, theGraphics}

end systemsInfo


------- Use System Preferences Display Pane -------

------ to determine present display orientation -----

-------- return a -1 if there is an error --------

on getDisOrient()


tell application "System Events"

activate

set runningApps to the name of every process whose background only is false

if runningApps does not contain "System Preferences" then

return -1

end if

end tell


tell application "System Preferences"

activate

set current pane to pane "com.apple.preference.displays"

end tell


tell application "System Events"

get properties

tell process "System Preferences"

tell window 1

tell tab group 1

click radio button "Display"

try

click pop up button 1

tell pop up button 1

repeat with i from 1 to 4

if selected of menu item i of menu 1 is true then

exit repeat

end if

end repeat

delay 0.25

click menu item i of menu 1

set displayOrient to 90 * (i - 1)

end tell

on error

return -1

end try

end tell

end tell


end tell


end tell


return displayOrient

end getDisOrient



------- Use System Preferences Display Pane -------

----- to change the present display orientation -----

-------- return a -1 if there is an error --------

on ChangeDisOrient(displayOrient)

tell application "System Events"

set theFrontApp to name of (process 1 where it is frontmost)

end tell


tell application "System Events"

set runningApps to the name of every process whose background only is false

if runningApps does not contain "System Preferences" then return -1

end tell


tell application "System Preferences"

activate

set current pane to pane "com.apple.preference.displays"

end tell


set rotateItem to (displayOrient / 90 + 1) as integer

tell application "System Events"

get properties

tell process "System Preferences"

tell window 1

tell tab group 1

click radio button "Display"

try

click pop up button 1

tell pop up button 1

click menu item rotateItem of menu 1

end tell


on error

return -1

end try

end tell

end tell


if rotateItem is not 1 then

set success to 0

repeat until success is equal to 1

try

tell window 1

tell sheet 1

click button "Confirm"

set success to 1

end tell

end tell

on error errText

log errText

delay 1

end try

end repeat

end if


end tell

----quit

end tell


delay 0.1

tell application theFrontApp

activate

end tell


return displayOrient

end ChangeDisOrient


----- Work around for AppleScripting difficulties -----

-------- return a -1 if there is still an error --------

on rotationError()


tell application "System Preferences" to quit

delay 0.1

do shell script "open /Applications/System\\ Preferences.app"

delay 0.25

tell application "System Events"

activate

display alert "Display Rotation is Not Possible at the Moment." & return message "System Preferencences has opened. While holding both the Command and Option keys down, please click on the Displays icon (second row) in System Preferences. Then click the OK button on this text box — it will be behind the System Preferences window."


end tell

return getDisOrient()

end rotationError