Fix regression where a2ec45c broke playalbumby filter

This is because a2ec45c removed the getArtistAlbums handler, which is
used by the playalbumby filter.

-- core configuration --

-- configurable options --

-- limit number of songs to improve efficiency
property resultLimit : 15
-- whether or not to retrieve/display album artwork for each result
property albumArtEnabled : true

-- workflow parameters --

-- workflow folders
property libraryFolder : (path to library folder from user domain as text)
property cacheFolder : (libraryFolder & "Caches:")
property alfredWorkflowDataFolder : (cacheFolder & "com.runningwithcrayons.Alfred:Workflow Data:")
property bundleId : "com.calebevans.playsong"
property workflowCacheFolder : (alfredWorkflowDataFolder & bundleId & ":") as text

-- the default icon used for search results without album artwork
property defaultIconName : "resources/icon-noartwork.png"
-- the name of the playlist used by the workflow for playing songs
property workflowPlaylistName : "Alfred Play Song"
-- list of Alfred results
property resultList : {}

-- replaces substring in string with another substring
on replace(replaceThis, replaceWith, theString)

	set oldDelims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to replaceThis
	set strItems to text items of theString
	set AppleScript's text item delimiters to replaceWith
	set newString to strItems as text
	set AppleScript's text item delimiters to oldDelims
	return newString

end replace

-- retrieve the plural/singular form of a quantity based on the given number
on quantifyNumber(theNumber, quantityName, pluralQuantityName)

	if theNumber is 1 then

		set theString to (theNumber as text) & space & quantityName

	else

		set theString to (theNumber as text) & space & pluralQuantityName

	end if

	return theString

end quantifyNumber

-- encodes JSON reserved characters in the given string
on encodeFeedbackChars(theString)

	set theString to replace("\\", "\\\\", theString)
	set theString to replace("\"", "\\\"", theString)
	return theString

end encodeFeedbackChars

-- decodes JSON reserved characters in the given string
on decodeFeedbackChars(theString)

	set theString to replace("\\\\", "\\", theString)
	set theString to replace("\\\"", "\"", theString)
	return theString

end decodeFeedbackChars

-- adds Alfred result to result list
on addResult(theResult)

	copy theResult to the end of resultList

end addResult

-- adds item for "No Results" message
on addNoResultsItem(query, queryType)

	addResult({uid:"no-results", valid:"no", title:"No Results Found", subtitle:("No " & queryType & "s matching '" & query & "'"), icon:defaultIconName})

end addNoResultsItem

on resultListIsFull()

	return (length of resultList is resultLimit)

end resultListIsFull

on resultListIsEmpty()

	return (length of resultList is 0)

end resultListIsFull

-- builds Alfred result item as JSON
on getResultFeedback(theResult)

	-- encode reserved JSON characters
	set resultUid to encodeFeedbackChars(uid of theResult)
	set resultValid to (valid of theResult) as text
	set resultTitle to encodeFeedbackChars(title of theResult)
	set resultSubtitle to encodeFeedbackChars(subtitle of theResult)

	if (icon of theResult) contains ":" then

		set resultIcon to encodeFeedbackChars(POSIX path of icon of theResult)

	else

		set resultIcon to icon of theResult

	end if

	set json to "{"
	set json to json & "\"uid\":\"" & resultUid & "\","
	set json to json & "\"arg\":\"" & resultUid & "\","
	set json to json & "\"valid\":\"" & resultValid & "\","
	set json to json & "\"title\":\"" & resultTitle & "\","
	set json to json & "\"subtitle\":\"" & resultSubtitle & "\","
	set json to json & "\"icon\":{\"path\":\"" & resultIcon & "\"}"
	set json to json & "}"
	return json

end getResultFeedback

-- retrieves JSON document for Alfred results
on getResultListFeedback()

	set json to "{\"items\": ["

	repeat with theResult in resultList

		set json to json & getResultFeedback(theResult)
		set json to json & ","

	end repeat

	-- remove trailing comma after last item
	set json to text 1 thru (length of json - 1) of json
	set json to json & "]}"
	return json

end getResultListFeedback

-- query path to artwork image file cached natively by Music.app in Catalina
on getSongArtworkPath(theSong)

	try

		if albumArtEnabled is false then return defaultIconName

		tell application "Music"

			-- get persistent ID of song and use it to fetch album artwork
			set songId to persistent ID of theSong
			-- the base path to the artwork file (without extension)
			set artworkPath to (do shell script "./resources/get-song-artwork-path.sh" & space & songId & space & defaultIconName)

		end tell

		return artworkPath

	on error errorMessage

		log errorMessage

	end try

