Give more verbose errors.

Give more verbose errors.

--
--  DASAppDelegate.applescript
--  itunes-concatenator
--
--  Created by David Schlachter on 2014-08-26.
--  Copyright (c) 2014 Red Eft Software. All rights reserved.
--

-- via http://macscripter.net/viewtopic.php?pid=173787 ; apparently needed for using arrays

script DASAppDelegate
	property parent : class "NSObject"

    global these_files, these_times, these_titles, the_index, the_pipes, theCounter, cmdPrefix

	-- IBOutlets
	property window : missing value
    property trackTable : missing value
    property catName : missing value
    property catArtist : missing value
    property catAlbum : missing value
    property catComposer : missing value
    property catGenre : missing value
    property catTrack : missing value
    property catTracks : missing value
    property catDisc : missing value
    property catDiscs : missing value
    property catAlbumArtist : missing value
    property catYear : missing value
    property radioType : missing value
    property progressField : missing value
    property tocToLyrics : missing value

    -- Again, per macscripter, we'll set up bindings for the options
    property pcatName : ""
    property pcatArtist : ""
    property pcatAlbum : ""
    property pcatComposer : ""
    property pcatGenre : ""
    property pcatTrack : ""
    property pcatTracks : ""
    property pcatDisc : ""
    property pcatDiscs : ""
    property pcatAlbumArtist : ""
    property pcatYear : ""
    property missingPackages : ""
    property mediaTypeText : ""
    property tocToLyricsValue : ""

    -- This set is for the tags
    property fcatName : ""
    property fcatArtist : ""
    property fcatAlbum : ""
    property fcatComposer : ""
    property fcatGenre : ""
    property fcatTrack : ""
    property fcatTracks : ""
    property fcatDisc : ""
    property fcatDiscs : ""
    property fcatAlbumArtist : ""
    property fcatYear : ""

    -- Empty strings for each file name and location
    property pEachName : ""
    property pEachLocation : ""

    property mediaType : ""
    property theAddedTrack : ""

    property these_titles : {}
    property these_files : {}
    property these_times: {}
    property the_index: {}
    property the_pipes: {}

    property quitme : 0

    property theCounter : ""
    property cmdPrefix : "if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;"

    on awakeFromNib()
        -- Check for FFMPEG in the path
        try
            do shell script cmdPrefix & " if [ -x \"`/usr/bin/which ffmpeg`\" ];then exit 0;else exit 1;fi"
            on error number error_number
            set missingPackages to "FFMPEG "
            set ffmpegmissing to 1
        end try

        -- Check for MP4v2 in the path
        try
            do shell script cmdPrefix & " if [ -x \"`/usr/bin/which mp4chaps`\" ];then exit 0;else exit 1;fi"
            on error number error_number
            if ffmpegmissing is 1 then
                set missingPackages to "FFMPEG MP4v2"
            else
                set missingPackages to "MP4v2 "
            end if
        end try

        if missingPackages is not "" then
            display dialog "You must install the following programs to continue: \n\t" & missingPackages & " \n\nYou may have to install Xcode Command Line Tools and Homebrew first. If you continue, we'll attempt to install them for you if they are not already present. \n\nIf you have already installed FFMPEG and MP4v2, ensure that they are in your bash path." buttons {"Quit","Install"} default button 2
            if result = {button returned:"Install"} then
                tell application "Terminal"
                    set newTab to do script cmdPrefix & "if [[ -x `which brew` ]];then brew update;brew prune;brew install ffmpeg mp4v2 && exit 0;else /usr/bin/ruby -e \"$(/usr/bin/curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\";brew update;brew prune;brew install ffmpeg mp4v2 && exit 0;fi"
                    delay 1
                    activate
                    -- Check for when the Terminal is done
                    try
                        repeat
                            delay 0.2
                            if not busy of newTab then exit repeat
                        end repeat
                    end try
                end tell
                -- Check if installation was successful
                try
                    do shell script cmdPrefix & " if [ -x \"`/usr/bin/which ffmpeg`\" -a -x \"`/usr/bin/which mp4chaps`\" ];then exit 0;else exit 1;fi"
                    tell application "Terminal" to quit
                    activate
                    display dialog "Installation was successful!" buttons {"OK"} default button "OK"
                    on error error_number
                    activate
                    display dialog "Homebrew, FFMPEG and/or MP4v2 could not be installed."
                    set quitme to 1 -- Exit if we couldn't install!
                end try
                else if result = {button returned:"Quit"} then
                    set quitme to 1
                    return current application's NSTerminateNow
            end if
        end if
    end awakeFromNib

    on btnGetTracks_(sender)
        -- Code to add iTunes tracks to our list
        -- via http://dougscripts.com/itunes/itinfo/info02.php and http://www.randomsequence.com/articles/applescript-to-send-selected-itunes-tracks-using-mail/
        tell application "iTunes"
            set these_titles to {}
            set these_times to {}
            set these_files to {}
            set the_index to {}
            if selection is not {} then -- there ARE tracks selected...
                set mySelection to selection
                set i to 1
                repeat with aTrack in mySelection
                    if class of aTrack is file track then
                        set end of these_titles to ((name of aTrack) as string)
                        set end of these_times to ((time of aTrack) as string)
                        set end of these_files to (posix path of (get location of aTrack))
                        set end of the_index to (count of these_titles)
                        -- Get metadata from the first track
                        if i is 1 then
                            set pcatArtist to ((artist of aTrack) as string)
                            set pcatAlbum to ((album of aTrack) as string)
                            set pcatComposer to ((composer of aTrack) as string)
                            set pcatGenre to ((genre of aTrack) as string)
                            set pcatDisc to ((disc number of aTrack) as string)
                            set pcatDiscs to ((disc count of aTrack) as string)
                            set pcatAlbumArtist to ((album artist of aTrack) as string)
                            set pcatYear to ((year of aTrack) as string)
                        end if
                        set i to (i + 1)
                    end if
                end repeat
            end if
        end tell
        -- Display the songs to be concatenated
        -- via http://stackoverflow.com/questions/25537750/setstringvalue-with-applescript-list
        set olddelimeters to AppleScript's text item delimiters
        set AppleScript's text item delimiters to "\n"
        set disp_titles to these_titles as string
        trackTable's setStringValue_(disp_titles)
        set AppleScript's text item delimiters to olddelimeters
        -- Update the default metadata
        catArtist's setStringValue_(pcatArtist)
        catAlbum's setStringValue_(pcatAlbum)
        catComposer's setStringValue_(pcatComposer)
        catGenre's setStringValue_(pcatGenre)
        catDisc's setStringValue_(pcatDisc)
        catDiscs's setStringValue_(pcatDiscs)
        catAlbumArtist's setStringValue_(pcatAlbumArtist)
        catYear's setStringValue_(pcatYear)
        -- Reset the name and track fields
        catName's setStringValue_("")
        catTrack's setStringValue_("")
        catTracks's setStringValue_("")
    end btnGetTracks_

    on btnConcatenate_(sender)
        -- Update the metadata variables with the user's input
        if catName's stringValue() is not "" then set pcatName to catName's stringValue()
        set pcatArtist to catArtist's stringValue()
        set pcatAlbum to catAlbum's stringValue()
        set pcatComposer to catComposer's stringValue()
        set pcatGenre to catGenre's stringValue()
        set pcatTrack to catTrack's stringValue()
        set pcatTracks to catTracks's stringValue()
        set pcatDisc to catDisc's stringValue()
        set pcatDiscs to catDiscs's stringValue()
        set pcatAlbumArtist to catAlbumArtist's stringValue()
        set pcatYear to catYear's stringValue()
        set the_pipes to {}
        set mediaTypeText to (radioType's titleOfSelectedItem()) as string
        set tocToLyricsValue to (tocToLyrics's state())

        try
            do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.chapters.txt /private/tmp/cat.m4* /private/tmp/cat.mp4"
        end try
        -- Initialize some variables
        set errorHappened to false
        set notaac to false
        set bitrate to 0
         -- Check if the audio files are all aac / mp4a
        progressField's setStringValue_("Determining filetypes...")
         delay 0.2
        repeat with theIndex in the_index
            set thefile to (quoted form of POSIX path of (item theIndex of these_files as text))
            if not notaac
                try
                    do shell script (cmdPrefix & "if [ `ffprobe -show_streams -select_streams a " & thefile & "  2>/dev/null | grep -c \"mp4a\\|aac\"` -gt 0 ]; then exit 0; else exit 1; fi")
                on error number error_number
                    set notaac to true
                end try
            end if
            try
                set newbitrate to (do shell script (cmdPrefix & "ffprobe -show_streams -select_streams a " & thefile & " 2>/dev/null | grep '^bit_rate=' | sed 's/bit_rate=\\([0-9][0-9]*\\)/\\1/' | sed 's/\\(.*\\).\\{3\\}/\\1/'") as text)
                if (newbitrate as number) is greater than (bitrate as number) then set bitrate to (newbitrate as number)
            end try
        end repeat
        set bitrate to bitrate as number
        if bitrate = 0 then set bitrate to 256
        -- Create the concatenated intermediate file
        if not notaac then
            -- Concatenation routine for mp4/aac files
            try
                repeat with theIndex in the_index
                    progressField's setStringValue_("Preparing track " & (theIndex as text) & "..." as text)
                    delay 0.2
                    do shell script (cmdPrefix & "ffmpeg -i " & (quoted form of POSIX path of (item theIndex of these_files as text)) & " -c copy -f mpegts -loglevel fatal -vn /private/tmp/concat" & theIndex & ".ts" as text)
                    set end of the_pipes to ("/private/tmp/concat" & theIndex & ".ts" as text)
                end repeat
            on error error_number number therror
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat*"
                progressField's setStringValue_("")
                display dialog "The tracks you selected could not be joined. An error occured when preparing the intermediate files. The error code was " & therror & ": " & error_number
            end try
            try
                set olddelimeters to AppleScript's text item delimiters
                set AppleScript's text item delimiters to "|"
                set disp_thepipes to the_pipes as string
                progressField's setStringValue_("Concatenating tracks...")
                delay 0.2
                do shell script (cmdPrefix & "ffmpeg -f mpegts -i \"concat:" & (disp_thepipes as text) & "\" -c copy -bsf:a aac_adtstoasc -loglevel fatal /private/tmp/cat.mp4" as text)
                set AppleScript's text item delimiters to olddelimeters
            on error error_number number therror
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4"
                progressField's setStringValue_("")
                display dialog "The tracks could not be joined. The error code was " & therror & ": " & error_number
            end try
            else
            -- Concatenation routine for non-mp4/aac audio files
            try
                repeat with theIndex in the_index
                    progressField's setStringValue_("Preparing track " & (theIndex as text) & "..." as text)
                    delay 0.2
                    -- No spaces allowed in paths for the script...
                    do shell script ("/bin/cp " & (quoted form of POSIX path of (item theIndex of these_files as text)) & " /private/tmp/concat" & theIndex & ".ts" as text)
                    set end of the_pipes to ("concat" & theIndex & ".ts" as text)
                end repeat
            on error error_number number therror
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat*"
                progressField's setStringValue_("")
                display dialog "The tracks you selected could not be joined. The error code was " & therror & ": " & error_number
            end try
            set olddelimeters to AppleScript's text item delimiters
            set AppleScript's text item delimiters to " "
            set disp_thepipes to the_pipes as string
            progressField's setStringValue_("Concatenating tracks...")
            delay 0.2
            try
                set scriptpath to (quoted form of POSIX path of (current application's NSBundle's mainBundle()'s bundlePath() as text & "/Contents/Resources/mmcat.sh")) & " "
                do shell script ("cd /private/tmp && " & scriptpath & (bitrate as text) & " " & (disp_thepipes as text) & " cat.mp4" as text)
            on error error_number number therror
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4"
                progressField's setStringValue_("")
                display dialog "The tracks could not be joined. An error occured during the reencoding. The error code was " & therror & ": " & error_number
            end try
            set AppleScript's text item delimiters to olddelimeters
        end if
        -- Now let's create the chapter file
        if not errorHappened then
            progressField's setStringValue_("Preparing chapters...")
            delay 0.2
            try
                repeat with theIndex in the_index
                    if theIndex < 2 then
                        do shell script ("/bin/echo \"00:00:00.000 " & (item theIndex of these_titles as text) & "\" > /private/tmp/cat.chapters.txt" as text)
                        set theCounter to (do shell script (cmdPrefix & "ffprobe -loglevel panic -show_streams /private/tmp/concat" & (theIndex as text) & ".ts | egrep -m 1 'duration=[0-9]+\\.' | sed 's/duration=\\([0-9]*[0-9]\\.[0-9]*\\)/\\1/'" as text) as string)
                        set theCounter to (do shell script ("/bin/echo $(/usr/bin/printf %.$2f $(/bin/echo \"`/usr/bin/printf %.3f " & theCounter & "` * 1000\" | /usr/bin/bc))") as string)
                    else
                        set theDateStamp to do shell script (cmdPrefix & "t="& (theCounter as text) & ";((msec=t%1000, t/=1000, sec=t%60, t/=60, min=t%60, hrs=t/60));timestamp=$(printf \"%02d:%02d:%02d.%03d\" $hrs $min $sec $msec);/bin/echo $timestamp" as text)
                        do shell script ("/bin/echo \"" & (theDateStamp as text) & " " & (item theIndex of these_titles as text) & "\" >> /private/tmp/cat.chapters.txt" as text)
                        set theNewCounter to do shell script ((cmdPrefix & "ffprobe -loglevel panic -show_streams /private/tmp/concat" & (theIndex as text) & ".ts | egrep -m 1 'duration=[0-9]+\\.' | sed 's/duration=\\([0-9]*[0-9]\\.[0-9]*\\)/\\1/'" as text) as string)
                        set theNewCounter to do shell script ("/bin/echo $(/usr/bin/printf %.$2f $(/bin/echo \"`/usr/bin/printf %.3f " & theNewCounter & "` * 1000\" | /usr/bin/bc))") as string
                        set theCounter to (theCounter + theNewCounter)
                    end if
                end repeat
            on error error_number number therror
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt"
                progressField's setStringValue_("")
                display dialog "The chapters could not be read from the tracks you had selected. The error code was " & therror & ": " & error_number
            end try
        end if
        -- Chapterize cat.mp4
        if not errorHappened then
            try
                progressField's setStringValue_("Chapterizing...")
                delay 0.2
                do shell script (cmdPrefix & "mp4chaps -i /private/tmp/cat.mp4" as text)
            on error error_number number therror
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt"
                progressField's setStringValue_("")
                display dialog "The chapters could not be added to concatenated file. The error code was " & therror & ": " & error_number
            end try
        end if
        -- Prepare tags
        if pcatName is not "" then set fcatName to (" -song " & quoted form of (pcatName as text) & " ")
        if fcatName contains "\"\"" then set fcatName to ""
        if pcatAlbum is not "" then set fcatAlbum to (" -album " & quoted form of (pcatAlbum as text) & " ")
        if fcatAlbum contains "\"\"" then set fcatAlbum to ""
        if pcatArtist is not "" then set fcatArtist to (" -artist " & quoted form of (pcatArtist as text) & " ")
        if fcatArtist contains "\"\"" then set fcatArtist to ""
        if pcatComposer is not "" then set fcatComposer to (" -writer " & quoted form of (pcatComposer as text) & " ")
        if fcatComposer contains "\"\"" then set fcatComposer to ""
        if pcatGenre is not "" then set fcatGenre to (" -genre " & quoted form of (pcatGenre as text) & " ")
        if fcatGenre contains "\"\"" then set fcatGenre to ""
        if pcatTrack is not "" then set fcatTrack to (" -track \"" & pcatTrack & "\" ")
        if fcatTrack contains "\"\"" then set fcatTrack to ""
        if pcatTracks is not "" then set fcatTracks to (" -tracks \"" & pcatTracks & "\" ")
        if fcatTracks contains "\"\"" then set fcatTracks to ""
        if pcatDisc is not "" then set fcatDisc to (" -disk \"" & pcatDisc & "\" ")
        if fcatDisc contains "\"\"" then set fcatDisc to ""
        if pcatDiscs is not "" then set fcatDiscs to (" -disks \"" & pcatDiscs & "\" ")
        if fcatDiscs contains "\"\"" then set fcatDiscs to ""
        if pcatAlbumArtist is not "" then set fcatAlbumArtist to (" -albumartist " & quoted form of (pcatAlbumArtist as text) & " ")
        if fcatAlbumArtist contains "\"\"" then set fcatAlbumArtist to ""
        if pcatYear is not "" then set fcatYear to (" -year \"" & pcatYear & "\" ")
        if fcatYear contains "\"\"" then set fcatYear to ""
        -- Add tags
        if not errorHappened then
            try
                progressField's setStringValue_("Adding tags...")
                delay 0.2
                do shell script (cmdPrefix & "mp4tags " & fcatName & fcatAlbum & fcatArtist & fcatComposer & fcatGenre & fcatTrack & fcatTracks & fcatDisc & fcatDiscs & fcatAlbumArtist & fcatYear & " /private/tmp/cat.mp4" as text)
            on error error_number number therror
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt"
                progressField's setStringValue_("")
                display dialog "The tags could not be added to the concatenated audio file. The error code was " & therror & ": " & error_number
            end try
        end if
        -- Grab the TOC, if needed
        if not errorHappened then
            if tocToLyricsValue is 1 then
                progressField's setStringValue_("Getting TOC...")
                delay 0.2
                try
                    set tocText to (do shell script "/bin/cat /private/tmp/cat.chapters.txt")
                on error error_number number therror
                    set errorHappened to true
                    do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt"
                    progressField's setStringValue_("")
                    display dialog "The TOC could not be processed. The error code was " & therror & ": " & error_number
                end try
            end if
        end if
        -- Add the finished track to iTunes
        if not errorHappened then
            progressField's setStringValue_("Adding to iTunes...")
            delay 0.2
            try
                if mediaTypeText is "Music track" then
                    set mediaType to "m4a" as text
                else if mediaTypeText is "Audiobook track" then
                    set mediaType to "m4b" as text
                end if
                do shell script ("/bin/mv /private/tmp/cat.mp4 /private/tmp/cat." & mediaType as text)
                tell application "iTunes"
                    set aliasPath to POSIX file ("/private/tmp/cat." & mediaType as text) as alias
                    set theAddedTrack to (add aliasPath)
                end tell
            on error error_number number therror
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt /private/tmp/cat." & mediaType
                progressField's setStringValue_("")
                display dialog "The concatenated file could not be added to iTunes.  The error code was " & therror & ": " & error_number
            end try
        end if
        if not errorHappened and tocToLyricsValue is 1 then
            progressField's setStringValue_("Adding TOC...")
            delay 0.2
            try
                tell application "iTunes"
                        set lyrics of theAddedTrack to tocText
                end tell
            on error error_number number therror
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt /private/tmp/cat." & mediaType
                progressField's setStringValue_("")
                set the clipboard to tocText
                display dialog "The lyrics tag for the TOC could not be set in iTunes. The error code was " & therror & ": " & error_number & " The TOC has been copied to the clipboard instead."
            end try
        end if
        -- Clean up
        do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.chapters.txt /private/tmp/cat.m4*"
        set theCounter to ""
        progressField's setStringValue_("")
    end btnConcatenate_

	on applicationWillFinishLaunching_(aNotification)
        -- Insert code here to initialize your application before any files are opened
        if quitme is 1 then
            tell me to quit
        end if
	end applicationWillFinishLaunching_

	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits
		return current application's NSTerminateNow
	end applicationShouldTerminate_

end script

--
--  DASAppDelegate.applescript
--  itunes-concatenator
--
--  Created by David Schlachter on 2014-08-26.
--  Copyright (c) 2014 Red Eft Software. All rights reserved.
--

-- via http://macscripter.net/viewtopic.php?pid=173787 ; apparently needed for using arrays

script DASAppDelegate
	property parent : class "NSObject"

    global these_files, these_times, these_titles, the_index, the_pipes, theCounter, cmdPrefix

	-- IBOutlets
	property window : missing value
    property trackTable : missing value
    property catName : missing value
    property catArtist : missing value
    property catAlbum : missing value
    property catComposer : missing value
    property catGenre : missing value
    property catTrack : missing value
    property catTracks : missing value
    property catDisc : missing value
    property catDiscs : missing value
    property catAlbumArtist : missing value
    property catYear : missing value
    property radioType : missing value
    property progressField : missing value
    property tocToLyrics : missing value

    -- Again, per macscripter, we'll set up bindings for the options
    property pcatName : ""
    property pcatArtist : ""
    property pcatAlbum : ""
    property pcatComposer : ""
    property pcatGenre : ""
    property pcatTrack : ""
    property pcatTracks : ""
    property pcatDisc : ""
    property pcatDiscs : ""
    property pcatAlbumArtist : ""
    property pcatYear : ""
    property missingPackages : ""
    property mediaTypeText : ""
    property tocToLyricsValue : ""

    -- This set is for the tags
    property fcatName : ""
    property fcatArtist : ""
    property fcatAlbum : ""
    property fcatComposer : ""
    property fcatGenre : ""
    property fcatTrack : ""
    property fcatTracks : ""
    property fcatDisc : ""
    property fcatDiscs : ""
    property fcatAlbumArtist : ""
    property fcatYear : ""

    -- Empty strings for each file name and location
    property pEachName : ""
    property pEachLocation : ""

    property these_titles : {}
    property these_files : {}
    property these_times: {}
    property the_index: {}
    property the_pipes: {}

    property quitme : 0

    property theCounter : ""
    property cmdPrefix : "if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;"

    on awakeFromNib()
        -- Check for FFMPEG in the path
        try
            do shell script cmdPrefix & " if [ -x \"`/usr/bin/which ffmpeg`\" ];then exit 0;else exit 1;fi"
            on error number error_number
            set missingPackages to "FFMPEG "
            set ffmpegmissing to 1
        end try

        -- Check for MP4v2 in the path
        try
            do shell script cmdPrefix & " if [ -x \"`/usr/bin/which mp4chaps`\" ];then exit 0;else exit 1;fi"
            on error number error_number
            if ffmpegmissing is 1 then
                set missingPackages to "FFMPEG MP4v2"
            else
                set missingPackages to "MP4v2 "
            end if
        end try

        if missingPackages is not "" then
            display dialog "You must install the following programs to continue: \n\t" & missingPackages & " \n\nYou may have to install Xcode Command Line Tools and Homebrew first. If you continue, we'll attempt to install them for you if they are not already present. \n\nIf you have already installed FFMPEG and MP4v2, ensure that they are in your bash path." buttons {"Quit","Install"} default button 2
            if result = {button returned:"Install"} then
                tell application "Terminal"
                    set newTab to do script cmdPrefix & "if [[ -x `which brew` ]];then brew update;brew prune;brew install ffmpeg mp4v2 && exit 0;else /usr/bin/ruby -e \"$(/usr/bin/curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\";brew update;brew prune;brew install ffmpeg mp4v2 && exit 0;fi"
                    delay 1
                    activate
                    -- Check for when the Terminal is done
                    try
                        repeat
                            delay 0.2
                            if not busy of newTab then exit repeat
                        end repeat
                    end try
                end tell
                -- Check if installation was successful
                try
                    do shell script cmdPrefix & " if [ -x \"`/usr/bin/which ffmpeg`\" -a -x \"`/usr/bin/which mp4chaps`\" ];then exit 0;else exit 1;fi"
                    tell application "Terminal" to quit
                    activate
                    display dialog "Installation was successful!" buttons {"OK"} default button "OK"
                    on error error_number
                    activate
                    display dialog "Homebrew, FFMPEG and/or MP4v2 could not be installed."
                    set quitme to 1 -- Exit if we couldn't install!
                end try
                else if result = {button returned:"Quit"} then
                    set quitme to 1
                    return current application's NSTerminateNow
            end if
        end if
    end awakeFromNib

    on btnGetTracks_(sender)
        -- Code to add iTunes tracks to our list
        -- via http://dougscripts.com/itunes/itinfo/info02.php and http://www.randomsequence.com/articles/applescript-to-send-selected-itunes-tracks-using-mail/
        tell application "iTunes"
            set these_titles to {}
            set these_times to {}
            set these_files to {}
            set the_index to {}
            if selection is not {} then -- there ARE tracks selected...
                set mySelection to selection
                set i to 1
                repeat with aTrack in mySelection
                    if class of aTrack is file track then
                        set end of these_titles to ((name of aTrack) as string)
                        set end of these_times to ((time of aTrack) as string)
                        set end of these_files to (posix path of (get location of aTrack))
                        set end of the_index to (count of these_titles)
                        -- Get metadata from the first track
                        if i is 1 then
                            set pcatArtist to ((artist of aTrack) as string)
                            set pcatAlbum to ((album of aTrack) as string)
                            set pcatComposer to ((composer of aTrack) as string)
                            set pcatGenre to ((genre of aTrack) as string)
                            set pcatDisc to ((disc number of aTrack) as string)
                            set pcatDiscs to ((disc count of aTrack) as string)
                            set pcatAlbumArtist to ((album artist of aTrack) as string)
                            set pcatYear to ((year of aTrack) as string)
                        end if
                        set i to (i + 1)
                    end if
                end repeat
            end if
        end tell
        -- Display the songs to be concatenated
        -- via http://stackoverflow.com/questions/25537750/setstringvalue-with-applescript-list
        set olddelimeters to AppleScript's text item delimiters
        set AppleScript's text item delimiters to "\n"
        set disp_titles to these_titles as string
        trackTable's setStringValue_(disp_titles)
        set AppleScript's text item delimiters to olddelimeters
        -- Update the default metadata
        catArtist's setStringValue_(pcatArtist)
        catAlbum's setStringValue_(pcatAlbum)
        catComposer's setStringValue_(pcatComposer)
        catGenre's setStringValue_(pcatGenre)
        catDisc's setStringValue_(pcatDisc)
        catDiscs's setStringValue_(pcatDiscs)
        catAlbumArtist's setStringValue_(pcatAlbumArtist)
        catYear's setStringValue_(pcatYear)
        -- Reset the name and track fields
        catName's setStringValue_("")
        catTrack's setStringValue_("")
        catTracks's setStringValue_("")
    end btnGetTracks_

    on btnConcatenate_(sender)
        -- Update the metadata variables with the user's input
        if catName's stringValue() is not "" then set pcatName to catName's stringValue()
        set pcatArtist to catArtist's stringValue()
        set pcatAlbum to catAlbum's stringValue()
        set pcatComposer to catComposer's stringValue()
        set pcatGenre to catGenre's stringValue()
        set pcatTrack to catTrack's stringValue()
        set pcatTracks to catTracks's stringValue()
        set pcatDisc to catDisc's stringValue()
        set pcatDiscs to catDiscs's stringValue()
        set pcatAlbumArtist to catAlbumArtist's stringValue()
        set pcatYear to catYear's stringValue()
        set the_pipes to {}
        set mediaTypeText to (radioType's titleOfSelectedItem()) as string
        set tocToLyricsValue to (tocToLyrics's state())

        try
            do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.chapters.txt /private/tmp/cat.m4* /private/tmp/cat.mp4"
        end try
        -- Initialize some variables
        set errorHappened to false
        set notaac to false
        set bitrate to 0
         -- Check if the audio files are all aac / mp4a
        progressField's setStringValue_("Determining filetypes...")
         delay 0.2
        repeat with theIndex in the_index
            set thefile to (quoted form of POSIX path of (item theIndex of these_files as text))
            if not notaac
                try
                    do shell script (cmdPrefix & "if [ `ffprobe -show_streams -select_streams a " & thefile & "  2>/dev/null | grep -c \"mp4a\\|aac\"` -gt 0 ]; then exit 0; else exit 1; fi")
                on error number error_number
                    set notaac to true
                end try
            end if
            try
                set newbitrate to (do shell script (cmdPrefix & "ffprobe -show_streams -select_streams a " & thefile & " 2>/dev/null | grep '^bit_rate=' | sed 's/bit_rate=\\([0-9][0-9]*\\)/\\1/' | sed 's/\\(.*\\).\\{3\\}/\\1/'") as text)
                if (newbitrate as number) is greater than (bitrate as number) then set bitrate to (newbitrate as number)
            end try
        end repeat
        set bitrate to bitrate as number
        if bitrate = 0 then set bitrate to 256
        -- Create the concatenated intermediate file
        if not notaac then
            -- Concatenation routine for mp4/aac files
            try
                repeat with theIndex in the_index
                    progressField's setStringValue_("Preparing track " & (theIndex as text) & "..." as text)
                    delay 0.2
                    do shell script (cmdPrefix & "ffmpeg -i " & (quoted form of POSIX path of (item theIndex of these_files as text)) & " -c copy -f mpegts -loglevel fatal -vn /private/tmp/concat" & theIndex & ".ts" as text)
                    set end of the_pipes to ("/private/tmp/concat" & theIndex & ".ts" as text)
                end repeat
            on error error_number
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat*"
                progressField's setStringValue_("")
                display dialog "The tracks you selected could not be joined. An error occured when preparing the intermediate files."
            end try
            try
                set olddelimeters to AppleScript's text item delimiters
                set AppleScript's text item delimiters to "|"
                set disp_thepipes to the_pipes as string
                progressField's setStringValue_("Concatenating tracks...")
                delay 0.2
                do shell script (cmdPrefix & "ffmpeg -f mpegts -i \"concat:" & (disp_thepipes as text) & "\" -c copy -bsf:a aac_adtstoasc -loglevel fatal /private/tmp/cat.mp4" as text)
                set AppleScript's text item delimiters to olddelimeters
            on error error_number
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4"
                progressField's setStringValue_("")
                display dialog "The tracks could not be joined."
            end try
            else
            -- Concatenation routine for non-mp4/aac audio files
            try
                repeat with theIndex in the_index
                    progressField's setStringValue_("Preparing track " & (theIndex as text) & "..." as text)
                    delay 0.2
                    -- No spaces allowed in paths for the script...
                    do shell script ("/bin/cp " & (quoted form of POSIX path of (item theIndex of these_files as text)) & " /private/tmp/concat" & theIndex & ".ts" as text)
                    set end of the_pipes to ("concat" & theIndex & ".ts" as text)
                end repeat
            on error error_number
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat*"
                progressField's setStringValue_("")
                display dialog "The tracks you selected could not be joined."
            end try
            set olddelimeters to AppleScript's text item delimiters
            set AppleScript's text item delimiters to " "
            set disp_thepipes to the_pipes as string
            progressField's setStringValue_("Concatenating tracks...")
            delay 0.2
            try
                set scriptpath to (quoted form of POSIX path of (current application's NSBundle's mainBundle()'s bundlePath() as text & "/Contents/Resources/mmcat.sh")) & " "
                do shell script ("cd /private/tmp && " & scriptpath & (bitrate as text) & " " & (disp_thepipes as text) & " cat.mp4" as text)
            on error error_number
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4"
                progressField's setStringValue_("")
                display dialog "The tracks could not be joined. An error occured during the reencoding."
            end try
            set AppleScript's text item delimiters to olddelimeters
        end if
        -- Now let's create the chapter file
        if not errorHappened then
            progressField's setStringValue_("Preparing chapters...")
            delay 0.2
            try
                repeat with theIndex in the_index
                    if theIndex < 2 then
                        do shell script ("/bin/echo \"00:00:00.000 " & (item theIndex of these_titles as text) & "\" > /private/tmp/cat.chapters.txt" as text)
                        set theCounter to (do shell script (cmdPrefix & "ffprobe -loglevel panic -show_streams /private/tmp/concat" & (theIndex as text) & ".ts | egrep -m 1 'duration=[0-9]+\\.' | sed 's/duration=\\([0-9]*[0-9]\\.[0-9]*\\)/\\1/'" as text) as string)
                        set theCounter to (do shell script ("/bin/echo $(/usr/bin/printf %.$2f $(/bin/echo \"`/usr/bin/printf %.3f " & theCounter & "` * 1000\" | /usr/bin/bc))") as string)
                    else
                        set theDateStamp to do shell script (cmdPrefix & "t="& (theCounter as text) & ";((msec=t%1000, t/=1000, sec=t%60, t/=60, min=t%60, hrs=t/60));timestamp=$(printf \"%02d:%02d:%02d.%03d\" $hrs $min $sec $msec);/bin/echo $timestamp" as text)
                        do shell script ("/bin/echo \"" & (theDateStamp as text) & " " & (item theIndex of these_titles as text) & "\" >> /private/tmp/cat.chapters.txt" as text)
                        set theNewCounter to do shell script ((cmdPrefix & "ffprobe -loglevel panic -show_streams /private/tmp/concat" & (theIndex as text) & ".ts | egrep -m 1 'duration=[0-9]+\\.' | sed 's/duration=\\([0-9]*[0-9]\\.[0-9]*\\)/\\1/'" as text) as string)
                        set theNewCounter to do shell script ("/bin/echo $(/usr/bin/printf %.$2f $(/bin/echo \"`/usr/bin/printf %.3f " & theNewCounter & "` * 1000\" | /usr/bin/bc))") as string
                        set theCounter to (theCounter + theNewCounter)
                    end if
                end repeat
            on error error_number
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt"
                progressField's setStringValue_("")
                display dialog "The chapters could not be read from the tracks you had selected."
            end try
        end if
        -- Chapterize cat.mp4
        if not errorHappened then
            try
                progressField's setStringValue_("Chapterizing...")
                delay 0.2
                do shell script (cmdPrefix & "mp4chaps -i /private/tmp/cat.mp4" as text)
            on error error_number
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt"
                progressField's setStringValue_("")
                display dialog "The chapters could not be added to concatenated file."
            end try
        end if
        -- Prepare tags
        if pcatName is not "" then set fcatName to (" -song " & quoted form of (pcatName as text) & " ")
        if fcatName contains "\"\"" then set fcatName to ""
        if pcatAlbum is not "" then set fcatAlbum to (" -album " & quoted form of (pcatAlbum as text) & " ")
        if fcatAlbum contains "\"\"" then set fcatAlbum to ""
        if pcatArtist is not "" then set fcatArtist to (" -artist " & quoted form of (pcatArtist as text) & " ")
        if fcatArtist contains "\"\"" then set fcatArtist to ""
        if pcatComposer is not "" then set fcatComposer to (" -writer " & quoted form of (pcatComposer as text) & " ")
        if fcatComposer contains "\"\"" then set fcatComposer to ""
        if pcatGenre is not "" then set fcatGenre to (" -genre " & quoted form of (pcatGenre as text) & " ")
        if fcatGenre contains "\"\"" then set fcatGenre to ""
        if pcatTrack is not "" then set fcatTrack to (" -track \"" & pcatTrack & "\" ")
        if fcatTrack contains "\"\"" then set fcatTrack to ""
        if pcatTracks is not "" then set fcatTracks to (" -tracks \"" & pcatTracks & "\" ")
        if fcatTracks contains "\"\"" then set fcatTracks to ""
        if pcatDisc is not "" then set fcatDisc to (" -disk \"" & pcatDisc & "\" ")
        if fcatDisc contains "\"\"" then set fcatDisc to ""
        if pcatDiscs is not "" then set fcatDiscs to (" -disks \"" & pcatDiscs & "\" ")
        if fcatDiscs contains "\"\"" then set fcatDiscs to ""
        if pcatAlbumArtist is not "" then set fcatAlbumArtist to (" -albumartist " & quoted form of (pcatAlbumArtist as text) & " ")
        if fcatAlbumArtist contains "\"\"" then set fcatAlbumArtist to ""
        if pcatYear is not "" then set fcatYear to (" -year \"" & pcatYear & "\" ")
        if fcatYear contains "\"\"" then set fcatYear to ""
        -- Add tags
        if not errorHappened then
            try
                progressField's setStringValue_("Adding tags...")
                delay 0.2
                do shell script (cmdPrefix & "mp4tags " & fcatName & fcatAlbum & fcatArtist & fcatComposer & fcatGenre & fcatTrack & fcatTracks & fcatDisc & fcatDiscs & fcatAlbumArtist & fcatYear & " /private/tmp/cat.mp4" as text)
            on error error_number
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt"
                progressField's setStringValue_("")
                display dialog "The tags could not be added to the concatenated audio file."
            end try
        end if
        -- Grab the TOC, if needed
        if not errorHappened then
            if tocToLyricsValue is 1 then
                progressField's setStringValue_("Getting TOC...")
                try
                    set tocText to (do shell script "/bin/cat /private/tmp/cat.chapters.txt")
                on error error_number
                    set errorHappened to true
                    do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt"
                    progressField's setStringValue_("")
                    display dialog "The TOC could not be processed."
                end try
            end if
        end if
        -- Add the finished track to iTunes
        if not errorHappened then
            progressField's setStringValue_("Adding to iTunes...")
            delay 0.2
            try
                if mediaTypeText is "Music track" then
                    set mediaType to "m4a" as text
                else if mediaTypeText is "Audiobook track" then
                    set mediaType to "m4b" as text
                end if
                do shell script ("/bin/mv /private/tmp/cat.mp4 /private/tmp/cat." & mediaType as text)
                tell application "iTunes"
                    set aliasPath to POSIX file ("/private/tmp/cat." & mediaType as text) as alias
                    set theAddedTrack to (add aliasPath)
                    if tocToLyricsValue is 1 then
                        set lyrics of theAddedTrack to tocText
                    end if
                end tell
            on error error_number
                set errorHappened to true
                do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/cat.chapters.txt /private/tmp/cat." & mediaType
                progressField's setStringValue_("")
                display dialog "The concatenated file could not be added to iTunes."
            end try
        end if
        -- Clean up
        do shell script "/bin/rm -f /private/tmp/concat* /private/tmp/cat.chapters.txt /private/tmp/cat.m4*"
        set theCounter to ""
        progressField's setStringValue_("")
    end btnConcatenate_

	on applicationWillFinishLaunching_(aNotification)
        -- Insert code here to initialize your application before any files are opened
        if quitme is 1 then
            tell me to quit
        end if
	end applicationWillFinishLaunching_

	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits
		return current application's NSTerminateNow
	end applicationShouldTerminate_

end script


Move script logic into hermes_status()

Move script logic into hermes_status()

tell application "Finder"
	set json_path to file "json.scpt" of folder of (path to me)
end tell
set json to load script (json_path as alias)

on is_running(appName)
	tell application "System Events" to (name of processes) contains appName
end is_running

on hermes_status()
	global json
	set reply to json's createDict()
	if is_running("Hermes") then
		reply's setkv("running", true)
		set hermesInfo to json's createDict()
--		set hermesStations to json's createDict()
		tell application "Hermes"
			hermesInfo's setkv("state", playback state as string)
			hermesInfo's setkv("volume", playback volume)

--			XXX: execution error: Hermes got an error: every station doesn’t understand the “count” message. (-1708)
--			repeat with theStation in stations
--				hermesStations's setkv("name", theStation's name)
--				hermesStations's setkv("id", theStation's station ID)
--			end repeat

			hermesInfo's setkv("title", current song's title)
			hermesInfo's setkv("artist", current song's artist)
			hermesInfo's setkv("album", current song's album)
			hermesInfo's setkv("artwork", current song's artwork URL)
			hermesInfo's setkv("rating", current song's rating)
			hermesInfo's setkv("position", playback position as integer)
			hermesInfo's setkv("duration", current song duration as integer)
			hermesInfo's setkv("station_name", current station's name)
			hermesInfo's setkv("station_id", current station's station ID)
		end tell
