Programmatically change screen saver settings - macos

I'm trying to programmatically change the configured screen saver.
If I do
$ defaults -currentHost read com.apple.screensaver
{
CleanExit = YES;
PrefsVersion = 100;
idleTime = 600;
moduleDict = {
moduleName = XXXX;
path = "/Users/juanjo/Library/Screen Savers/XXXX.saver";
type = 0;
};
showClock = 0;
}
I can see that info or even update it using the write parameter.
This settings are not accesibles via NSUserDefaults but they are via CF.
I was able to do this by code
var moduleDict = CFPreferencesCopyAppValue("moduleDict", "com.apple.screensaver") as CFDictionary
but when I try to get one value from that "dict" the program crash in this line:
var saverName = CFDictionaryGetValue(moduleDict, "moduleName")
saying EXC_BAD_ACCESS (code=EXC_I386_GPFLT).
So, do you know how can I read this values and write back?

As I mentioned in Cocoa-Dev list, I was able to do it this way.
Reading:
var moduleDict = CFPreferencesCopyAppValue("moduleDict", "com.apple.screensaver") as NSDictionary
var saverName = moduleDict["moduleName"] as String!
Writing:
var moduleDict = CFPreferencesCopyAppValue("moduleDict", "com.apple.screensaver") as NSDictionary
var mutable = moduleDict.mutableCopy() as NSMutableDictionary
mutable["moduleName"] = "MyScreenSaver"
mutable["path"] = mySaverPath
CFPreferencesSetValue("moduleDict", mutable as CFPropertyList, "com.apple.screensaver", kCFPreferencesCurrentUser, kCFPreferencesCurrentHost)
CFPreferencesAppSynchronize("com.apple.screensaver")

Related

Getting 'Error: AppleEvent handler failed' every time I run this script in Script Editor