end getSongArtworkPath

-- creates album artwork cache
on createWorkflowPlaylist()

	tell application "Music"

		if not (user playlist workflowPlaylistName exists) then

			make new user playlist with properties {name:workflowPlaylistName, shuffle:false}

		end if

	end tell

end createWorkflowPlaylist

on clearQueue()

	tell application "Music"

		if user playlist workflowPlaylistName exists then

			delete tracks of user playlist workflowPlaylistName

		end if

	end tell

end clearQueue

on queueSongs(theSongs)

	tell application "Music"

		repeat with theSong in theSongs

			duplicate theSong to user playlist workflowPlaylistName

		end repeat

	end tell

end queueSongs

on playQueue()

	tell application "Music"

		if number of tracks in user playlist workflowPlaylistName is not 0 then

			play user playlist workflowPlaylistName

		end if

	end tell

end playQueue

on getPlaylist(playlistId)

	tell application "Music"

		return (first playlist whose id is playlistId)

	end tell

end getPlaylist

on getPlaylistSongs(playlistId)

	tell application "Music"

		set thePlaylist to getPlaylist(playlistId) of me
		set playlistSongs to every track of thePlaylist

	end tell

	return playlistSongs

end getPlaylistSongs

-- retrieves list of songs within the given genre, sorted by artist
on getGenreSongs(genreName)

	tell application "Music"

		set genreSongs to every track of playlist 2 whose genre is genreName

	end tell

	return genreSongs

end getGenreSongs

-- retrieves list of album names for the given artist
on getArtistAlbums(artistName)

    tell application "Music"

        set artistSongs to every track of playlist 2 whose artist is artistName
        set albumNames to {}

        repeat with theSong in artistSongs

            if (album of theSong) is not in albumNames then

                set albumNames to albumNames & (album of theSong)

            end if

        end repeat

    end tell

    return albumNames

end getArtistAlbums

-- retrieves list of songs by the given artist, sorted by album
on getArtistSongs(artistName)

	tell application "Music"

		set artistSongs to every track of playlist 2 whose artist is artistName

	end tell

	return artistSongs

end getArtistSongs

-- retrieves list of songs in the given album
on getAlbumSongs(albumName)

	tell application "Music"

		set albumSongs to every track of playlist 2 whose album is albumName

	end tell

	return albumSongs

end getAlbumSongs

-- retrieves the song with the given ID
on getSong(songId)

	tell application "Music"

		set theSong to first track of playlist 2 whose database ID is songId

	end tell

	return theSong

end getSong

-- retrieves a list of objects or names matching the given query and type
on getResultsFromQuery(query, queryType)

	set evalScript to run script "
	script

		on findResults(query, queryType, resultLimit)

			tell application \"Music\"

				set theSongs to (get every track in playlist 2 whose " & queryType & " starts with query)

				if length of theSongs < resultLimit then

					set theSongs to theSongs & (get every track in playlist 2 whose " & queryType & " contains (space & query) and " & queryType & " does not start with query)

				end if

				if length of theSongs < resultLimit then

					set theSongs to theSongs & (get every track in playlist 2 whose " & queryType & " contains query and " & queryType & " does not start with query and " & queryType & " does not contain (space & query))

				end if

				if length of theSongs is 0 then

					if queryType is \"name\" then

						set theSongs to theSongs & (search playlist 2 for query only songs)

					else if queryType is not \"genre\" then

						set theSongs to theSongs & (search playlist 2 for query only " & queryType & "s)

					end if

				end if

				if queryType is \"name\" then

					if length of theSongs > resultLimit then

						set theSongs to items 1 thru resultLimit of theSongs

					end if

					set theResults to theSongs

				else

					set theResults to {}

					repeat with theSong in theSongs

						if length of theResults is resultLimit then exit repeat

						set theResult to " & queryType & " of theSong

						if theResult is not in theResults then

							set theResults to theResults & theResult

						end if

					end repeat

				end if

			end tell

			return theResults

		end findResults

	end script
	"

	evalScript's findResults(query, queryType, resultLimit)

end getResultsFromQuery