--		hermesInfo's setkv("stations", hermesStations)
		reply's setkv("info", hermesInfo)
	else
		reply's setkv("running", false)
	end if
	reply's setkv("time", (do shell script "date -u +%s"))
	return reply's toJson()
end hermes_status

return hermes_status()

tell application "Finder"
	set json_path to file "json.scpt" of folder of (path to me)
end tell
set json to load script (json_path as alias)

on is_running(appName)
	tell application "System Events" to (name of processes) contains appName
end is_running

set reply to json's createDict()
if is_running("Hermes") then
	reply's setkv("running", true)
	set hermesInfo to json's createDict()
--	set hermesStations to json's createDict()
	tell application "Hermes"
		hermesInfo's setkv("state", playback state as string)
		hermesInfo's setkv("volume", playback volume)

-- XXX: execution error: Hermes got an error: every station doesn’t understand the “count” message. (-1708)
--		repeat with theStation in stations
--			hermesStations's setkv("name", theStation's name)
--			hermesStations's setkv("id", theStation's station ID)
--		end repeat

		hermesInfo's setkv("title", current song's title)
		hermesInfo's setkv("artist", current song's artist)
		hermesInfo's setkv("album", current song's album)
		hermesInfo's setkv("artwork", current song's artwork URL)
		hermesInfo's setkv("rating", current song's rating)
		hermesInfo's setkv("position", playback position as integer)
		hermesInfo's setkv("duration", current song duration as integer)
		hermesInfo's setkv("station_name", current station's name)
		hermesInfo's setkv("station_id", current station's station ID)
	end tell
