Search code examples
macosapplescriptitunesdesktop-background

How to activate full screen apps in background via Apple Script


I've been working on an application in Automator that changes the desktop background to the album art of the current song playing in iTunes.

You can download my first version here.

The most annoying issue I have found is that when there is a full screen app open on the same display being updated, whenever the song changes the background flickers between the current song and the previous.

This is my current code (Updated from version 1.0 above):
You may need to scroll within the code to see all of it.

tell application "System Events"
    set fileName to (((path to desktop) as text) & ".iTunesArt2-1.jpg")
    set oldFile to open for access file fileName with write permission
    write 0 to oldFile
    close access oldFile
    delete file fileName
    if process "iTunes" exists then
        tell application "iTunes"
            if (player state is not stopped) then
                -- get the raw bytes of the artwork into a var
                tell application "iTunes" to tell artwork 1 of current track
                    set srcBytes to raw data
                end tell
                -- write to file
                set outFile to open for access file fileName with write permission
                -- truncate the file
                set eof outFile to 0
                -- write the image bytes to the file
                write srcBytes to outFile
                close access outFile
            end if
        end tell
        tell desktop 2
            set picture to fileName
        end tell
    end if
    set fileName to (((path to desktop) as text) & ".iTunesArt2-2.jpg")
    set oldFile to open for access file fileName with write permission
    write 0 to oldFile
    close access oldFile
    delete file fileName
    if process "iTunes" exists then
        tell application "iTunes"
            if (player state is not stopped) then
                -- get the raw bytes of the artwork into a var
                tell application "iTunes" to tell artwork 1 of current track
                    set srcBytes to raw data
                end tell
                -- write to file
                set outFile to open for access file fileName with write permission
                -- truncate the file
                set eof outFile to 0
                -- write the image bytes to the file
                write srcBytes to outFile
                close access outFile
            end if
        end tell
        tell desktop 2
            set picture to fileName
        end tell
    end if
end tell

I got the actual code that saves the artwork to a file from here.

The desktop will not update unless you give it a new file name to update, therefore I have duplicated the process with "iTunesArt2-1" and "iTunesArt2-1".

The first 2 in '2-1' or '2-2' simply means the second desktop, as I have two different applications to change each desktop, and use my 2nd desktop for testing.

The entire application is set to loop for 1000 years, using three separate Loop functions in Automator (720 minutes, 730 times & 1000 times).

When first trying to debug this issue, the process was duplicated into four separate scripts, one for saving the image, then setting as background, and two more scripts to repeat the process with a new file name.

Here's an example of my debugging:

  1. I remove the opening period from ".iTunesArt##.jpg" so that I can see the files on my desktop.
  2. I play a Coldplay song and run the application in Automator to set the background.
  3. "iTunesArt2-1.jpg" and "iTunesArt2-2.jpg" are shown on my desktop with the correct album art.
  4. I stop the application, and play a Paramore song.
  5. I run the first script of the application (Saves the album art).
  6. "iTunesArt2-1.jpg" is updated to the Paramore artwork.
  7. I run the second script of the application (Sets background image).
    Note, this script should be setting the background to the Paramore image.
  8. The background remains set to the Coldplay image.

At first I think this is only because the background image was already set to "iTunesArt2-1.jpg", and therefore the system will not try to update it again, not knowing the data in the file has been changed.

So I run the next script which should force the background to update:

  1. I run the third script in the application.
  2. "iTunesArt2-2.jpg" is updated to the Paramore artwork.
  3. I run the forth script in the application.
  4. The desktop background is updated to the Paramore artwork.

So, we can confirm that scripts 3 & 4 worked correctly.
According to the code, when the application loops back to scripts 1 & 2, the desktop background should remain as the Paramore artwork.
BUT...

  1. I run the first script in the application.
  2. "iTunesArt2-1.jpg" remains the Paramore artwork (as it should).
  3. I run the second script in the application.
    This script should update the desktop background from ""iTunesArt2-2.jpg" (Paramore) to "iTunesArt2-1.jpg" (Paramore).
  4. The desktop background changes to the Coldplay artwork.

Now that makes zero sense at all.

This will happen every time I loop through the scripts.
Script 4 will change the desktop to Paramore and script 2 will change it back to Coldplay.

Remember this issue only happens when there is a full screen app open on the same display being updated. ie. A full screen app open on my primary display doesn't matter.

I have found sometimes that sliding over to the full screen app and 'activating' it will stop the flickering, and the background will be set correctly.

There surely is nothing 'wrong' with my code is there? If not, I need a way to get around this issue.

Specifically, is there a way of 'activating' every full screen app in the background without moving to those spaces?

I would love anyone who wants it to have this program, but it needs to be able to run under all circumstances.

Any help would be greatly appreciated.


Solution

  • Found a work around which creates a random file name each time, meaning the desktop can't get confused as to which image it is supposed to display.

    screenNum refers to which screen the desktop is being set to.

        set randID to screenNum
    set randLoop to 0
    repeat while randLoop is not 9
        set randNum to (random number from 0 to 9) as text
        set randID to randID & randNum
        set randLoop to randLoop + 1
    end repeat
    

    Then included randID in the file name upon its creation.

    Have not noticed any flickering using this method.

    Note: This solves my problem, but does not answer my initial question of how one can activate a full screen app in the background.