-- returns the given string with leading and trailing whitespace removed
on trimWhitespace(theString)

	-- trim leading whitespace
	repeat while theString begins with space

		if length of theString is 1 then return ""
		set theString to text 2 thru end of theString

	end repeat

	-- trim trailing whitespace
	repeat while theString ends with space

		set theString to text 1 thru ((length of theString) - 1) of theString

	end repeat

	return theString

end trimWhitespace

-- queues the song with the given ID
on queueSong(songId)

	set theSong to getSong(songId)
	queueSongs({theSong})

end queueSong

-- queues all songs belonging to the given album
on queueAlbum(albumName)

	set albumName to decodeFeedbackChars(albumName)
	set albumSongs to getAlbumSongs(albumName)
	queueSongs(albumSongs)

end queueAlbum

-- queues all songs by the given artist
on queueArtist(artistName)

	set artistName to decodeFeedbackChars(artistName)
	set artistSongs to getArtistSongs(artistName)
	queueSongs(artistSongs)

end queueArtist

-- queues all songs within the given genre
on queueGenre(genreName)

	set genreName to decodeFeedbackChars(genreName)
	set genreSongs to getGenreSongs(genreName)
	queueSongs(genreSongs)

end queueGenre

-- queues all songs in the given playlist
on queuePlaylist(playlistId)

	set playlistSongs to getPlaylistSongs(playlistId)
	queueSongs(playlistSongs)

end queuePlaylist

-- parses the given result query to retrieve type and id of item to queue
on parseResultQuery(query)

	set pos to offset of "-" in query
	set theType to text 1 thru (pos - 1) of query
	set theId to text (pos + 1) thru end of query
	return {type:theType, id:theId}

end parseResultQuery

on queue(query)

	set typeAndId to parseResultQuery(query)
	set theType to type of typeAndId
	set theId to id of typeAndId

	createWorkflowPlaylist()

	if theType is "song" then
		queueSong(theId)
	else if theType is "album" then
		queueAlbum(theId)
	else if theType is "artist" then
		queueArtist(theId)
	else if theType is "genre" then
		queueGenre(theId)
	else if theType is "playlist" then
		queuePlaylist(theId)
	else
		log "Unsupported type: " & theType
	end if

end queue

on play(query)

	clearQueue()
	queue(query)
	playQueue()

end play

-- core configuration --

-- configurable options --

-- limit number of songs to improve efficiency
property resultLimit : 15
-- whether or not to retrieve/display album artwork for each result
property albumArtEnabled : true

-- workflow parameters --

-- workflow folders
property libraryFolder : (path to library folder from user domain as text)
property cacheFolder : (libraryFolder & "Caches:")
property alfredWorkflowDataFolder : (cacheFolder & "com.runningwithcrayons.Alfred:Workflow Data:")
property bundleId : "com.calebevans.playsong"
property workflowCacheFolder : (alfredWorkflowDataFolder & bundleId & ":") as text

-- the default icon used for search results without album artwork
property defaultIconName : "resources/icon-noartwork.png"
-- the name of the playlist used by the workflow for playing songs
property workflowPlaylistName : "Alfred Play Song"
-- list of Alfred results
property resultList : {}

-- replaces substring in string with another substring
on replace(replaceThis, replaceWith, theString)

	set oldDelims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to replaceThis
	set strItems to text items of theString
	set AppleScript's text item delimiters to replaceWith
	set newString to strItems as text
	set AppleScript's text item delimiters to oldDelims
	return newString

end replace

-- retrieve the plural/singular form of a quantity based on the given number
on quantifyNumber(theNumber, quantityName, pluralQuantityName)

	if theNumber is 1 then

		set theString to (theNumber as text) & space & quantityName

	else

		set theString to (theNumber as text) & space & pluralQuantityName

	end if

	return theString

end quantifyNumber

-- encodes JSON reserved characters in the given string
on encodeFeedbackChars(theString)

	set theString to replace("\\", "\\\\", theString)
	set theString to replace("\"", "\\\"", theString)
	return theString

end encodeFeedbackChars

-- decodes JSON reserved characters in the given string
on decodeFeedbackChars(theString)

	set theString to replace("\\\\", "\\", theString)
	set theString to replace("\\\"", "\"", theString)
	return theString

end decodeFeedbackChars

-- adds Alfred result to result list
on addResult(theResult)

	copy theResult to the end of resultList

end addResult