--	hermesInfo's setkv("stations", hermesStations)
	reply's setkv("info", hermesInfo)
else
	reply's setkv("running", false)
end if
reply's setkv("time", (do shell script "date -u +%s"))
return reply's toJson()


dos2unix galore

dos2unix galore

tell application "System Events" to set SkypeIsRunning to (count of (every process whose name is "Skype")) > 0
if SkypeIsRunning then
  tell application "Skype"
    send command "SET USERSTATUS DND" script name "SETSKYPESTATUSTODND"
  end tell
end if


Lots of internal improvements. Better error handling. Hopefully solving issue #5

-- Setting the "playing" property to the constant returned by Spotify as a "player state" when it's playing.
property playing : constant ****kPSP
global currentVolume

if (isInLoginItems("SpotiFree", ":Applications:SpotiFree.app") = false) then -- Check if SpotiFree is login items.
	local dialogTitle, dialogMessage, dialogButtonYes, dialogButtonYes, spotifreeAppName, spotifreeAppPath
	set spotifreeAppName to "SpotiFree"
	set spotifreeAppPath to ":Applications:SpotiFree.app"
	set dialogTitle to "Open SpotiFree at login"
	set dialogMessage to "Do you want SpotiFree to run automatically on startup? You'll never notice it, seriously."
	set dialogButtonNo to "No, thanks"
	set dialogButtonYes to "OK"

	-- Run the dialog to a user.
	set runAtStartupQuestion to (display dialog dialogMessage with title dialogTitle with icon 1 buttons {dialogButtonNo, dialogButtonYes} default button 2)
	-- Assign a result to the variable runAtStartupAnswer.
	set runAtStartupAnswer to the button returned of runAtStartupQuestion
	-- Check if user agreed.
	if (runAtStartupAnswer = dialogButtonYes) then
		try
			-- Add SpotiFree to the Login Items.
			my addToLoginItems(spotifreeAppName, spotifreeAppPath)
		end try
	end if
