Wording change

Wording change

--
--  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

    -- 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 : ""

    -- 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 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 "
        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 missingPackages is "FFMPEG" then
                set the end of missingPackages to "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 install ffmpeg mp4v2 && exit 0;else /usr/bin/ruby -e \"$(/usr/bin/curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)\"; 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."
                end try
                else if result = {button returned:"Quit"} then
                tell me to quit
            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
        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

        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
        set errorHappened to false
        -- Create the intermediate 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 \"" & (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. Only mp4 files encoded as AAC can be joined presently."
        end try
        -- Run the actual concatenation command in ffmpeg (for mp4/AAC files only!)
        -- via https://trac.ffmpeg.org/wiki/How%20to%20concatenate%20(join,%20merge)%20media%20files
        if not errorHappened then
            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
        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
        -- Add tags
        if not errorHappened then
            try
                progressField's setStringValue_("Adding tags...")
                delay 0.2
                do shell script (cmdPrefix & "mp4tags -song \"" & pcatName & "\" -album \"" &  pcatAlbum & "\" -artist \"" &  pcatArtist & "\" -writer \"" &  pcatComposer & "\" -genre \"" &  pcatGenre & "\" -track \"" &  pcatTrack & "\" -tracks \"" &  pcatTracks & "\" -disk \"" &  pcatDisc & "\" -disks \"" &  pcatDiscs & "\" -albumartist \"" & pcatAlbumArtist & "\" -year \"" & pcatYear & "\" /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
        -- 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"
                else if mediaTypeText is "Audiobook track" then
                    set mediaType to "m4b"
                end if
                do shell script ("/bin/mv /private/tmp/cat.mp4 /private/tmp/cat." & mediaType as text)
                tell application "iTunes"
                    add file (":private:tmp:cat." & mediaType as text)
                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
	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

    -- 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 : ""

    -- 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 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 "
        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 missingPackages is "FFMPEG" then
                set the end of missingPackages to "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 install ffmpeg mp4v2 && exit 0;else /usr/bin/ruby -e \"$(/usr/bin/curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)\"; 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."
                end try
                else if result = {button returned:"Quit"} then
                tell me to quit
            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
        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

        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
        set errorHappened to false
        -- Create the intermediate files
        try
            repeat with theIndex in the_index
                progressField's setStringValue_("Processing track " & (theIndex as text) & "..." as text)
                delay 0.2
                do shell script (cmdPrefix & "ffmpeg -i \"" & (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. Only mp4 files encoded as AAC can be joined presently."
        end try
        -- Run the actual concatenation command in ffmpeg (for mp4/AAC files only!)
        -- via https://trac.ffmpeg.org/wiki/How%20to%20concatenate%20(join,%20merge)%20media%20files
        if not errorHappened then
            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
        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
        -- Add tags
        if not errorHappened then
            try
                progressField's setStringValue_("Adding tags...")
                delay 0.2
                do shell script (cmdPrefix & "mp4tags -song \"" & pcatName & "\" -album \"" &  pcatAlbum & "\" -artist \"" &  pcatArtist & "\" -writer \"" &  pcatComposer & "\" -genre \"" &  pcatGenre & "\" -track \"" &  pcatTrack & "\" -tracks \"" &  pcatTracks & "\" -disk \"" &  pcatDisc & "\" -disks \"" &  pcatDiscs & "\" -albumartist \"" & pcatAlbumArtist & "\" -year \"" & pcatYear & "\" /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
        -- 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"
                else if mediaTypeText is "Audiobook track" then
                    set mediaType to "m4b"
                end if
                do shell script ("/bin/mv /private/tmp/cat.mp4 /private/tmp/cat." & mediaType as text)
                tell application "iTunes"
                    add file (":private:tmp:cat." & mediaType as text)
                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
	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


The chapter file is now generated.

The chapter file is now generated.

--
--  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

	-- 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

    -- 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 : ""

    -- 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 theCounter : ""

    on awakeFromNib()
        --
        -- Check for FFMPEG
        --
        -- (This works, but it's ugly!)
        --
        --
        try
            do shell script "if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi; if [ -x \"`/usr/bin/which ffmpeg`\" ];then exit 0;else exit 1;fi"
        on error number error_number
            display dialog "You must install FFMPEG to continue. \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, ensure that it is in your bash path." buttons {"Quit","Install FFMPEG"} default button 2
            If button returned of result is "Install FFMPEG" then
                try
                    tell application "Terminal"
                        -- TODO: This should be cleaner -- Terminal in front, only one window, focus back to the cat'er afterwards
                        set newTab to do script "if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;if [[ -x `which brew` ]];then brew install ffmpeg;else /usr/bin/ruby -e \"$(/usr/bin/curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)\";brew install ffmpeg;fi"
                        delay 4
                        repeat
                            delay 0.1
                            if not busy of newTab then exit repeat
                        end repeat
                    end tell
                     -- TODO: This needs a better test, i.e., check if ffmpeg is actually accessible on the path
                    display dialog "FFMPEG was successfully installed"
                    -- TODO: This should actually work! (Bring us back to the foreground)
                    activate current application
                on error number error_number
                    display dialog "FFMPEG did not successfully install"
                end try
            end If
            If button returned of result is "Quit" then
                -- Fix!
                current application's NSApp's terminate()
            end If
        end try
    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)
                    end if
                end repeat
            end if
        end tell
        -- 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
    end btnGetTracks_

    on btnConcatenate_(sender)
        set the_pipes to {}
        repeat with theIndex in the_index
            -- TODO: Needs error checking!
            -- TODO: We need to check what kind of audio files we have, then adjust accordingly
            do shell script ("if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;ffmpeg -i \"" & (item theIndex of these_files as text) & "\" -c copy -bsf:v h264_mp4toannexb -f mpegts /private/tmp/concat" & theIndex & ".ts 2> /dev/null" as text)
            log ("Processed file number" & theIndex) as text
            set end of the_pipes to ("/private/tmp/concat" & theIndex & ".ts" as text)
        end repeat
        -- Run the actual concatenation command in ffmpeg, via https://trac.ffmpeg.org/wiki/How%20to%20concatenate%20(join,%20merge)%20media%20files
        set olddelimeters to AppleScript's text item delimiters
        set AppleScript's text item delimiters to "|"
        set disp_thepipes to the_pipes as string
        do shell script ("if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;ffmpeg -f mpegts -i \"concat:" & (disp_thepipes as text) & "\" -c copy -bsf:a aac_adtstoasc /private/tmp/cat.mp4")
        set AppleScript's text item delimiters to olddelimeters
        -- Now let's create the chapter file
        repeat with theIndex in the_index
            if theIndex < 2 then
                do shell script ("/bin/echo \"00:00:00 " & (item theIndex of these_titles as text) & "\" > /private/tmp/chapters" as text)
                set theCounter to (do shell script ("if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;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)
            else
                set theDateStamp to do shell script ("if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;t="& (theCounter as text) & ";((sec=t%60, t/=60, min=t%60, hrs=t/60));timestamp=$(printf \"%02d:%02d:%02d\" $hrs $min $sec);/bin/echo $timestamp" as text)
                do shell script ("/bin/echo \"" & (theDateStamp as text) & " " & (item theIndex of these_titles as text) & "\" >> /private/tmp/chapters" as text)
                log ("Before the addition, theCounter is " & theCounter) as text
                set theCounter to do shell script ("if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;t=" & theCounter & ";t=`echo $t\"+\\`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/'\\`\" | bc`;echo $t" as text)
                log ("After the addition, theCounter is " & theCounter) as text
            end if
        end repeat
        -- Clean up
        -- do shell script "/bin/rm /private/tmp/concat* /private/tmp/cat.mp4 /private/tmp/chapters"
        set theCounter to ""
    end btnConcatenate_

	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened
	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

	-- 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

    -- 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 : ""

    -- 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: {}

    on awakeFromNib()
        --
        -- Check for FFMPEG
        --
        -- (This works, but it's ugly!)
        --
        --
        try
            do shell script "if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi; if [ -x \"`/usr/bin/which ffmpeg`\" ];then exit 0;else exit 1;fi"
        on error number error_number
            display dialog "You must install FFMPEG to continue. \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, ensure that it is in your bash path." buttons {"Quit","Install FFMPEG"} default button 2
            If button returned of result is "Install FFMPEG" then
                try
                    tell application "Terminal"
                        -- TODO: This should be cleaner -- Terminal in front, only one window, focus back to the cat'er afterwards
                        set newTab to do script "if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;if [[ -x `which brew` ]];then brew install ffmpeg;else /usr/bin/ruby -e \"$(/usr/bin/curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)\";brew install ffmpeg;fi"
                        delay 4
                        repeat
                            delay 0.1
                            if not busy of newTab then exit repeat
                        end repeat
                    end tell
                     -- TODO: This needs a better test, i.e., check if ffmpeg is actually accessible on the path
                    display dialog "FFMPEG was successfully installed"
                    -- TODO: This should actually work! (Bring us back to the foreground)
                    activate current application
                on error number error_number
                    display dialog "FFMPEG did not successfully install"
                end try
            end If
            If button returned of result is "Quit" then
                -- Fix!
                current application's NSApp's terminate()
            end If
        end try
    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)
                    end if
                end repeat
            end if
        end tell
        -- 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
    end btnGetTracks_

    on btnConcatenate_(sender)
        -- Make the pipes
        set the_pipes to {}
        repeat with theIndex in the_index
            -- TODO: Needs error checking!
            display dialog (item theIndex of these_files as text)
            do shell script ("if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;ffmpeg -i \"" & (item theIndex of these_files as text) & "\" -c copy -bsf:v h264_mp4toannexb -f mpegts /private/tmp/concat" & theIndex & ".ts 2> /dev/null" as text)
            log ("Processed file number" & theIndex) as text
            set end of the_pipes to ("/private/tmp/concat" & theIndex & ".ts" as text)
        end repeat
        set olddelimeters to AppleScript's text item delimiters
        set AppleScript's text item delimiters to "|"
        set disp_thepipes to the_pipes as string
        do shell script ("if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi;ffmpeg -f mpegts -i \"concat:" & (disp_thepipes as text) & "\" -c copy -bsf:a aac_adtstoasc /private/tmp/cat.mp4")
        set AppleScript's text item delimiters to olddelimeters
    end btnConcatenate_

	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened
	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


Properly use tab

Properly use tab

use scripting additions
use framework "Foundation"
property NSString : a reference to current application's NSString

-- Helper

on myRemoveLastPath(myPath)
set myString to NSString's stringWithString:myPath
set removedLastPathString to myString's stringByDeletingLastPathComponent
removedLastPathString as text
end myRemoveLastPath

on myFolderExists(myFolder) -- (String) as Boolean
tell application "System Events"
if exists folder myFolder then
return true
else
return false
end if
end tell
end myFolderExists

on myGetRemote(myText)
set myString to NSString's stringWithString:myText
set myParts to myString's componentsSeparatedByString:"\t"
set myFirstParts to item 1 of myParts
myFirstParts as text
end myGetRemote

-- Path

on myHomePath()
tell application "System Events"
"/Users/" & (name of current user)
end tell
end myHomePath

on myLibraryPath()
myHomePath() & "/Library"
end myLibraryPath

on myXcodePath()
myLibraryPath() & "/Developer/Xcode"
end myXcodePath

on myUserDataPath()
myXcodePath() & "/UserData"
end myUserDataPath

on myProjectPath()
tell application "Xcode"
tell active workspace document
set myPath to path
end tell
end tell
myRemoveLastPath(myPath)
end myProjectPath

-- Generic Open

on myOpenFolder(myPath)
tell application "Finder"
activate
open myPath as POSIX file
end tell
end myOpenFolder

on myOpeniTerm(myPath)
tell application "Finder"
do shell script "open -a iTerm " & quoted form of myPath
end tell
end myOpeniTerm

-- Open

on myOpenThemesFolder()
set myPath to myUserDataPath() & "/FontAndColorThemes/"
myOpenFolder(myPath)
end myOpenThemesFolder

on myOpenCodeSnippetsFolder()
set myPath to myUserDataPath() & "/CodeSnippets/"
myOpenFolder(myPath)
end myOpenCodeSnippetsFolder

on myOpenDeviceSupportFolder()
set myPath to "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport"
myOpenFolder(myPath)
end myOpenDeviceSupportFolder

on myOpenArchivesFolder()
set myPath to myXcodePath() & "/Archives/"
myOpenFolder(myPath)
end myOpenArchivesFolder

on myOpenProvisioningProfileFolder()
set myPath to myLibraryPath() & "/MobileDevice/Provisioning Profiles"
myOpenFolder(myPath)
end myOpenProvisioningProfileFolder

on myOpenProjectFolder()
set myPath to myProjectPath()
myOpenFolder(myPath)
end myOpenProjectFolder

on myOpeniTermForCurrentProject()
set myPath to myProjectPath()
myOpeniTerm(myPath)
end myOpeniTermForCurrentProject

on myOpenDerivedDataFolder()
set myRelativePath to myProjectPath() & "/DerivedData/"
if myFolderExists(myRelativePath) then
myOpenFolder(myRelativePath)
else
myOpenFolder(myXcodePath() & "/DerivedData/")
end if
end myOpenDerivedDataFolder

on myOpenGitHub()
set myPath to myProjectPath()
set myConsoleOutput to (do shell script "cd " & quoted form of myPath & "; git remote -v")
set myRemote to myGetRemote(myConsoleOutput)
set myUrl to (do shell script "cd " & quoted form of myPath & "; git config --get remote." & quoted form of myRemote & ".url")
open location myUrl
end myOpenGitHub

use scripting additions
use framework "Foundation"
property NSString : a reference to current application's NSString

-- Helper

on myRemoveLastPath(myPath)
set myString to NSString's stringWithString:myPath
set removedLastPathString to myString's stringByDeletingLastPathComponent
removedLastPathString as text
end myRemoveLastPath

on myFolderExists(myFolder) -- (String) as Boolean
tell application "System Events"
if exists folder myFolder then
return true
else
return false
end if
end tell
end myFolderExists

on myGetRemote(myText)
set myString to NSString's stringWithString:myText
set myParts to myString's componentsSeparatedByString:"  "
set myFirstParts to item 1 of myParts
myFirstParts as text
end myGetRemote

-- Path

on myHomePath()
tell application "System Events"
"/Users/" & (name of current user)
end tell
end myHomePath

on myLibraryPath()
myHomePath() & "/Library"
end myLibraryPath

on myXcodePath()
myLibraryPath() & "/Developer/Xcode"
end myXcodePath

on myUserDataPath()
myXcodePath() & "/UserData"
end myUserDataPath

on myProjectPath()
tell application "Xcode"
tell active workspace document
set myPath to path
end tell
end tell
myRemoveLastPath(myPath)
end myProjectPath

-- Generic Open

on myOpenFolder(myPath)
tell application "Finder"
activate
open myPath as POSIX file
end tell
end myOpenFolder

on myOpeniTerm(myPath)
tell application "Finder"
do shell script "open -a iTerm " & quoted form of myPath
end tell
end myOpeniTerm

-- Open

on myOpenThemesFolder()
set myPath to myUserDataPath() & "/FontAndColorThemes/"
myOpenFolder(myPath)
end myOpenThemesFolder

on myOpenCodeSnippetsFolder()
set myPath to myUserDataPath() & "/CodeSnippets/"
myOpenFolder(myPath)
end myOpenCodeSnippetsFolder

on myOpenDeviceSupportFolder()
set myPath to "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport"
myOpenFolder(myPath)
end myOpenDeviceSupportFolder

on myOpenArchivesFolder()
set myPath to myXcodePath() & "/Archives/"
myOpenFolder(myPath)
end myOpenArchivesFolder

on myOpenProvisioningProfileFolder()
set myPath to myLibraryPath() & "/MobileDevice/Provisioning Profiles"
myOpenFolder(myPath)
end myOpenProvisioningProfileFolder

on myOpenProjectFolder()
set myPath to myProjectPath()
myOpenFolder(myPath)
end myOpenProjectFolder

on myOpeniTermForCurrentProject()
set myPath to myProjectPath()
myOpeniTerm(myPath)
end myOpeniTermForCurrentProject

on myOpenDerivedDataFolder()
set myRelativePath to myProjectPath() & "/DerivedData/"
if myFolderExists(myRelativePath) then
myOpenFolder(myRelativePath)
else
myOpenFolder(myXcodePath() & "/DerivedData/")
end if
end myOpenDerivedDataFolder

on myOpenGitHub()
set myPath to myProjectPath()
set myConsoleOutput to (do shell script "cd " & quoted form of myPath & "; git remote -v")
set myRemote to myGetRemote(myConsoleOutput)
set myUrl to (do shell script "cd " & quoted form of myPath & "; git config --get remote." & quoted form of myRemote & ".url")
open location myUrl
end myOpenGitHub


remove tab

remove tab

on escape_quotes(string_to_escape)
  set AppleScript's text item delimiters to the "\""
  set the item_list to every text item of string_to_escape
  set AppleScript's text item delimiters to the "\\\""
  set string_to_escape to the item_list as string
  set AppleScript's text item delimiters to ""
  return string_to_escape
end escape_quotes

tell application "Spotify"
  set ctrack to "{"
  set ctrack to ctrack & "\"artist\": \"" & my escape_quotes(current track's artist) & "\""
  set ctrack to ctrack & ",\"album\": \"" & my escape_quotes(current track's album) & "\""
  set ctrack to ctrack & ",\"disc_number\": " & current track's disc number
  set ctrack to ctrack & ",\"duration\": " & current track's duration
  set ctrack to ctrack & ",\"played_count\": " & current track's played count
  set ctrack to ctrack & ",\"track_number\": " & current track's track number
  set ctrack to ctrack & ",\"popularity\": " & current track's popularity
  set ctrack to ctrack & ",\"id\": \"" & current track's id & "\""
  set ctrack to ctrack & ",\"name\": \"" & my escape_quotes(current track's name) & "\""
  set ctrack to ctrack & ",\"album_artist\": \"" & my escape_quotes(current track's album artist) & "\""
  set ctrack to ctrack & ",\"artwork_url\": \"" & current track's artwork url & "\""
  set ctrack to ctrack & ",\"spotify_url\": \"" & current track's spotify url & "\""
  set ctrack to ctrack & "}"
end tell


Simplified iCal script

Simplified iCal script

--HG--
extra : convert_revision : svn%3A99687598-2e92-11dd-8019-fe7b9d601d1b/trunk%402688

FasdUAS 1.101.10
k
lQK	An applescript that shows today's events from iCal as growl notifications.
l

a[	The script shows how to register and use multiple types of notifications from Applescript:
l

l		"Today's Events"
l			and
l!		"In-Script Notifications"
lD>			are the two notification types that this script registers.
l@: 			The types of notification are separated functionally.
l|v 			So the user can disable the first informational note from the prefpane without disabling the main notifications.
l!!tn-------------------------------------------------------------------------------------------------------------- "#
"l$$tn--------------------------------------------------------------------------------------------------------------#%&
%l&'(
'l()*
)l*+,
+l--A;	Register with growl and show the "gathering" notification.,./
.l20
0O212
1k13345
4l567
6O89
8k::;<
;r=>
=J??@A
@m	BBToday's EventsAC
Cm
DDIn-Script Notification
>o 0myallnoteslistmyAllNotesList<E
EIF
.registernullnullFGH

appl
GmII-'AppleScript iCal today's Event NotifierHJK

anot
Jo 0myallnoteslistmyAllNotesListKLM

dnot
Lo 0myallnoteslistmyAllNotesListMN

iapp
NmOO
iCal
9mPP2null߀LGrowlHelperApp.appP(x)(|zGRRRalisMacintosh HDgH+LGrowlHelperApp.appLȞV	 	ResourcesfȂ6LLLDDYMacintosh HD:Library:PreferencePanes:Growl.prefPane:Contents:Resources:GrowlHelperApp.app&GrowlHelperApp.appMacintosh HDLLibrary/PreferencePanes/Growl.prefPane/Contents/Resources/GrowlHelperApp.app/7QR
QlRS
SI1T
.notifygrnullnullTUV

name
Ul	 !W
Wm !XXIn-Script NotificationVYZ

titl
Yl	"#[
[m"#\\Please WaitZ]^

desc
]l	&)_
_m&)``^XGathering today's events from iCal... (n.b. Events which are repeats will not be shown!)^a

appl
am*-bb-'AppleScript iCal today's Event Notifier
2mP/cd
cldef
el3<g
gr3<hi
hI38
.misccurdldt null
io0nowfjk
jl=Ll
lr=Lmn
m\=Hop
oo=@0now
pl@Gq
qn@Grs
r1CG

time
so@C0now
no0thismorningthisMorningktu
tlMTv
vIMTw
.ascrcmnt********
wlMPx
xoMP0thismorningthisMorninguyz
ylUd{
{rUd|}
|\U`~
~[U^
oUX0thismorningthisMorning
]X]
mXY
1Y\

days
m^_
}o0thiseveningthisEveningz
lel
Iel
.ascrcmnt********
leh
oeh0thiseveningthisEvening
l
l	Gather today's events
lmB
OmB
ksA
lss
rs}
csy
Jsu
mux

list
o0
currentevents
currentEvents
X~z
Ou
Xt
Oo
kn
l$	Catch events that start today
r
m
boovfals
o 0eventiscurrenteventIsCurrent
Z
F
l
@
1

wr1s
o0thismorningthisMorning
l
B
1

wr1s
o0thiseveningthisEvening
r
m
boovtrue
o 0eventiscurrenteventIsCurrent
l
lF@	Catch events that started before today, but have not yet ended.
Z
F
l
@
1

wr5s
o0now
l
B
1

wr1s
o0thismorningthisMorning
r
m
boovtrue
o 0eventiscurrenteventIsCurrent
l
Zn
l

=

o 0eventiscurrenteventIsCurrent
m
boovtrue
kj
I
.ascrcmnt********
l
mCURRENT EVENT!
r!
1

wr1s
o0thestarttheStart
r"-
n")
1%)

tstr
o"%0thestarttheStart
o~~0thestarttimetheStartTime
r.P
c.L
K.H}}0
eventtitle
eventTitle
n16
126|
|
wr11
o12{{0	thisevent	thisEventzz$0eventdescriptioneventDescription
n9>
1:>y
y
wr12
o9:xx0	thisevent	thisEventwvw0	starttime	startTime
oADuu0thestarttimetheStartTimev
mHKt
t
reco
oss0myrecordmyRecord
rQ^
cQZ
JQVr
oQTqq0myrecordmyRecordr
mVYp
p
list
ooo0newlistnewListn
r_j
b_f
o_bmm0
currentevents
currentEvents
obell0newlistnewList
okk0
currentevents
currentEventsn
ojj0	thisevent	thisEvent0	thisevent	thisEvent
2i
i
wrev
ohh0thiscalthisCal0thiscalthisCal
2g
g
wres
l{{fefe
l{{dd	Show the events.

	l{{cbcb

Z{
a`

l{_
={
n{
m^
^
nmbr
n{
2~]
]
cobj
o{~\\0
currentevents
currentEvents
m[[_
O
l	Z
IYX
Y.notifygrnullnullXW
W
name
l	V
mIn-Script NotificationVU
U
titl
l	 T
 m!!No iCal events todayTS"#
S
desc
"l	$R
$m%%Go outside and play!R#Q&P
Q
appl
&m''-'AppleScript iCal today's Event NotifierPZ
mPa`()
(lONON)*+
*Y?,M-.L
,k://01
0r23
2n45
44K6
K
cobj
6oJJ0i
5oII0
currentevents
currentEvents
3oHH"0thiseventrecordthisEventRecord178
7Q9:;
9r<=
<l>G
>b?@
?bAB
AnCD
CoFF0
eventtitle
eventTitle
DoEE"0thiseventrecordthisEventRecord
BmEE	 -
@nFG
FoDD0	starttime	startTime
GoCC"0thiseventrecordthisEventRecordG
=oBB"0theeventsummarytheEventSummary
:RA@?
A.ascrerr ********@?
;rHI
HbJK
JmLL
no summary -
KnMN
Mo>>0	starttime	startTime
No=="0thiseventrecordthisEventRecord
Io<<"0theeventsummarytheEventSummary8OP
Ol;:;:PQR
QQSTU
SrVW
Vn
XY
Xo
99$0eventdescriptioneventDescription
Yo88"0thiseventrecordthisEventRecord
Wo77*0theeventdescriptiontheEventDescription
TR654
6.ascrerr ********54
UrZ[
Zm\\no description
[o33*0theeventdescriptiontheEventDescriptionR]^
]l2121^_0
_O:`a
`l	"9b/
bI"9.-c
..notifygrnullnull-c,de
,
name
dl	$'f+
fm$'ggToday's Events+e*hi
*
titl
hl	(+j)
jo(+(("0theeventsummarytheEventSummary)i'kl
'
desc
kl	.1m&
mo.1%%*0theeventdescriptiontheEventDescription&l$n#
$
appl
nm25oo-'AppleScript iCal today's Event Notifier#/
amP0M0i
-m""
.npq
pm!
!
nmbr
qnrs
r2

cobj
so0
currentevents
currentEventsL+t
tl@@
mmpuunull߀iiCal.app֠P<(x)(|zwrbtalisDMacintosh HDgH+iiCal.app?Y	 Applicationsf?Ki"Macintosh HD:Applications:iCal.appiCal.appMacintosh HDApplications/iCal.app/vw
vlwx
xlyzy
.aevtoappnull****z{|}
.aevtoappnull****
{kB~~.ejty|
0thiscalthisCal0	thisevent	thisEvent
0i}CPBDI
	OX\`bu!%'EL\go 0myallnoteslistmyAllNotesList

appl

anot

dnot

iapp
.registernullnull

name

titl

desc
.notifygrnullnull
.misccurdldt null0now

time0thismorningthisMorning
.ascrcmnt********

days0thiseveningthisEvening

list0
currentevents
currentEvents

wres

kocl

cobj
.corecnte********

wrev 0eventiscurrenteventIsCurrent

wr1s

bool

wr5s0thestarttheStart

tstr0thestarttimetheStartTime0
eventtitle
eventTitle

wr11$0eventdescriptioneventDescription

wr120	starttime	startTime

reco0myrecordmyRecord0newlistnewList

nmbr"0thiseventrecordthisEventRecord"0theeventsummarytheEventSummary*0theeventdescriptiontheEventDescriptionC/lvEO*UO*aaaUO*jE`O__a,E`O_jO_k_ kE`O_jOajva&E`O*a-[aa l!kh*a"-[aa l!khfE`#O*a$,_	*a$,_a%&
eE`#YhO*a&,_	*a$,_a%&
eE`#YhO_#e_a'jO*a$,E`(O_(a),E`*Oa+a,,a-a.,a/_*a0a1&E`2O_2kva&E`3O__3%E`YhU[OY=U[OYO_a -a4,j!*a5a6aa7a8UYhOk_a -a4,Ekh_a /E`9O_9a+,a:%_9a/,%E`;WX<=a>_9a/,%E`;O_9a-,E`?WX<=a@E`?O*aA_;a_?aBU[OYOPUascr
ޭ

FasdUAS 1.101.10
k
lQK	An applescript that shows today's events from iCal as growl notifications.
l

a[	The script shows how to register and use multiple types of notifications from Applescript:
l

l		"Today's Events"
l			and
l!		"In-Script Notifications"
lD>			are the two notification types that this script registers.
l@: 			The types of notification are separated functionally.
l|v 			So the user can disable the first informational note from the prefpane without disabling the main notifications.
l!!tn-------------------------------------------------------------------------------------------------------------- "#
"l$$tn--------------------------------------------------------------------------------------------------------------#%&
%l&'(
'l()*
)l*+,
+l--A;	Register with growl and show the "gathering" notification.,./
.l20
0O212
1k13345
4l567
6O89
8k::;<
;r=>
=J??@A
@m	BBToday's EventsAC
Cm
DDIn-Script Notification
>o 0myallnoteslistmyAllNotesList<E
EIF
.registernullnullFGH

appl
GmII-'AppleScript iCal today's Event NotifierHJK

anot
Jo 0myallnoteslistmyAllNotesListKLM

dnot
Lo 0myallnoteslistmyAllNotesListMN

iapp
NmOO
iCal
9mPPLnull߀OGrowlHelperApp.appL7ڐ0g`)z(K ڰGRRRalisWideBoy.1H+OGrowlHelperApp.appO)	 	Resources.1)OOO+m|bWideBoy:Users:diggory:Library:PreferencePanes:Growl.prefPane:Contents:Resources:GrowlHelperApp.app&GrowlHelperApp.appWideBoyZUsers/diggory/Library/PreferencePanes/Growl.prefPane/Contents/Resources/GrowlHelperApp.app/7QR
QlRS
SI1T
.notifygrnullnullTUV

name
Ul	 !W
Wm !XXIn-Script NotificationVYZ

titl
Yl	"#[
[m"#\\Please WaitZ]^

desc
]l	&)_
_m&)``^XGathering today's events from iCal... (n.b. Events which are repeats will not be shown!)^a

appl
am*-bb-'AppleScript iCal today's Event Notifier
2mP/cd
cldef
elfgh
glhij
il3<k
kr3<lm
lI38
.misccurdldt null
mo0nowjno
nl=|p
pr=|qr
qc=xst
sl=tu
ub=tvw
vb=pxy
xb=lz{
zb=d|}
|b=`~
~b=X
b=T
b=L
b=H
m=@"
n@G
mCG

wkdy
o@C0now
mHK,
nLS
mOS

mnth
oLO0now
mTW
nX_
1[_

day
oX[0now
}m`c,
{ndk
1gk

year
odg0now
ymlo 12:00:00 am
wmps"
tmtw

TEXT
ro0morningtimemorningTimeo
l}
r}
4}

ldt
o0morningtimemorningTime
o0thismorningthisMorning
l
I
.ascrcmnt********
l
o0thismorningthisMorning
l
r
c
l
b
b
b
b
b
b
b
b
b
m"
n
m

wkdy
o0now
m,
n
m

mnth
o0now
m
n
1

day
o0now
m,
n
1

year
o0now
m 11:59:59 pm
m"
m

TEXT
o0eveningtimeeveningTime
l
r
4

ldt
o0eveningtimeeveningTime
o0thiseveningthisEvening
l
I
.ascrcmnt********
l
o0thiseveningthisEvening
l
l
l	Gather today's events
l
O
k
l
r
2

wres
o0
everycalendar
everyCalendar
l
r
c
J
m

list
o0
currentevents
currentEvents
Y&
k!
r#
n
4

cobj
o0i
o0
everycalendar
everyCalendar
o0thiscalthisCal
l$$
O$!
k*
r*3
2*/

wrev
o0
everyevent
everyEvent
Y4 	~
kI

rIU

nIQ
4LQ}
}
cobj
oOP||0ii
oIL{{0
everyevent
everyEvent
ozz0	thisevent	thisEventy
OV
k\
l\\xwxw
l\\vv$	Catch events that start today
r\a
m\]u
uboovfals
ott 0eventiscurrenteventIsCurrent
Zb!"sr
!Fb{#$
#lbk%q
%?bk&'
&1bgp
p
wr1s
'ogjoo0thismorningthisMorningq
$lnw(n
(Anw)*
)1nsm
m
wr1s
*osvll0thiseveningthisEveningn
"r~+,
+m~k
kboovtrue
,ojj 0eventiscurrenteventIsCurrentsr -.
-lihih./0
/lg1g1F@	Catch events that started before today, but have not yet ended.023
2Z45fe
4F67
6l8d
8?9:
91c
c
wr5s
:obb0nowd
7l;a
;A<=
<1`
`
wr1s
=o__0thismorningthisMorninga
5r>?
>m^
^boovtrue
?o]] 0eventiscurrenteventIsCurrentfe3@A
@l\[\[ABC
BlZYZYCDE
DZFGXW
FlHV
H=IJ
IoUU 0eventiscurrenteventIsCurrent
JmT
TboovtrueV
GkKKLM
LISNR
S.ascrcmnt********
NlOQ
OmPPCURRENT EVENT!QRMQR
QrST
S1P
P
wr1s
ToOO0thestarttheStartRUV
UrWX
WnYZ
Y1N
N
tstr
ZoMM0thestarttheStart
XoLL0thestarttimetheStartTimeV[\
[r]^
]c_`
_KaaKbcK0
eventtitle
eventTitle
bnde
d1J
J
wr11
eoII0	thisevent	thisEventcHfgH$0eventdescriptioneventDescription
fnhi
h1G
G
wr12
ioFF0	thisevent	thisEventgEjDE0	starttime	startTime
joCC0thestarttimetheStartTimeD
`mB
B
reco
^oAA0myrecordmyRecord\kl
krmn
mcop
oJqqr@
ro??0myrecordmyRecord@
pm>
>
list
no==0newlistnewListls<
sr	tu
tb	vw
vo	;;0
currentevents
currentEvents
wo::0newlistnewList
uo990
currentevents
currentEvents<XWExy
xl8787yz6
zl54546
oVY330	thisevent	thisEventy0ii
m7822
	n8D{|
{m?C1
1
nmbr
|n8?}~
}2;?0
0
cobj
~o8;//0
everyevent
everyEvent~
o$'..0thiscalthisCal0i
m--
n
m
,
,
nmbr
n

2
+
+
cobj
o	**0
everycalendar
everyCalendar
l'')()(
l'''&'&
l''%%	Show the events.
l''$#$#
Z'W"!
l'4
='4
n'2
m.2

nmbr
n'.
2*.

cobj
o'*0
currentevents
currentEvents
m23
O7S
l	;R
I;R
.notifygrnullnull

name
l	=@
m=@In-Script Notification

titl
l	AD
mADNo iCal events today

desc
l	GJ
mGJGo outside and play!

appl
mKN-'AppleScript iCal today's Event Notifier
m78P"!
lXX
YX

km
rmy
nmu
4pu

cobj
ost0i
omp

0
currentevents
currentEvents
o		"0thiseventrecordthisEventRecord
Qz
r}
l}
b}
b}
n}
o0
eventtitle
eventTitle
o}"0thiseventrecordthisEventRecord
m	 -
n
o0	starttime	startTime
o"0thiseventrecordthisEventRecord
o"0theeventsummarytheEventSummary
R
.ascrerr ********
r
b
m
no summary -
n
o0	starttime	startTime
o"0thiseventrecordthisEventRecord
o"0theeventsummarytheEventSummary
l
Q
r
n
o$0eventdescriptioneventDescription
o"0thiseventrecordthisEventRecord
o*0theeventdescriptiontheEventDescription
R
.ascrerr ********
r
mno description
o*0theeventdescriptiontheEventDescription
l
O
l
I
.notifygrnullnull

name
l
mToday's Events

titl
l
o"0theeventsummarytheEventSummary

desc
l
o*0theeventdescriptiontheEventDescription

appl
m-'AppleScript iCal today's Event Notifier
mP0i
m[\
n\h
mcg

nmbr
n\c
2_c

cobj
o\_0
currentevents
currentEvents

l
mnull߀^iCal.app`0L7֐0g)z(K ְwrbtalis6WideBoy.1H+^iCal.app	 Applications.1^WideBoy:Applications:iCal.appiCal.appWideBoyApplications/iCal.app/
l
l
.aevtoappnull****
.aevtoappnull****
k.in0i0iiWPBDIOX\`bP 0myallnoteslistmyAllNotesList

appl

anot

dnot

iapp
.registernullnull

name

titl

desc
.notifygrnullnull
.misccurdldt null0now

wkdy

mnth

day

year

TEXT0morningtimemorningTime

ldt 0thismorningthisMorning
.ascrcmnt********0eveningtimeeveningTime0thiseveningthisEvening

wres0
everycalendar
everyCalendar

list0
currentevents
currentEvents

cobj

nmbr0thiscalthisCal

wrev0
everyevent
everyEvent0	thisevent	thisEvent 0eventiscurrenteventIsCurrent

wr1s

bool

wr5s0thestarttheStart

tstr0thestarttimetheStartTime0
eventtitle
eventTitle

wr11$0eventdescriptioneventDescription

wr120	starttime	startTime

reco0myrecordmyRecord0newlistnewList"0thiseventrecordthisEventRecord"0theeventsummarytheEventSummary*0theeventdescriptiontheEventDescription/lvEO*UO*aaaUO*jE`Oa_a,%a%_a,%a%_a,%a%_a,%a%a%a &E`!O*a"_!/E`#O_#j$Oa%_a,%a&%_a,%a'%_a,%a(%_a,%a)%a*%a &E`+O*a"_+/E`,O_,j$Oa-*a.-E`/Ojva0&E`1O#k_/a2-a3,Ekh_/a2/E`4O_4*a5-E`6Ok_6a2-a3,Ekh_6a2/E`7O_7fE`8O*a9,_#	*a9,_,a:&
eE`8YhO*a;,_	*a9,_#a:&
eE`8YhO_8eca<j$O*a9,E`=O_=a>,E`?Oa@_7aA,aB_7aC,aD_?aEaF&E`GO_Gkva0&E`HO_1_H%E`1YhOPU[OY(U[OYO_1a2-a3,j!*aIaJaaKaLUYhOk_1a2-a3,Ekh_1a2/E`MO_Ma@,aN%_MaD,%E`OWXPQaR_MaD,%E`OO_MaB,E`SWXPQaTE`SO*aU_Oa_SaVU[OYOPUascrޭ


remove unnecessary usage of System Events

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 file_exists(filePath)
  tell application "Finder" to return exists filePath as POSIX file
end file_exists

tell application "Spotify"
  set currentArtwork to current track's artwork
  set savePath to POSIX path of (path to temporary items from user domain as string) & my replace_chars(current track's id,":","_")
  set tiffPath to (savePath & ".tiff")
  set pngPath to (savePath & ".png")
end tell

-- don't do the image events dance when the file already exists
if my file_exists(pngPath) then return pngPath

if not (my file_exists(tiffPath)) then
  set fileRef to (open for access tiffPath with write permission)
  write currentArtwork to fileRef
  close access fileRef
end

tell application "Image Events"
  launch
  set theImage to open tiffPath
  save theImage as PNG in pngPath
  delete file tiffPath
  quit
end tell

return pngPath

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 file_exists(filePath)
  tell application "Finder" to return exists filePath as POSIX file
end file_exists

tell application "Spotify"
  set currentArtwork to current track's artwork
  set savePath to POSIX path of (path to temporary items from user domain as string) & my replace_chars(current track's id,":","_")
  set tiffPath to (savePath & ".tiff")
  set pngPath to (savePath & ".png")
end tell

-- don't do the image events dance when the file already exists
if my file_exists(pngPath) then return pngPath

tell application "System Events"
  if not (my file_exists(tiffPath)) then
    set fileRef to (open for access tiffPath with write permission)
    write currentArtwork to fileRef
    close access fileRef
  end

  tell application "Image Events"
    launch
    set theImage to open tiffPath
    save theImage as PNG in pngPath
    quit
  end tell

  delete file tiffPath
  quit
end tell

return pngPath


Added code to handle checking for ffmpeg

--
--  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
property NSMutableArray : class "NSMutableArray"

script DASAppDelegate
	property parent : class "NSObject"

	-- 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

    -- 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 : ""

    -- Run NSTask to see if ffmpeg is installed...
    on awakeFromNib()
        -- Check for FFMPEG
    try
        do shell script "if [[ -r /etc/profile ]];then . /etc/profile;fi;if [[ -r ~/.bashrc ]];then . ~/.bashrc;fi;if [[ -r ~/.bash_profile ]];then . ~/.bash_profile;fi; if [ -x \"`/usr/bin/which ffmpeg`\" ];then exit 0;else exit 1;fi"
        on error number error_number
        display dialog "You must install FFMPEG to continue. \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, ensure that it is in your bash path." buttons {"Cancel","Install FFMPEG"} default button 2
    end try

    end awakeFromNib

	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened
	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
property NSMutableArray : class "NSMutableArray"

script DASAppDelegate
	property parent : class "NSObject"

	-- 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

    -- 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 : ""

    -- Run NSTask to see if ffmpeg is installed...

	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened
	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


Escape double quote in name of track, alnum and artist.

tell application "iTunes"
  set specified_tracks to (every track whose #{conditions})

	set json to "["

	repeat with specified_track in specified_tracks
    set props to {}

    set prop_name to name of specified_track

    set end of props to "{"
    set end of props to ("\"persistent_id\":\"" & persistent ID of specified_track & "\",")
    set end of props to ("\"name\":\"" & my escape_quote(name of specified_track) & "\",")
    set end of props to ("\"album\":\"" & my escape_quote(album of specified_track) & "\",")
    set end of props to ("\"artist\":\"" & my escape_quote(artist of specified_track) & "\",")
    set end of props to ("\"track_count\":\"" & track count of specified_track & "\",")
    set end of props to ("\"track_number\":\"" & track number of specified_track & "\"")
    set end of props to "}"

    set json to json & props as string & ","
  end repeat

  set json to json & "null]"
  return json

end tell

on escape_quote(someText)
 return replaceText(someText, "\"", "\\\"")
end escape_quote

(*
   https://discussions.apple.com/thread/4588230?start=0&tstart=0
*)
on replaceText(someText, oldItem, newItem)
     set {tempTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, oldItem}
     try
          set {itemList, AppleScript's text item delimiters} to {text items of someText, newItem}
          set {someText, AppleScript's text item delimiters} to {itemList as text, tempTID}
     on error errorMessage number errorNumber -- oops
          set AppleScript's text item delimiters to tempTID
          error errorMessage number errorNumber -- pass it on
     end try

     return someText
end replaceText

tell application "iTunes"
  set specified_tracks to (every track whose #{conditions})

	set json to "["

	repeat with specified_track in specified_tracks
    set props to {}
    set end of props to "{"
    set end of props to ("\"persistent_id\":\"" & persistent ID of specified_track & "\",")
    set end of props to ("\"name\":\"" & name of specified_track & "\",")
    set end of props to ("\"album\":\"" & album of specified_track & "\",")
    set end of props to ("\"artist\":\"" & artist of specified_track & "\",")
    set end of props to ("\"track_count\":\"" & track count of specified_track & "\",")
    set end of props to ("\"track_number\":\"" & track number of specified_track & "\"")
    set end of props to "}"

    set json to json & props as string & ","
  end repeat

  set json to json & "null]"
  return json

end tell