-- adds item for "No Results" message
on addNoResultsItem(query, queryType)

	addResult({uid:"no-results", valid:"no", title:"No Results Found", subtitle:("No " & queryType & "s matching '" & query & "'"), icon:defaultIconName})

end addNoResultsItem

on resultListIsFull()

	return (length of resultList is resultLimit)

end resultListIsFull

on resultListIsEmpty()

	return (length of resultList is 0)

end resultListIsFull

-- builds Alfred result item as JSON
on getResultFeedback(theResult)

	-- encode reserved JSON characters
	set resultUid to encodeFeedbackChars(uid of theResult)
	set resultValid to (valid of theResult) as text
	set resultTitle to encodeFeedbackChars(title of theResult)
	set resultSubtitle to encodeFeedbackChars(subtitle of theResult)

	if (icon of theResult) contains ":" then

		set resultIcon to encodeFeedbackChars(POSIX path of icon of theResult)

	else

		set resultIcon to icon of theResult

	end if

	set json to "{"
	set json to json & "\"uid\":\"" & resultUid & "\","
	set json to json & "\"arg\":\"" & resultUid & "\","
	set json to json & "\"valid\":\"" & resultValid & "\","
	set json to json & "\"title\":\"" & resultTitle & "\","
	set json to json & "\"subtitle\":\"" & resultSubtitle & "\","
	set json to json & "\"icon\":{\"path\":\"" & resultIcon & "\"}"
	set json to json & "}"
	return json

end getResultFeedback

-- retrieves JSON document for Alfred results
on getResultListFeedback()

	set json to "{\"items\": ["

	repeat with theResult in resultList

		set json to json & getResultFeedback(theResult)
		set json to json & ","

	end repeat

	-- remove trailing comma after last item
	set json to text 1 thru (length of json - 1) of json
	set json to json & "]}"
	return json

end getResultListFeedback

-- query path to artwork image file cached natively by Music.app in Catalina
on getSongArtworkPath(theSong)

	try

		if albumArtEnabled is false then return defaultIconName

		tell application "Music"

			-- get persistent ID of song and use it to fetch album artwork
			set songId to persistent ID of theSong
			-- the base path to the artwork file (without extension)
			set artworkPath to (do shell script "./resources/get-song-artwork-path.sh" & space & songId & space & defaultIconName)

		end tell

		return artworkPath

	on error errorMessage

		log errorMessage

	end try

end getSongArtworkPath

-- creates album artwork cache
on createWorkflowPlaylist()

	tell application "Music"

		if not (user playlist workflowPlaylistName exists) then

			make new user playlist with properties {name:workflowPlaylistName, shuffle:false}

		end if

	end tell

end createWorkflowPlaylist

on clearQueue()

	tell application "Music"

		if user playlist workflowPlaylistName exists then

			delete tracks of user playlist workflowPlaylistName

		end if

	end tell

end clearQueue

on queueSongs(theSongs)

	tell application "Music"

		repeat with theSong in theSongs

			duplicate theSong to user playlist workflowPlaylistName

		end repeat

	end tell

end queueSongs

on playQueue()

	tell application "Music"

		if number of tracks in user playlist workflowPlaylistName is not 0 then

			play user playlist workflowPlaylistName

		end if

	end tell

end playQueue

on getPlaylist(playlistId)

	tell application "Music"

		return (first playlist whose id is playlistId)

	end tell

end getPlaylist

on getPlaylistSongs(playlistId)

	tell application "Music"

		set thePlaylist to getPlaylist(playlistId) of me
		set playlistSongs to every track of thePlaylist

	end tell

	return playlistSongs

end getPlaylistSongs

-- retrieves list of songs within the given genre, sorted by artist
on getGenreSongs(genreName)

	tell application "Music"

		set genreSongs to every track of playlist 2 whose genre is genreName

	end tell

	return genreSongs

end getGenreSongs

-- retrieves list of songs by the given artist, sorted by album
on getArtistSongs(artistName)

	tell application "Music"

		set artistSongs to every track of playlist 2 whose artist is artistName

	end tell

	return artistSongs

end getArtistSongs

-- retrieves list of songs in the given album
on getAlbumSongs(albumName)

	tell application "Music"

		set albumSongs to every track of playlist 2 whose album is albumName

	end tell

	return albumSongs

end getAlbumSongs

-- retrieves the song with the given ID
on getSong(songId)

	tell application "Music"

		set theSong to first track of playlist 2 whose database ID is songId

	end tell

	return theSong