end if

repeat
	try
		-- Checking if Spotify is running, playing, and if current track is an advertisement.
		if (isRunning() and isPlaying() and isAnAd()) then
			try
				-- Mute Spotify.
				mute()
			end try
			-- Wait until the end of an ad + 1 sec. Then go forward.
			delay untilTheEndOfTrack()

			repeat
				try
					-- Check if current track is an ad. Or if Spotify was paused during an advertisement.
					if (isAnAd()) then
						-- Delay until the end of an ad + 1 sec.
						-- If Spotify was paused, or there is a second ad, this loop will continue to repeat.
						delay untilTheEndOfTrack()
					else
						-- If there's no more ads, unmute and exit the loop.
						unmute()
						exit repeat
					end if
				end try
			end repeat
		end if
	end try
	-- This is how fast we are polling Spotify.
	-- The only speed at which you will hear no sounds passing through.
	-- Fortunately, combined with the added load on Spotify, the CPU usage stays well below 1% even on an old dual-core 3.6 GHz processor.
	delay 0.3
end repeat

on mute()
	try
		tell application "Spotify"
			-- Get the current sound volume from Spotify and save it in a variable currentVolume.
			set currentVolume to sound volume
			-- This is the only way possible to mute Spotify during an advertisement. Otherwise it pauses when you mute the sound.
			pause
			set sound volume to 0
			play
		end tell
	end try
	return
