Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

mac-mike

macrumors newbie
May 29, 2020
16
-13
Chicagoland
mac-mike said:


The posted code is AppleScriptObjC code, and not plain vanilla AppleScript.
So you can't save it as a script with a ".scpt" file extension, you can only save it as an application or text.
When you go to the "Save" menu option, and the save dialog box appears, select the Application or Text option from the "File Format:" combo box.

Secondly as previously stated, this code may not work as expected on "Big Sur", as I can only test here on "Mojave".
So my posting was aimed at Red Menace who knows AppleScriptObjC and has "Big Sur" to test with, so that he could come up with a solution for you.

Regards Mark
OK, I get why it can't be saved as a ".scpt" file, and that's also why I don't follow mostly what the script does; I know nothing about AppleScriptObjC! So saving it as an ".app" file instead may allow me to save it, but the result is still not what I need. I use random images from a specified folder for wallpaper, and this script shows me the folder name, but not, as has been pointed out, the image name. So it seems like I'm out of luck; Apple has made what used to be relatively straight-forward to produce, extraordinarily complex/impossible in Big Sur.

I don't know how it might help, but I found a discussion of this on another site and a couple of terminal commands that display the full path (with image name) on the screen. So it is able to identify the current image, but it's displayed in the ugliest possible format on the desktop until a second terminal command is issued to shut it off. So it also is not what I want, but it might be a step in the right direction. See:
 

Red Menace

macrumors 6502a
May 29, 2011
584
231
Colorado, USA
Note that AppleScript has historically saved persistent properties and global values in the script file itself (current versions of macOS don’t like that very much). Since Cocoa objects are usually pointers to stuff in the heap, that data can’t be saved. You can just recompile the script before saving it (or use Script Debugger, which is smart enough to know how to do that).

It looks like the desktop image files are in a Dock SQLite database for whatever reason, but I don’t know how they are getting the names (the indexes are not constant). The output shown in answer #15 is using the sqlite3 shell utility in the Terminal, but you can also use something like the following from a script:

AppleScript:
set databaseFile to POSIX path of (path to application support from user domain) & "Dock/desktoppicture.db"
set displayStuff to paragraphs of (do shell script "sqlite3 " & quoted form of databaseFile & " 'select * from data;'")
log result
 

mac-mike

macrumors newbie
May 29, 2020
16
-13
Chicagoland
Note that AppleScript has historically saved persistent properties and global values in the script file itself (current versions of macOS don’t like that very much). Since Cocoa objects are usually pointers to stuff in the heap, that data can’t be saved. You can just recompile the script before saving it (or use Script Debugger, which is smart enough to know how to do that).

It looks like the desktop image files are in a Dock SQLite database for whatever reason, but I don’t know how they are getting the names (the indexes are not constant). The output shown in answer #15 is using the sqlite3 shell utility in the Terminal, but you can also use something like the following from a script:

AppleScript:
set databaseFile to POSIX path of (path to application support from user domain) & "Dock/desktoppicture.db"
set displayStuff to paragraphs of (do shell script "sqlite3 " & quoted form of databaseFile & " 'select * from data;'")
log result
Thanks for your continued effort.

Well... on my Big Sur this Applescript runs without error, but the output is confusing. It doesn't display anything in the "Results" part of the Script Editor window. What does "log result" do?

I added a line in an attempt to see the results:

display dialog "Current Desktop picture is " & return & return & displayStuff buttons {"OK"} default button 1 with title "Desktop Image"

It appears to be displaying (maybe) the entire contents of desktoppicture.db, not the currently used image. And it seems like it might be the entire contents across all workspaces. So...it's not really useful for my objective to display the image name currently in use on the current workspace.

I don't think Apple could have obscured this information any more if they tried. I just don't know enough about sqlite or AppleScript to be able to overcome the problem.
 

Red Menace