end getSong

-- retrieves a list of objects or names matching the given query and type
on getResultsFromQuery(query, queryType)

	set evalScript to run script "
	script

		on findResults(query, queryType, resultLimit)

			tell application \"Music\"

				set theSongs to (get every track in playlist 2 whose " & queryType & " starts with query)

				if length of theSongs < resultLimit then

					set theSongs to theSongs & (get every track in playlist 2 whose " & queryType & " contains (space & query) and " & queryType & " does not start with query)

				end if

				if length of theSongs < resultLimit then

					set theSongs to theSongs & (get every track in playlist 2 whose " & queryType & " contains query and " & queryType & " does not start with query and " & queryType & " does not contain (space & query))

				end if

				if length of theSongs is 0 then

					if queryType is \"name\" then

						set theSongs to theSongs & (search playlist 2 for query only songs)

					else if queryType is not \"genre\" then

						set theSongs to theSongs & (search playlist 2 for query only " & queryType & "s)

					end if

				end if

				if queryType is \"name\" then

					if length of theSongs > resultLimit then

						set theSongs to items 1 thru resultLimit of theSongs

					end if

					set theResults to theSongs

				else

					set theResults to {}

					repeat with theSong in theSongs

						if length of theResults is resultLimit then exit repeat

						set theResult to " & queryType & " of theSong

						if theResult is not in theResults then

							set theResults to theResults & theResult

						end if

					end repeat

				end if

			end tell

			return theResults

		end findResults

	end script
	"

	evalScript's findResults(query, queryType, resultLimit)

end getResultsFromQuery

-- returns the given string with leading and trailing whitespace removed
on trimWhitespace(theString)

	-- trim leading whitespace
	repeat while theString begins with space

		if length of theString is 1 then return ""
		set theString to text 2 thru end of theString

	end repeat

	-- trim trailing whitespace
	repeat while theString ends with space

		set theString to text 1 thru ((length of theString) - 1) of theString

	end repeat

	return theString

end trimWhitespace

-- queues the song with the given ID
on queueSong(songId)

	set theSong to getSong(songId)
	queueSongs({theSong})

end queueSong

-- queues all songs belonging to the given album
on queueAlbum(albumName)

	set albumName to decodeFeedbackChars(albumName)
	set albumSongs to getAlbumSongs(albumName)
	queueSongs(albumSongs)

end queueAlbum

-- queues all songs by the given artist
on queueArtist(artistName)

	set artistName to decodeFeedbackChars(artistName)
	set artistSongs to getArtistSongs(artistName)
	queueSongs(artistSongs)

end queueArtist

-- queues all songs within the given genre
on queueGenre(genreName)

	set genreName to decodeFeedbackChars(genreName)
	set genreSongs to getGenreSongs(genreName)
	queueSongs(genreSongs)

end queueGenre

-- queues all songs in the given playlist
on queuePlaylist(playlistId)

	set playlistSongs to getPlaylistSongs(playlistId)
	queueSongs(playlistSongs)

end queuePlaylist

-- parses the given result query to retrieve type and id of item to queue
on parseResultQuery(query)

	set pos to offset of "-" in query
	set theType to text 1 thru (pos - 1) of query
	set theId to text (pos + 1) thru end of query
	return {type:theType, id:theId}

end parseResultQuery

on queue(query)

	set typeAndId to parseResultQuery(query)
	set theType to type of typeAndId
	set theId to id of typeAndId

	createWorkflowPlaylist()

	if theType is "song" then
		queueSong(theId)
	else if theType is "album" then
		queueAlbum(theId)
	else if theType is "artist" then
		queueArtist(theId)
	else if theType is "genre" then
		queueGenre(theId)
	else if theType is "playlist" then
		queuePlaylist(theId)
	else
		log "Unsupported type: " & theType
	end if

end queue

on play(query)

	clearQueue()
	queue(query)
	playQueue()

end play


Try catch statements for when there's no terminal


Fixes #12 — now actually quits