end mute

on unmute()
	try
		tell application "Spotify"
			-- Restore the volume to the level supplied to the parameter.
			set sound volume to currentVolume
		end tell
	end try
	return
end unmute

on isAnAd()
	local currentTrackPopularity, currentTrackDuration
	try
		tell application "Spotify"
			-- Get the popularity of a current track and save it in a variable currentTrackPopularity.
			set currentTrackPopularity to popularity of current track
			-- Get the duration of current track and save it in a variable currentTrackDuration.
			set currentTrackDuration to duration of current track
		end tell
	on error
		return false
	end try
	-- If current track's popularity is 0 and its duration is less then 40, then it's almost certainly an ad.
	if (currentTrackPopularity = 0 and currentTrackDuration < 40) then
		return true
	else
		return false
	end if
end isAnAd

on untilTheEndOfTrack()
	local currentTrackDuration, currentTrackPosition
	try
		tell application "Spotify"
			-- Get the duration of current track and save it in a variable currentTrackDuration.
			set currentTrackDuration to duration of current track
			-- Get the current track position and save it in a variable currentTrackPosition.
			set currentTrackPosition to player position
		end tell
	on error
		return
	end try
	return currentTrackDuration - currentTrackPosition + 1.5
end untilTheEndOfTrack

on isPlaying()
	local playerState
	try
		tell application "Spotify"
			-- Hook the variable playerState to Spotify's state (playing, paused etc.).
			set playerState to player state
		end tell
	on error
		return false
	end try
	-- Compare Spotify's state with a constant saved in the property on line 1.
	if playerState = playing then
		return true
	else
		return false
	end if
