Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Automatically change the desktop picture Desktop
[Warning!! Do not run the script in the comments here! It will work, but after a few uses, it will cause minor system errors. Use at your own risk! See the comments for a discussion on alternatives and next steps...]

A posting over on the MacNN forums got me interested in trying to come up with a way to automatically change the desktop picture. If I can find a way to change it from the terminal, then the next steps become somewhat obvious (and maybe easy?) -- write a shell script to pick a file at random from a folder, and then issue the command to update the desktop pic and get it to display. Finally, schedule that shell script as a 'cron' job to run however often you'd like a new desktop picture.

I made a bit of progress, but not much. Please read the rest if you're interested in trying to help me figure out how to make desktop pictures change automatically...

Here's what I posted over on MacNN:

The current desktop image is stored in com.apple.finder.plist, which lives in:
/Users/username/Library/Preferences. The problem is, it's stored inside a key that contains all the finder prefs:
DesktopViewOptions = {
ArrangeBy = grid;
BackgroundFlags = 0;
BackgroundPictureURL = "file://localhost/path/to/pic.jpg";
BackgroundType = PctB;
IconSize = 48;
};
Those were my current settings, which you can read on your machine by typing defaults read comp.apple.finder. I was able to change the desktop picture by issuing the following command (NOTE: I've broken it up to keep the window width small, but this was all entered without hiting RETURN:
defaults write com.apple.finder "DesktopViewOptions" '{
"ArrangeBy" = grid; "BackgroundFlags" = 0;
"BackgroundPictureURL" = "file://localhost/path/to/newpic.jpg";
"BackgroundType" = PctB; "IconSize" = 48; }'
The problem is that if you just set the 'BackgroundPictureURL', you overwrite all the other Finder settings - I know, because I tried!. In digging around the 'man' pages for defaults, I didn't see any way to set just the one sub-key value for the "DesktopViewOptions" key; you either write one top-level key, or you whatever you write to the sub-key becomes the only value saved there.