Fixes #12 — now actually quits

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

    -- 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 install ffmpeg mp4v2 && exit 0;else /usr/bin/ruby -e \"$(/usr/bin/curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/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
                    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

        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
        -- Prepare tags
        if pcatName is not "" then set fcatName to (" -song \"" & pcatName & "\" ")
        if fcatName contains "\"\"" then set fcatName to ""
        if pcatAlbum is not "" then set fcatAlbum to (" -album \"" & pcatAlbum & "\" ")
        if fcatAlbum contains "\"\"" then set fcatAlbum to ""
        if pcatArtist is not "" then set fcatArtist to (" -artist \"" & pcatArtist & "\" ")
        if fcatArtist contains "\"\"" then set fcatArtist to ""
        if pcatComposer is not "" then set fcatComposer to (" -writer \"" & pcatComposer & "\" ")
        if fcatComposer contains "\"\"" then set fcatComposer to ""
        if pcatGenre is not "" then set fcatGenre to (" -genre \"" & pcatGenre & "\" ")
        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 \"" & pcatAlbumArtist & "\" ")
        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
        -- 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
        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

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

    -- 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 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 install ffmpeg mp4v2 && exit 0;else /usr/bin/ruby -e \"$(/usr/bin/curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/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
        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

        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
        -- Prepare tags
        if pcatName is not "" then set fcatName to (" -song \"" & pcatName & "\" ")
        if fcatName contains "\"\"" then set fcatName to ""
        if pcatAlbum is not "" then set fcatAlbum to (" -album \"" & pcatAlbum & "\" ")
        if fcatAlbum contains "\"\"" then set fcatAlbum to ""
        if pcatArtist is not "" then set fcatArtist to (" -artist \"" & pcatArtist & "\" ")
        if fcatArtist contains "\"\"" then set fcatArtist to ""
        if pcatComposer is not "" then set fcatComposer to (" -writer \"" & pcatComposer & "\" ")
        if fcatComposer contains "\"\"" then set fcatComposer to ""
        if pcatGenre is not "" then set fcatGenre to (" -genre \"" & pcatGenre & "\" ")
        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 \"" & pcatAlbumArtist & "\" ")
        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
        -- 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


Fix to support 'install to device' on iOS when no device present or sync disallowed [TISTUD-209]

FasdUAS 1.101.10
lL
OL
YK
ZF

=

l
n
1

pKnd
4

cSrc
o0n

m
eSrckPod
QB
I"'
.hookUpdtnullcSrc
o"#0n
R
.ascrerr ********
o0errorstrerrorStr

errn
o0errornumbererrorNumber
I/B
.ascrcmnt********
b/>
b/<
b/:
b/8 !
 b/6"#
"b/4$%
$m/0&&''The device
%n03()
(113

pnam
)o010n
#m45**++* was unable to sync (
!o670errorstrerrorStr
m89,,--:
o:;0errornumbererrorNumber
m<=..//)0n
m
	l0
0I1
.corecnte********
12

cSrc
m22hookalisLMacintosh HDSH+q
iTunes.app7l	 Applicationsm$wq$Macintosh HD:Applications:iTunes.app
iTunes.appMacintosh HDApplications/iTunes.app/343
.aevtoappnull****4567
.aevtoappnull****
5kL8860n0errorstrerrorStr0errornumbererrorNumber729&*,.

cSrc
.corecnte********

pKnd
eSrckPod
.hookUpdtnullcSrc0errorstrerrorStr9

errn0errornumbererrorNumber