end isPlaying

on isRunning()
	local spotifyProcesses
	try
		tell application "System Events"
			-- Check if there are any Spotify processes. Set to variable spotifyProcesses
			set spotifyProcesses to (count of (every process whose bundle identifier is "com.spotify.client"))
		end tell
	on error
		return false
	end try
	-- Check the variable spotifyProcesses, to see is Spotify running.
	if spotifyProcesses  0 then
		return true
	else
		return false
	end if
end isRunning

on isInLoginItems(appName)
	local applicationName, allLoginItems
	set applicationName to appName
	try
		-- Get all apps in Login Items.
		tell application "System Events"
			set allLoginItems to name of every login item as string
		end tell
	on error
		return false
	end try
	-- Check if inputted app is in there.
	if applicationName is in allLoginItems then
		return true
	else
		return false
	end if
end isInLoginItems

on addToLoginItems(appName, appPath)
	local applicationName, applicationPath, posixAppPath
	set applicationName to appName
	-- Translate a supplied application path to a POSIX standard (e.g. "/Applications/SpotiFree.app" to ":Applications:SpotiFree.app").
	set applicationPath to POSIX path of alias appPath
	try
		tell application "System Events"
			-- Add inputted app to the Login Items.
			make login item at end with properties {path:applicationPath, hidden:true}
		end tell
	on error
		return
	end try