macrumors 6502a
May 29, 2011
584
231
Colorado, USA
In the Script Editor, select View > Show Log menu item to see log statements.

Actually, it seems to only get weird(er) for multiple displays (I use 2). For a single display, the first item is the base folder, the third item is the base picture, and the last item is the name of the image, so you could do something like:

Code:
set databaseFile to POSIX path of (path to application support from user domain) & "Dock/desktoppicture.db"
set displayStuff to paragraphs of (do shell script "sqlite3 " & quoted form of databaseFile & " 'select value from data;'")
log result
tell displayStuff to set {baseFolder, fileName} to {first item, last item}
display dialog baseFolder & "/" & fileName with title "Desktop Image"
 
Last edited:

mac-mike

macrumors newbie
May 29, 2020
16
-13
Chicagoland
In the Script Editor, select View > Show Log menu item to see log statements.

Actually, it seems to only get weird(er) for multiple displays (I use 2). For a single display, the first item is the base folder, the third item is the base picture, and the last item is the name of the image, so you could do something like:

Code:
set databaseFile to POSIX path of (path to application support from user domain) & "Dock/desktoppicture.db"
set displayStuff to paragraphs of (do shell script "sqlite3 " & quoted form of databaseFile & " 'select value from data;'")
log result
tell displayStuff to set {baseFolder, fileName} to {first item, last item}
display dialog baseFolder & "/" & fileName with title "Desktop Image"
Well, we're suddenly almost home! This script does indeed show the image name, but it's having difficulty displaying the folder name (which I'm not concerned with). My system is a single display (MacBook Pro) with 8 workspaces. Each workspace uses a specified folder for wallpaper, so I know that already. The script shows the image name correctly but seems to show "0" (zero) for the folder name. As I said, I'm wanting the image name and that is shown:
Screen Shot 2021-12-12 at 8.36.14 PM.png
 

mac-mike

macrumors newbie
May 29, 2020
16
-13
Chicagoland
Well, it's really close, but not quite. After a wallpaper change, reading the current workspace, the script reports the correct image on a given workspace. However, it erroneously reports the same image on other workspaces, until the wallpaper changes again. Very weird.
 

Red Menace

macrumors 6502a
May 29, 2011
584
231
Colorado, USA
Yes, each display / space can have its own desktop image, so it can get weird in a hurry because the database is constantly changing. The Dock gets it right, so it should just be a matter of understanding what is happening with the database (theoretically). The following is the schema if any SQL gurus want to chime in:
Code:
sqlite> .schema
CREATE TABLE pictures (space_id INTEGER, display_id INTEGER);
CREATE TABLE preferences (key INTEGER, data_id INTEGER, picture_id INTEGER);
CREATE TABLE spaces (space_uuid VARCHAR);
CREATE TABLE displays (display_uuid);
CREATE TABLE data (value);
CREATE TABLE prefs (key INTEGER, data);
CREATE INDEX pictures_index ON pictures (space_id, display_id);
CREATE INDEX preferences_index ON preferences (picture_id, data_id);
CREATE INDEX spaces_index ON spaces (space_uuid);
CREATE INDEX displays_index ON displays (display_uuid);
CREATE INDEX data_index ON data (value);
CREATE INDEX prefs_index ON prefs (key);
CREATE TRIGGER space_deleted AFTER DELETE ON spaces BEGIN DELETE FROM pictures WHERE space_id=OLD.ROWID;END;
CREATE TRIGGER display_deleted AFTER DELETE ON displays BEGIN DELETE FROM pictures WHERE display_id=OLD.ROWID;END;
CREATE TRIGGER picture_deleted AFTER DELETE ON pictures BEGIN DELETE FROM preferences WHERE picture_id=OLD.ROWID; DELETE FROM displays WHERE ROWID=OLD.display_id AND NOT EXISTS (SELECT NULL FROM pictures WHERE display_id=OLD.display_id); DELETE FROM spaces WHERE ROWID=OLD.space_id AND NOT EXISTS (SELECT NULL FROM pictures WHERE space_id=OLD.space_id);END;
CREATE TRIGGER preferences_deleted AFTER DELETE ON preferences BEGIN DELETE FROM data WHERE ROWID=OLD.data_id AND NOT EXISTS (SELECT NULL FROM preferences WHERE data_id=OLD.data_id);END;
 

mac-mike

macrumors newbie
May 29, 2020
16
-13
Chicagoland
Yes, each display / space can have its own desktop image, so it can get weird in a hurry because the database is constantly changing. The Dock gets it right, so it should just be a matter of understanding what is happening with the database (theoretically). The following is the schema if any SQL gurus want to chime in:
Code:
sqlite> .schema
CREATE TABLE pictures (space_id INTEGER, display_id INTEGER);
CREATE TABLE preferences (key INTEGER, data_id INTEGER, picture_id INTEGER);
CREATE TABLE spaces (space_uuid VARCHAR);
CREATE TABLE displays (display_uuid);
CREATE TABLE data (value);
CREATE TABLE prefs (key INTEGER, data);
CREATE INDEX pictures_index ON pictures (space_id, display_id);
CREATE INDEX preferences_index ON preferences (picture_id, data_id);
CREATE INDEX spaces_index ON spaces (space_uuid);
CREATE INDEX displays_index ON displays (display_uuid);
CREATE INDEX data_index ON data (value);
CREATE INDEX prefs_index ON prefs (key);
CREATE TRIGGER space_deleted AFTER DELETE ON spaces BEGIN DELETE FROM pictures WHERE space_id=OLD.ROWID;END;
CREATE TRIGGER display_deleted AFTER DELETE ON displays BEGIN DELETE FROM pictures WHERE display_id=OLD.ROWID;END;
CREATE TRIGGER picture_deleted AFTER DELETE ON pictures BEGIN DELETE FROM preferences WHERE picture_id=OLD.ROWID; DELETE FROM displays WHERE ROWID=OLD.display_id AND NOT EXISTS (SELECT NULL FROM pictures WHERE display_id=OLD.display_id); DELETE FROM spaces WHERE ROWID=OLD.space_id AND NOT EXISTS (SELECT NULL FROM pictures WHERE space_id=OLD.space_id);END;
CREATE TRIGGER preferences_deleted AFTER DELETE ON preferences BEGIN DELETE FROM data WHERE ROWID=OLD.data_id AND NOT EXISTS (SELECT NULL FROM preferences WHERE data_id=OLD.data_id);END;
Thanks for the help, Red Menace! I worked with SQL databases back in the day, but it's been a long time and I've not investigated SQLite at all. I'm good to go (until Apple screws this all up again, probably with Monterrey). Your script from #30 (modified to ignore the folder) gives me the file name so I'm satisfied.

Happy Holidays!
 

aladdinh7

macrumors newbie
Aug 22, 2023
1
0
NC, USA
I know this is an old thread, but I am looking for a solution for Sonoma. I have posted below on apple's dev forums, but not getting any answers as of yet.

previous to SONOMA you had a few options to locate the currently displayed desktop wallpaper. you can change the DOCK preference to enable the option to display the wallpaper path on the desktop

[defaults write com.apple.dock desktop-picture-show-debug-text -bool TRUE;killall Dock]

but this does not seem to be working anymore.

you were also able to run a AppleScript to locate and display the wallpaper file. this was done by querying the desktoppicture.db. but it does not appear that SONOMA utilizes this file anymore.

Code:
-- Usage: osascript find_wall_pic n
--        n = 1 or 2 (monitor ID)
on replace_chars(this_text, search_string, replacement_string)
set AppleScript's text item delimiters to the search_string
set the item_list to every text item of this_text
set AppleScript's text item delimiters to the replacement_string
set this_text to the item_list as string
set AppleScript's text item delimiters to ""
return this_text
end replace_chars

on run argv
if (count of argv) < 1 then
set screenId to 1
else
set screenId to item 1 of argv as integer
end if
if screenId ≤ 1 then
set screenId to 1 -- 1st monior index
else
set screenId to 18 -- 2nd monitor index
end if

set posixaliaspath to (do shell script "/usr/bin/sqlite3 ~/Library/Application\\ Support/Dock/desktoppicture.db \"select d1.value || '/' || d2.value from preferences pf1 join data d1 on pf1.data_id=d1.rowid join preferences pf2 on pf1.picture_id=pf2.picture_id join data d2 on pf2.data_id=d2.rowid where pf1.key=10 and pf2.key=16 and pf1.picture_id=" & screenId & "\"") as string

set homepath to (do shell script "echo $HOME")
-- replace "~" in the path to actual $HOME dir
set posixaliaspath to replace_chars(posixaliaspath, "~", homepath)

set aliaspath to (POSIX file posixaliaspath) as string
set posixpath to POSIX path of aliaspath
set imgfile to POSIX file posixpath
-- tell application "Finder" to reveal imgfile
tell application "Finder"
activate
reveal imgfile
end tell
end run


I am looking for a solution similar to the AppleScript above, that can be run on demand to locate the file active on the desktop at that time. any ideas??
 

bongo_x

macrumors newbie
Mar 8, 2021
3
0
I know this is an old thread, but I am looking for a solution for Sonoma. I have posted below on apple's dev forums, but not getting any answers as of yet.

previous to SONOMA you had a few options to locate the currently displayed desktop wallpaper. you can change the DOCK preference to enable the option to display the wallpaper path on the desktop

[defaults write com.apple.dock desktop-picture-show-debug-text -bool TRUE;killall Dock]

but this does not seem to be working anymore.

you were also able to run a AppleScript to locate and display the wallpaper file. this was done by querying the desktoppicture.db. but it does not appear that SONOMA utilizes this file anymore.

Code:
-- Usage: osascript find_wall_pic n
--        n = 1 or 2 (monitor ID)
on replace_chars(this_text, search_string, replacement_string)
set AppleScript's text item delimiters to the search_string
set the item_list to every text item of this_text
set AppleScript's text item delimiters to the replacement_string
set this_text to the item_list as string
set AppleScript's text item delimiters to ""
return this_text
end replace_chars

on run argv
if (count of argv) < 1 then
set screenId to 1
else
set screenId to item 1 of argv as integer
end if
if screenId ≤ 1 then
set screenId to 1 -- 1st monior index
else
set screenId to 18 -- 2nd monitor index
end if

set posixaliaspath to (do shell script "/usr/bin/sqlite3 ~/Library/Application\\ Support/Dock/desktoppicture.db \"select d1.value || '/' || d2.value from preferences pf1 join data d1 on pf1.data_id=d1.rowid join preferences pf2 on pf1.picture_id=pf2.picture_id join data d2 on pf2.data_id=d2.rowid where pf1.key=10 and pf2.key=16 and pf1.picture_id=" & screenId & "\"") as string

set homepath to (do shell script "echo $HOME")
-- replace "~" in the path to actual $HOME dir
set posixaliaspath to replace_chars(posixaliaspath, "~", homepath)

set aliaspath to (POSIX file posixaliaspath) as string
set posixpath to POSIX path of aliaspath
set imgfile to POSIX file posixpath
-- tell application "Finder" to reveal imgfile
tell application "Finder"
activate
reveal imgfile
end tell
end run


I am looking for a solution similar to the AppleScript above, that can be run on demand to locate the file active on the desktop at that time. any ideas??
Ooh thanks. This one works to show me the picture on screen 2 under 10.14.6, even though I don't understand the syntax for selecting the screen.
I have some old ones that work great for screen 1, but that's the one that never changes for me.
Now I just need to figure out how to get screen 3!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.