pnam
.ascrcmnt********MIFk*-jkh*/,(
jWX,%%%%%%j
Yh[OYUascrޭ

FasdUAS 1.101.10
l

O

I
.hookUpdtnullcSrc
mhookalisLMacintosh HD@eH+
iTunes.appuWMU	 Applications@ML$Macintosh HD:Applications:iTunes.app
iTunes.appMacintosh HDApplications/iTunes.app/
.aevtoappnull****

.aevtoappnull****

k

.hookUpdtnullcSrc*jUascrޭ


revert: create new Terminal window to open fold path

JsOsaDAS1.001.00bplist00Vscriptom//  The MIT License (MIT)
//  Copyright  2017 Lex Tang, http://lexrus.com
//
//  https://github.com/lexrus/LTFinderButtons
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the  Software ), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED  AS IS , WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.

var app = Application.currentApplication()
app.includeStandardAdditions = true

ObjC.import("Foundation")

function urlPathToPosixPath(path) {
	return unescape(path)
	    .replace(/^\/?file[:]\/+/i, '/')
		.replace(/(")/g, '\\$1')
}

function getCurrentFinderFolderPath() {
	var Finder = Application('Finder')
	var item = Finder.selection()[0]
	if (!item) {
		try {
			return urlPathToPosixPath(Finder.windows[0].target().url())
		} catch (e) {
			return urlPathToPosixPath(Finder.desktop().url())
		}
	}
	if (item.kind() == 'Folder') {
		return urlPathToPosixPath(item.url())
	}

	var fileURL = $.NSURL.alloc.initFileURLWithPath(item.url())
	var urlPath = ObjC.unwrap(fileURL.path.stringByDeletingLastPathComponent)
	return urlPathToPosixPath(urlPath)
}

var currentFolderPath = getCurrentFinderFolderPath()

var cmd = `cd "${currentFolderPath}";clear;`

var Terminal = Application('Terminal')
Terminal.activate()
Terminal.doScript(cmd)

jscrޭ

JsOsaDAS1.001.00bplist00Vscripto	//  The MIT License (MIT)
//  Copyright  2017 Lex Tang, http://lexrus.com
//
//  https://github.com/lexrus/LTFinderButtons
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the  Software ), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED  AS IS , WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.

var app = Application.currentApplication()
app.includeStandardAdditions = true

ObjC.import("Foundation")

function urlPathToPosixPath(path) {
	return unescape(path)
	    .replace(/^\/?file[:]\/+/i, '/')
		.replace(/(")/g, '\\$1')
}

function getCurrentFinderFolderPath() {
	var Finder = Application('Finder')
	var item = Finder.selection()[0]
	if (!item) {
		try {
			return urlPathToPosixPath(Finder.windows[0].target().url())
		} catch (e) {
			return urlPathToPosixPath(Finder.desktop().url())
		}
	}
	if (item.kind() == 'Folder') {
		return urlPathToPosixPath(item.url())
	}

	var fileURL = $.NSURL.alloc.initFileURLWithPath(item.url())
	var urlPath = ObjC.unwrap(fileURL.path.stringByDeletingLastPathComponent)
	return urlPathToPosixPath(urlPath)
}

function commandExistWindow(command) {
    var Terminal = Application('Terminal')
    Terminal.activate()
    try {
        currentWindow = Terminal.windows.at(0)
        currentTab = currentWindow.selectedTab()
        Terminal.doScript(command, {
            in: currentTab
        })
    } catch(err) {
        // console.log(err) // no window
        Terminal.doScript(command);
    }
}

var currentFolderPath = getCurrentFinderFolderPath()
var cmd = `tmux -2 -u new-window -c "${currentFolderPath}";`
commandExistWindow(cmd)

jscrޭ


Save before committing!

Save before committing!

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

tell application "Finder"
	tell disk "Growl"
		open
		tell container window
			set current view to icon view
			set toolbar visible to false
			set statusbar visible to false
			--set the bounds to {30, 50, 579, 600}
		end tell
		close
		set opts to the icon view options of container window
		tell opts
			set icon size to 64
			set arrangement to not arranged
		end tell
		set background picture of opts to file ".background:growlDMGBackground.png"
		set position of item "Growl.prefPane" to {147, 75}
		set position of item "Extras" to {80, 315}
		--set position of item "Scripts" to {36, 153}
		set position of item "Growl Documentation.webloc" to {100, 215}
		set position of item "Growl version history.webloc" to {275, 215}
		set position of item "Get more styles.webloc" to {415, 215}
		set position of item "Uninstall Growl.app" to {415, 315}
		update without registering applications
		tell container window
			open
			set the_window_id to id
		end tell
		update without registering applications
	end tell
	set bounds of window id the_window_id to {30, 50, 579, 462}
	--give the finder some time to write the .DS_Store file
	delay 5
end tell

tell application "Finder"
	tell disk "Growl"
		open
		tell container window
			set current view to icon view
			set toolbar visible to false
			set statusbar visible to false
			--set the bounds to {30, 50, 579, 600}
		end tell
		close
		set opts to the icon view options of container window
		tell opts
			set icon size to 64
			set arrangement to not arranged
		end tell
		set background picture of opts to file ".background:growlDMGBackground.png"
		set position of item "Growl.prefPane" to {147, 75}
		set position of item "Extras" to {80, 315}
		--set position of item "Scripts" to {36, 153}
		set position of item "Growl Documentation.webloc" to {100, 215}
		set position of item "Growl version history.webloc" to {275, 215}
		set position of item "Get more styles.webloc" to {415, 215}
		set position of item "Uninstall Growl.app" to {415, 315}
		update without registering applications
		set the_window_id to id of container window
		update without registering applications
	end tell
	set bounds of window id the_window_id to {30, 50, 579, 900}
	--give the finder some time to write the .DS_Store file
	delay 5
end tell


updated fmGUI_PasteFromClipboard to handle pasting styled

-- fmGUI_PasteFromClipboard()
-- Erik Shagdar, NYHTC
-- Paste FileMaker object into the current context. Assumes the focus is already set and there is an object in the clipboard

(*
HISTORY:
	1.1 - 2016-09-29 ( eshagdar ): HTC is converting 'Paste' menu item to 'Paste Styled Text'. The default 'Paste' shortcut is pasting plain text. This tries the default 'Paste' command, and then uses 'Paste Styled Text' if needed.
	1.0 - 2016-06-28 ( eshagdar ): first created
*)

property helper : ""

on run
	set pathHelper to do shell script "dirname " & quoted form of POSIX path of ((path to me) as string)
	set pathHelper to do shell script "dirname " & quoted form of POSIX path of pathHelper
	set pathHelper to do shell script "dirname " & quoted form of POSIX path of pathHelper
	set pathHelper to POSIX file (pathHelper & "/main.scpt") as string
	set helper to load script file pathHelper

	fmGUI_PasteFromClipboard()
end run

--------------------
-- START OF CODE
--------------------

on fmGUI_PasteFromClipboard()
	-- version 1.1, Erik Shagdar

	set paseMenuItemExists to false

	tell application "System Events"
		tell application process "FileMaker Pro Advanced"

			my fmGUI_AppFrontMost()

			try
				set pasteMenuItem to first menu item of menu 1 of menu bar item "Edit" of menu bar 1 whose name is "Paste"
			on error
				set pasteMenuItem to first menu item of menu 1 of menu bar item "Edit" of menu bar 1 whose name is "Paste Styled Text"
			end try

			return pasteMenuItem
			try
				click pasteMenuItem
			on error errMsg number errNum
				error "Unable to click 'Select All' menu item - " & errMsg number errNum
			end try

			-- waiting until the paste item exists suggests the paste completed
			repeat 20 times
				try
					if exists pasteMenuItem then
						set paseMenuItemExists to true
						exit repeat
					end if
				end try
				delay 0.5
			end repeat
		end tell
	end tell

	return paseMenuItemExists

end fmGUI_PasteFromClipboard

--------------------
-- END OF CODE
--------------------
on fmGUI_AppFrontMost()
	tell helper to fmGUI_AppFrontMost()
end fmGUI_AppFrontMost

-- fmGUI_PasteFromClipboard()
-- Erik Shagdar, NYHTC
-- Paste FileMaker object into the current context. Assumes the focus is already set and there is an object in the clipboard

(*
HISTORY:
	1.0 - 2016-06-28 ( eshagdar ): first created
*)

property helper : ""

on run
	set pathHelper to do shell script "dirname " & quoted form of POSIX path of ((path to me) as string)
	set pathHelper to do shell script "dirname " & quoted form of POSIX path of pathHelper
	set pathHelper to do shell script "dirname " & quoted form of POSIX path of pathHelper
	set pathHelper to POSIX file (pathHelper & "/main.scpt") as string
	set helper to load script file pathHelper

	fmGUI_PasteFromClipboard({})
end run

--------------------
-- START OF CODE
--------------------

on fmGUI_PasteFromClipboard()
	-- version 1.0, Erik Shagdar

	set paseMenuItemExists to false

	tell application "System Events"
		tell application process "FileMaker Pro Advanced"

			my fmGUI_AppFrontMost()

			set pasteMenuItem to first menu item of menu 1 of menu bar item "Edit" of menu bar 1 whose name is "Paste"
			try
				click pasteMenuItem
			on error errMsg number errNum
				error "Unable to click 'Select All' menu item - " & errMsg number errNum
			end try

			-- waiting until the paste item exists suggests the paste completed
			repeat 20 times
				try
					if exists pasteMenuItem then
						set paseMenuItemExists to true
						exit repeat
					end if
				end try
				delay 0.5
			end repeat
		end tell
	end tell

	return paseMenuItemExists

end fmGUI_PasteFromClipboard

--------------------
-- END OF CODE
--------------------
on fmGUI_AppFrontMost()
	tell helper to fmGUI_AppFrontMost()
end fmGUI_AppFrontMost