end addToLoginItems

-- Setting the "playing" property to the constant returned by Spotify as a "player state" when it's playing.
property playing : constant ****kPSP
global currentVolume, currentTrackPopularity, currentTrackDuration, currentTrackPosition

if (isInLoginItems("SpotiFree", ":Applications:SpotiFree.app") = false) then -- Check if SpotiFree is login items.
	local dialogTitle, dialogMessage, dialogButtonYes, dialogButtonYes, spotifreeAppName, spotifreeAppPath
	set spotifreeAppName to "SpotiFree"
	set spotifreeAppPath to ":Applications:SpotiFree.app"
	set dialogTitle to "Open SpotiFree at login"
	set dialogMessage to "Do you want SpotiFree to run automatically on startup? You'll never notice it, seriously."
	set dialogButtonNo to "No, thanks"
	set dialogButtonYes to "OK"

	-- Run the dialog to a user.
	set runAtStartupQuestion to (display dialog dialogMessage with title dialogTitle with icon 1 buttons {dialogButtonNo, dialogButtonYes} default button 2)
	-- Assign a result to the variable runAtStartupAnswer.
	set runAtStartupAnswer to the button returned of runAtStartupQuestion
	-- Check if user agreed.
	if (runAtStartupAnswer = dialogButtonYes) then
		try
			-- Add SpotiFree to the Login Items.
			my addToLoginItems(spotifreeAppName, spotifreeAppPath)
		end try
	end if