The above does work if you then quit and relaunch the finder (which you can do from the terminal window as well, but I can't remember how -- I tested it with force-quit). The script would have to have some way of restarting the finder to make the desktop refresh.

I've about reached my UNIX skills limit, but it seems that there are two ways to make this work. The first (easiest) is if someone knows how to write to just the "BackgroundPictureURL" value in the key, instead of wiping out the whole key. The second would be to have a shell script first run the command "defaults read com.apple.finder DesktopViewOptions > tempfile", and then (perl?) parse the tempfile to replace the BackgroundPictureURL setting, then (somehow) take the contents of tempfile and place it back into the "defaults write com.apple.finder DesktopViewOptions" command.

Can anyone help move this forward a bit more? It may not be very practical, but it's teaching me more about UNIX and Mac OS X, which is a good thing.
    •    
  • Currently 2.25 / 5
  You rated: 2 / 5 (4 votes cast)
 
[8,081 views]  

Automatically change the desktop picture | 8 comments | Create New Account
Click here to return to the 'Automatically change the desktop picture' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
I know nothing about UNIX, but...
Authored by: GORDYmac on Mar 19, '01 07:13:56AM

Wouldn't it be simpler to just overwrite the current picture with the new one? You could have a folder of desktop pictures, all of which overwrite a pic file stored in another location. Good luck.



[ Reply to This | # ]
I know nothing about UNIX, but...
Authored by: robg on Mar 19, '01 08:19:27AM

Hmm, hadn't even thought about doing it that way! Sounds much simpler...thanks!

-rob.



[ Reply to This | # ]
I know nothing about UNIX, but...
Authored by: Anonymous on Mar 20, '01 09:34:04PM

I just tried that. No go.

The finder probably caches(?) the image and only updates it when you remove/place a new background.



[ Reply to This | # ]
Perl solution
Authored by: robh on Mar 19, '01 08:52:06AM

This Perl script seems to work. Don't blame me if it breaks anything :-). Note that I don't know if HUPing the Desktop process is the right way to activate the change but it seems to work.

#!/usr/bin/perl

# This is freeware, do whatever you want with it apart from passing it
# off as your own work.
# Use it at your own risk. It has been tested on Mac OSX Public Beta.
# Rob Hartill, 19/March/2001

use strict;

my $pic_dir = "/Users/rob/Documents/Images";  # change for local dir
my $prefs = `defaults read com.apple.finder`; # read existing finder prefs

# read all the jpeg images in the local dir
my $dirhandle;
opendir($dirhandle, $pic_dir) || die "Failed to open $pic_dir, $!";
my @jpegs = grep(/jpe?g$/i, readdir($dirhandle));
closedir($dirhandle);

# pick a random jpeg image
my $new_pic = $jpegs[rand(@jpegs)];

# insert the URL for the image
$prefs =~ s|(BackgroundPictureURL = )"?([^;]+)"?;|$1"file://localhost$pic_dir/$new_pic";|;
# switch on background image
$prefs =~ s/(BackgroundType = )"?([^;]+)"?;/${1}PctB;/;

# remove old finder prefs and replace with new prefs
print STDERR `defaults delete com.apple.finder`;
print STDERR `defaults write com.apple.finder '$prefs'`;

# find the process id of the 'Desktop' process
my $pid = `ps x | grep Desktop`;
$pid =~ s/^ ?(d+) .*/$1/;

# if we have a process id for the Desktop, send it a restart signal
if ($pid >0) {
    kill(1, $pid);
} else {
    die "Failed to find pid of Desktop processn";
}



[ Reply to This | # ]
Perl solution
Authored by: robh on Mar 20, '01 10:20:54AM

hold off using my script. After using it a few times it stops working - the kill signal to restart the Desktop process will eventually fail with the desktop error 'The system has detected a minor problem and repaired it. Some of your preferences may have changed'.

Anyone know of a way to talk to the Desktop (aka Finder) ?. I did some research into Applescript but couldn't locate anything that'd tell the process to refresh the root window. It's possible to communicate with Desktop with this ...
/usr/bin/osascript 'tell application "Desktop" to XXXX'
but I can't work out what instruction (XXXX) to give it.

I also prefer the other poster's suggestion of changing the picture file instead of the .finder prefs. It's easy to change my Perl script to do that, but there's still a need to find a way to tell Desktop to do the refresh.



[ Reply to This | # ]
Using Cocoa...
Authored by: Anonymous on Mar 20, '01 09:30:19PM
This is what I just whipped up:
- (IBAction)test:(id)sender
{
 NSDictionary *finderPrefs = [[NSUserDefaults standardUserDefaults] persistentDomainForName:@"com.apple.finder"];
 NSMutableDictionary *finderDict = [finderPrefs mutableCopy];
 NSMutableDictionary *subDict = [[finderDict objectForKey:@"DesktopViewOptions"] mutableCopy];
    [subDict setObject:@"file://localhost/Users/( ... )/whatever.jpg" forKey:@"BackgroundPictureURL"];
    [finderDict setObject:subDict forKey:@"DesktopViewOptions"];
 [[NSUserDefaults standardUserDefaults] setPersistentDomain:[NSDictionary dictionaryWithDictionary:finderDict] forName:@"com.apple.finder"];
  [[NSUserDefaults standardUserDefaults] synchronize];
//find someway to notify the Finder that the defaults have changed
// ...
 [finderDict release];
 [subDict release];
}
The problem then is not how to change the value but how to tell the Finder to update the background.



[ Reply to This | # ]
Automatically changing the desktop picture?
Authored by: Anonymous on Mar 21, '01 09:13:08AM

Wouldn't it be easier to do this via Applescript?



[ Reply to This | # ]
Solved! Perl/Applescript combo...
Authored by: Anonymous on Mar 31, '01 01:21:48AM

I got it working! The answer is to write a simple little applescript like so:
tell application "Finder" quit end tell tell application "Finder" activate end tell

Then, save it in Mac OS X Applet format from ScriptEditor, and put it in a useful directory. I used my users/me/Library/ folder, and put robh's perl script in there too, but with a little modification: Replace the part where he kills the finder by process id, with a call to the applescript like so:

# call applescript to restart finder print STDERR `open /Users/username/Library/finder_restart_applescript`;

Save this new script, chmod it so it's owner executable (chmod u+x scriptfile.pl), and set up a cron to run it (I cheated and used the CronniX app, which is a nice front end, look for it on versiontracker), and there you go!

This does forcibly quit the finder, so if you knew more applescript, you could have it throw up a warning to the user, or else just schedule it for three in the morning!

-kevin

[ Reply to This | # ]