Been struggling to get this script to work. It's meant to batch export notes out of Apple Notes. Script is below.
// set things up
var app = Application.currentApplication();
app.includeStandardAdditions = true;
var notesApp = Application('Notes');
notesApp.includeStandardAdditions = true;
// choose which notes
var notes = notesApp.notes;
var whichNotes = app.chooseFromList(notes.name(), { withPrompt: "Which Notes?", multipleSelectionsAllowed: true });
if (whichNotes) {
// choose save location
var saveWhere = app.chooseFolder().toString();
if (saveWhere) {
// loop through all notes
for(var i=0; i<notes.length; i++) {
// is this note one to be exported?
if (whichNotes.indexOf(notes[i].name()) > -1) {
// save file as html
var filename = saveWhere+"/"+notes[i].name()+".html";
var file = app.openForAccess(Path(filename), { writePermission: true });
app.setEof(file, { to: 0 });
app.write(notes[i].body(), {to: file});
app.closeAccess(file);
}
}
}
}
A bunch of other people have used it with no problems.
I have the same problem with the same script on 10.15.7. The issue is raised on notes.name().
I assume this is related to either too many notes (it used to work, but I created a lot of notes since), or some special char in the note title. But I did not managed to fix it with my notes.
I copied my version below.
(notice the replace to build a valid file name if your note title contain "/".)
// set things up
var app = Application.currentApplication();
app.includeStandardAdditions = true;
var notesApp = Application('Notes');
notesApp.includeStandardAdditions = true;
// choose which notes
var notes = notesApp.notes;
this.console.log("before notes.name()")
var whichNotes = app.chooseFromList(notes.name(), { withPrompt: "Which Notes?", multipleSelectionsAllowed: true });
this.console.log("After notes.name()")
this.console.log("Let's do it") // view / show log / message tab
if (whichNotes) {
// choose save location
var saveWhere = app.chooseFolder().toString();
if (saveWhere) {
this.console.log("note count:"+notes.length)
// loop through all notes
for(var i=0; i<notes.length; i++) {
// is this note one to be exported?
if (whichNotes.indexOf(notes[i].name()) > -1) {
// save file as html
var notename = notes[i].name().replace(/\//gi,'-')
this.console.log("next:"+notename) // view / show log / message tab
var filename = saveWhere+"/"+ notename +".html";
var file = app.openForAccess(Path(filename), { writePermission: true });
app.setEof(file, { to: 0 });
app.write(notes[i].body(), {to: file});
app.closeAccess(file);
}
}
}
}

Get samples of audio clip in AVAudioPlayer?

Is there a property on the AVAudioPlayer class that I can use to get the samples? If not is there another class I can use to get this information?
Here's what I have:
var openDialog = NSOpenPanel.OpenPanel;
openDialog.CanChooseFiles = true;
openDialog.CanChooseDirectories = false;
openDialog.AllowedFileTypes = new string[] { "wav" };
if (openDialog.RunModal() == 1)
{
var url = openDialog.Urls[0];
if (url != null)
{
var path = url.Path;
var audioplayer = AVFoundation.AVAudioPlayer.FromUrl(file);
var samples = audioplayer.SAMPLES?;
Visual Studio Mac (C# / Xamarin)
AVAudioPlayer does not give you access to the sample data, but if you switch playback to AVPlayer you can use an MTAudioProcessingTap to "tap" the samples as they are played.
If you simply want to examine the samples in your file you can use AVAudioFile.
// get the total number of samples
var audioFile = new AVAudioFile(file, out outError);
var samples = audioFile.Length;

Test for Firefox being hidden in OS X

Is there a way I test to see if Firefox windows are hidden in OS X via the "Hide Firefox" (Command-H) option? Enumerating using nsIWindowMediator says that the hidden attribute is false and the windowState is STATE_NORMAL for these hidden windows in OS X. Thanks!
Try console.log(window) or if you dont have access to thew indow object Services.appShell.hiddenDOMWindow.console.log(Services.wm.getMostRecentWindow('navigator:browser')) then in browser console go and click '[object ChromeWindow]' and then it will print all its enumerable and non-enumerable properties.
Maybe it will show something in here differently when it's hidden I'm not sure.
i dont know but heres a way that might help you figure out.
install this addon from github
and then in scratchpad in browser environment run Cu.import('chrome://cdumpjsm/content/cDump.jsm'); cDump(window,{depth:0}) when hidden, then save that file. then show the window then run cDump again, then diff the files
Ok at long last here is your solution. js-ctypes using objective-c:
Tested on OS 10.9
GitHubGIST :: Noitidart / _ff-addon-snippet-OSXHidden.js
Cu.import('resource://gre/modules/ctypes.jsm');
var objc = ctypes.open(ctypes.libraryName('objc'));
// types
var id = ctypes.voidptr_t;
var SEL = ctypes.voidptr_t;
var BOOL = ctypes.signed_char;
// constants
var nil = ctypes.voidptr_t(0);
//common functions
var objc_getClass = objc.declare('objc_getClass', ctypes.default_abi, id, ctypes.char.ptr);
var sel_registerName = objc.declare('sel_registerName', ctypes.default_abi, SEL, ctypes.char.ptr);
var objc_msgSend = objc.declare('objc_msgSend', ctypes.default_abi, id, id, SEL, '...');
//common selectors
var alloc = sel_registerName('alloc');
var init = sel_registerName('init');
var release = sel_registerName('release');
//now using docs here: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/index.html#//apple_ref/occ/instp/NSApplication/hidden
// pool = [[NSAutoreleasePool alloc] init]
var NSAutoreleasePool = objc_getClass('NSAutoreleasePool');
var pool = objc_msgSend(objc_msgSend(NSAutoreleasePool, alloc), init);
// NSApp = [NSApplication sharedApplication];
var NSApplication = objc_getClass('NSApplication');
var sharedApplication = sel_registerName('sharedApplication');
var NSApp = objc_msgSend(NSApplication, sharedApplication);
// [NSApp isHidden]
var isHidden = sel_registerName('isHidden');
var objc_msgSend_returnBool = objc.declare('objc_msgSend', ctypes.default_abi, BOOL, id, SEL, '...'); //this is return value because `isHidden` returns a BOOL per the docs
var rez_isHidden = objc_msgSend_returnBool(NSApp, isHidden);
console.info('rez_isHidden:', rez_isHidden, rez_isHidden.toString(), uneval(rez_isHidden));
if (rez_isHidden == 0) {
console.log('Firefox is HIDDEN!');
} else if (rez_isHidden == 1) {
console.log('Firefox is showing.');
} else {
console.warn('rez_isHidden was not 0 or 1, this should never happen, if it did, objc should error and crash the browser');
}
// [pool release]
objc_msgSend(pool, release);
objc.close();
Credit to #arai for teaching me objc jsctypes! When no one else would the guy spoon fed me!!! More people should spoon feed each other!

Can't animate a custom view

I'm trying to animate the movement of a custom view of mine using the following code (my best translation from objective-c from Apples own documents)
var animDict = new NSMutableDictionary ();
animDict [NSViewAnimation.TargetKey] = this.View;
animDict [NSViewAnimation.StartFrameKey] = NSValue.FromRectangleF (this.View.Frame);
animDict [NSViewAnimation.EndFrameKey] = NSValue.FromRectangleF (new RectangleF (0, 150 * index, 400, 150));
var theAnim = new NSViewAnimation ();
theAnim.SetValuesForKeysWithDictionary (animDict);
theAnim.Duration = 2;
theAnim.StartAnimation ();
However I get the following run-time error when running the app: 2011-05-08 00:53:30.827 EpisodeNext[61715:613] [ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key NSViewAnimationTargetKey.
Any idea what I'm doing wrong? Thanx!
You cannot use the method SetValuesForKeysWithDictionary to pass the animation keys to the NSViewAnimation instance.
You must use the NSViewAnimation(NSDictionary[] viewAnimations) constructor to pass the animation dictionary.
// Create the attributes dictionary for the first view.
NSMutableDictionary firstViewDict = new NSMutableDictionary ();
//var firstViewRect = new NSDictionary[] { };
firstViewDict [NSViewAnimation.TargetKey] = animateWindow;
firstViewDict [NSViewAnimation.StartFrameKey] = NSValue.FromRectangleF (new RectangleF (1000, 300 , this.Frame.Width - 40, 0));
firstViewDict [NSViewAnimation.EndFrameKey] = NSValue.FromRectangleF (SettingNSWindow.Frame);
//var NSDict = new NSDictionary[]{ };
NSDictionary[] NSDict = new NSDictionary[]{firstViewDict};
//NSDict.Cast(NSMutableDictionary = (NSDictionary[])firstViewDict;
NSViewAnimation theAnim = new NSViewAnimation(NSDict);
//theAnim.SetValuesForKeysWithDictionary (firstViewDict);
theAnim.Duration = 2;
theAnim.StartAnimation ();

AS3 URLRequest in for Loop problem

I read some data from a xml file, everything works great besides urls. I can't figure what's the problem with the "navigateURL" function or with the eventListener... on which square I click it opens the last url from the xml file
for(var i:Number = 0; i <= gamesInput.game.length() -1; i++)
{
var square:square_mc = new square_mc();
//xml values
var tGame_name:String = gamesInput.game.name.text()[i];//game name
var tGame_id:Number = gamesInput.children()[i].attributes()[2].toXMLString();//game id
var tGame_thumbnail:String = thumbPath + gamesInput.game.thumbnail.text()[i];//thumb path
var tGame_url:String = gamesInput.game.url.text()[i];//game url
addChild(square);
square.tgname_txt.text = tGame_name;
square.tgurl_txt.text = tGame_url;
//load & attach game thumb
var getThumb:URLRequest = new URLRequest(tGame_thumbnail);
var loadThumb:Loader = new Loader();
loadThumb.load(getThumb);
square.addChild(loadThumb);
//
square.y = squareY;
square.x = squareX;
squareX += square.width + 10;
square.buttonMode = true;
square.addEventListener(MouseEvent.CLICK, navigateURL);
}
function navigateURL(event:MouseEvent):void
{
var url:URLRequest = new URLRequest(tGame_url);
navigateToURL(url, "_blank");
trace(tGame_url);
}
Many thanks!
In navigateURL() you use tGame_url, but I think you'd rather use something like tgurl_txt.text which will be different for each square.
Looks like you're not attaching the event listener properly. Instead of this.addEventListener, attach it to the variable you created when creating new square_mc..... so:
square.addEventListener(MouseEvent.CLICK, navigateURL);
you should add the addEventListener on the Squares
mmm..still figuring how eventhandler function will ever get the correct tgame_url var.
What if you try this:
square.addEventListener(MouseEvent.CLICK, function navigateURL(event:MouseEvent):void
{
var url:URLRequest = new URLRequest(tGame_url);
navigateToURL(url, "_blank");
trace(tGame_url);
});
try tracing this:
function navigateURL(event:MouseEvent):void
{
var url:URLRequest = new URLRequest(tGame_url);
navigateToURL(url, "_blank");
//trace(tGame_url);
trace(event.currentTarget.tgurl_txt.text);
}
you should add the url to your square in the loop
square.theUrl = tGame_url;
in the event listener function you should be able to access it with
event.currentTarget.theUrl;

Resources