end if

repeat
	try
		-- Checking if Spotify is running and playing right now.
		if (isRunning() and isPlaying()) then
			tell application "Spotify"
				try
					-- Get the popularity of a current track and save it in a variable currentTrackPopularity.
					set currentTrackPopularity to popularity of current track
					-- Get the duration of current track and save it in a variable currentTrackDuration.
					set currentTrackDuration to duration of current track
				end try
			end tell

			-- Check if current track is an advertisement.
			if (isAnAd(currentTrackPopularity, currentTrackDuration)) then
				try
					tell application "Spotify"
						try
							-- Get the current sound volume from Spotify and save it in a variable currentVolume.
							set currentVolume to sound volume
							-- Get the current track position and save it in a variable currentTrackPosition.
							set currentTrackPosition to player position
						end try
					end tell

					-- Mute Spotify.
					mute()

					-- Wait until the end of an ad + 1 sec. Then go forward.
					delay currentTrackDuration - currentTrackPosition + 1
				end try

				try
					repeat
						tell application "Spotify"
							try
								-- Get the popularity of a current track and save it in a variable currentTrackPopularity.
								set currentTrackPopularity to popularity of current track
								-- Get the duration of current track and save it in a variable currentTrackDuration.
								set currentTrackDuration to duration of current track
								-- Get the current track position and save it in a variable currentTrackPosition.
								set currentTrackPosition to player position

							on error number errorNumber
								-- Checking if Spotify returns "Cant get current track." error.  It's being thrown when there's no track after an ad.
								-- Happens, for instance, when an ad has played after the last song on the playlist.
								if (errorNumber = -1728) then
									-- If it is, unmute Spotify and exit the loop.
									my unmute(currentVolume)
									exit repeat
								end if
							end try
						end tell

						-- Check if current track is an ad. Or if Spotify was paused during an advertisement.
						if (isAnAd(currentTrackPopularity, currentTrackDuration)) then
							-- Delay until the end of an ad + 1 sec.
							-- If Spotify was paused, or there is a second ad, this loop will continue to repeat.
							delay currentTrackDuration - currentTrackPosition + 1
						else
							-- If there's no more ads, unmute and exit the loop.
							unmute(currentVolume)
							exit repeat
						end if
					end repeat
				end try
			end if
		end if
	end try
	-- This is how fast we are polling Spotify.
	-- The only speed at which you will hear no sounds passing through.
	-- Fortunately, combined with the added load on Spotify, the CPU usage stays well below 1% even on an old dual-core 3.6 GHz processor.
	delay 0.3
end repeat

on mute()
	try
		tell application "Spotify"
			try
				-- This is the only way possible to mute Spotify during an advertisement. Otherwise it pauses when you mute the sound.
				pause
				set sound volume to 0
				play
			end try
		end tell
	end try
end mute

on unmute(volume)
	local currentVolume
	set currentVolume to volume

	tell application "Spotify"
		try
			-- Restore the volume to the level supplied to the parameter.
			set sound volume to currentVolume
		end try
	end tell
end unmute

on isAnAd(popularity, duration)
	local trackPopularity, trackDuration
	set trackPopularity to popularity
	set trackDuration to duration

	try
		-- If current track's popularity is 0 and its duration is less then 40, then it's almost certainly an ad.
		if (trackPopularity = 0 and trackDuration < 40) then
			return true
		else
			return false
		end if
	end try
end isAnAd

on isPlaying()
	local playerState
	try
		tell application "Spotify"
			try
				-- Hook the variable playerState to Spotify's state (playing, paused etc.).
				set playerState to player state
			end try
		end tell
		-- Compare Spotify's state with a constant saved in the property on line 1.
		if playerState = playing then
			return true
		else
			return false
		end if
	end try

end isPlaying

on isRunning()
	local spotifyProcesses
	try
		tell application "System Events"
			try
				-- Check if there are any Spotify processes. Set to variable spotifyProcesses
				set spotifyProcesses to (count of (every process whose bundle identifier is "com.spotify.client"))
			end try
		end tell
		-- Check the variable spotifyProcesses, to see is Spotify running.
		if spotifyProcesses  0 then
			return true
		else
			return false
		end if
	end try
end isRunning

on isInLoginItems(appName)
	local applicationName, allLoginItems
	set applicationName to appName
	try
		-- Get all apps in Login Items.
		tell application "System Events" to set allLoginItems to name of every login item as string
		-- Check if inputted app is in there.
		if applicationName is in allLoginItems then
			return true
		else
			return false
		end if
	end try
end isInLoginItems

on addToLoginItems(appName, appPath)
	local applicationName, applicationPath, posixAppPath
	set applicationName to appName
	set applicationPath to appPath

	try
		-- Translate a supplied application path to a POSIX standard (e.g. "/Applications/SpotiFree.app" to ":Applications:SpotiFree.app").
		set posixAppPath to POSIX path of alias applicationPath
		tell application "System Events"
			try
				-- Add inputted app to the Login Items.
				make login item at end with properties {path:posixAppPath, hidden:true}
			end try
		end tell
	end try
end addToLoginItems