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

Shadowhawk109

macrumors newbie
Original poster
Jun 10, 2010
4
0
Hi there,

I wrote a simple AppleScript that gets a random line from a song playing in iTunes, then outputs that line as well as the next four. I linked it up to Adium through use of AdiumScripts, but it memory leaks like nobody's business, and completely unpredictably. Sometimes I can go a whole day with ~4MB usage (good!), sometimes it takes all of five seconds to use two to three GIGABYTES of RAM.

Should be noted that I just modified someone elses code; which, as it explicitly says, they were fine with.

Any advice?

Code:
-- **** by quis 
-- **** www.quis.cc
-- **** this is a script for use with adium
-- **** version 1.0
-- **** do whatever you want with this code
-- **** see 
-- ****   http://adiumxtras.com/index.php?a=xtras&xtra_id=2187
-- **** for more
substitute()
on substitute()
	--You can configure the variables below without changing the logic of the script.
	--If iTunes is either paused or closed, this is displayed:
	set quiet to "Silence."
	--If you'd like a suffix to be displayed (for example, an ellipsis), set it below:
	set suffix to ""
	--If you want a comma, if present, at the end of the lyric line itself to be removed, keep this true.
	--Otherwise, set it to false.
	--As an example of what this does:  if the lyric chosen is "The lookout has parked the car," (from Kate Bush's song "There Goes a Tenner"), the resulting lyric displayed becomes "The lookout has parked the car" and whatever suffix you've specified, if you've done so.  Note that if your suffix itself is a comma, it will be removed if this option is set to true.
	--Remember that you can override what's displayed for any song (for example, if it's instrumental and thus has no lyrics) by adding "display lyric as ", followed by whatever you want to display, to the end of the song's comment.
	--For example, if you wanted a certain classical track to display as "Interlude while I run and get something", append "display lyric as Interlude while I run and get something" to that track's comment.
	set removeendcomma to true
	--If there are no lyrics for a song, what do you want to be displayed?  Set it below:
	set returnifnolyric to "No Lyrics"
	--Changing things below this may change the logic of the script.
	--check if iTunes is running...
	tell application "System Events"
		set iTunes to ((application processes whose (name is equal to "iTunes")) count)
	end tell
	if iTunes is greater than 0 then
		tell application "iTunes"
			--...and playing
			if player state is playing then
				--grab handler for current track
				set song to current track
				--are there lyrics in the comment section?
				if comment of song contains "display lyric as " then
					--return comment of song
					set _chars to characters of ((get comment of song) & "") as list
					set todisplay to ""
					repeat with i from ((offset of "display lyric as " in (get comment of song)) + 17) to (length of _chars)
						set todisplay to todisplay & (get item i of _chars)
					end repeat
					return todisplay
				end if
				--do lyrics exist?
				if lyrics of song is equal to "" then
					return returnifnolyric
				end if
				--if neither, fetch current lyrics
				set final to ""
				set tuid to database ID of song
				--get tuid of song that was playing last time this script ran
				set oldtuid to do shell script "/bin/cat ~/Library/Application\\ Support/Adium\\ 2.0/Scripts/ParaLyrical.AdiumScripts/Contents/Resources/cache.dat"
				--pass track unique identifier to cache file
				if tuid as integer is not equal to oldtuid as integer then
					--	repeat until (final is not "")
					--get lyrics
					set lyric to lyrics of song
					--count lines
					set paracount to count paragraphs of lyric
					--set paracount to paracount - 5
					
					set boolvalid to false
					
					repeat until boolvalid is true
						--choose a random line
						set randomnumber to random number from 1 to paracount as integer
						set randomnumber2 to randomnumber + 1 as integer
						set randomnumber3 to randomnumber + 2 as integer
						set randomnumber4 to randomnumber + 3 as integer
						set randomnumber5 to randomnumber + 4 as integer
						if randomnumber5 is greater than paracount then
							set boolvalid to false
						else
							set boolvalid to true
						end if
					end repeat
					
					--ORIGINAL CODE
					set randomline to paragraph randomnumber of lyric
					set randomline2 to paragraph randomnumber2 of lyric
					set randomline3 to paragraph randomnumber3 of lyric
					set randomline4 to paragraph randomnumber4 of lyric
					set randomline5 to paragraph randomnumber5 of lyric
					
					--work some array + for loop magic here?
					(*
					set randompara to paragraph randomnumber of lyric & paragraph randomnumber2 of lyric & paragraph randomnumber3 of lyric & paragraph randomnumber4 of lyric & paragraph randomnumber5 of lyric as list
					repeat with i from 1 to ((length of randompara) + 5)
						if (length of item i of randompara) is equal to 0 then
							set item i of randompara to item (i + 1)
							set item (i + 1) of randompara to item (i + 2)
							set item (i + 2) of randompara to item (i + 3)
							set item (i + 3) of randompara to item (i + 4)
							set item (i + 4) of randompara to item (i + 5)
							set item (i + 5) of randompara to item (i + 6)
						end if
					end repeat
					*)
					
					--see if you can fix this to have no blank lines!
					
					set lyriclength to count characters of (randomline & randomline2 & randomline3 & randomline4 & randomline5)
					set lyric to randomline & return & randomline2 & return & randomline3 & return & randomline4 & return & randomline5 & suffix
					--set lyric to randompara
					set _chars to characters of lyric as list
					repeat with i from 1 to (length of _chars)
						if (get item i of _chars) is "'" then
							set item i of _chars to "\\'"
						end if
					end repeat
					if removeendcomma is true and ((get item (length of _chars) of _chars) is ",") then
						set item (length of _chars) of _chars to ""
					end if
					--	end repeat
					--store lyric to linecache.dat
					do shell script "/bin/echo " & tuid & " > ~/Library/Application\\ Support/Adium\\ 2.0/Scripts/ParaLyrical.AdiumScripts/Contents/Resources/cache.dat"
					do shell script "/bin/echo " & (items of _chars as string) & " > ~/Library/Application\\ Support/Adium\\ 2.0/Scripts/ParaLyrical.AdiumScripts/Contents/Resources/linecache.dat"
					--send it over to adium
					final is equal to items of _chars as string
					return final
				else if tuid as integer is equal to oldtuid as integer then
					--get current song lyric from linecache.dat
					set existingLyric to do shell script "/bin/cat ~/Library/Application\\ Support/Adium\\ 2.0/Scripts/ParaLyrical.AdiumScripts/Contents/Resources/linecache.dat"
					set _chars to characters of existingLyric as list
					--if removeendcomma is true and ((get item (length of _chars) of _chars) is ",") then
					--	set item (length of _chars) of _chars to ""
					--end if
					return items of _chars as string
				end if
			else
				return quiet
			end if
		end tell
	else
		return quiet
	end if
end substitute
 

Shadowhawk109

macrumors newbie
Original poster
Jun 10, 2010
4
0
Sammich, that's fine; I kinda just posted to see if anyone else understands wtf's goin' on.

Note that there's a LOT of commented out code; rather than just deleting stuff, I commented it out in case I had a brainspark that caused me to continue on the previous path.
 

rev316

macrumors regular
Nov 7, 2004
156
0
Unfortunately, I can't run your script (external dependancies).

However, I suggest you comb through any iteration blocks where the interpreter is allocating tons of memory. Common mistakes.
 

Shadowhawk109

macrumors newbie
Original poster
Jun 10, 2010
4
0
Shouldn't have any external dependencies (other than, say, iTunes), so that's weird...

I'm a noob at this, so how do you propose I do that...
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.