Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 129 lines (111 sloc) 4.14 KB
#!/usr/bin/env python
# tweet: play a bird call matching the argument string.
# Copyright 2003 by Akkana Peck.
# You may use, distribute or modify this program under the terms of the GPL.
# This program assumes that you have bird calls installed in files
# named after each bird, where spaces may be replaced by underscores:
# e.g. Broad-Billed_Hummingbird.wav or Song_Sparrow.ogg.
# Edit calldir to point to the place where these are stored.
# It also assumes that you have a program called "play" which
# can play whatever format you're using. If you use a different
# program, edit the os.system line in the play function appropriately.
# This program does NOT come with any bird calls included.
# I recommend the Stokes Field Guide to Bird Songs, available
# from booksellers. Use your favorite CD ripper to rip the CDs
# in and store in whatever format you like (I use ogg).
import sys, string, os, types
calldir = os.environ["HOME"] + "/Sounds/Birds"
calldirlen = len(calldir)
def prettify(filnam) :
parts = os.path.split(filnam)
birdname = parts[1].replace("_", " ")
if parts[0].startswith(calldir) :
return '%s (%s)' % (birdname, parts[0][calldirlen+1:])
else :
print parts[0], "doesn't start with", calldir
return birdname
def getMatchingFiles(pats) :
'''Find the list of birdcall files matching the list of terms.'''
matches = []
birds = map(string.lower, pats)
for root, dirs, files in os.walk(calldir) :
for f in files :
# Omit .aup files -- audacity sometimes leaves them
# but play can't play them.
callfile = string.lower(f)
if callfile.endswith('.aup') :
continue
for bird in birds:
# print "Looking for", bird, "in", callfile
if (callfile.find(bird) < 0) :
break
else: # only if we haven't broken out of the for loop
matches.append(os.path.join(root,f))
#print "Appended: matches is now", matches
#print "Returning", matches
return matches
def narrow(pat, lis):
'''We already have a list, but we need to narrow it by pattern.'''
def play(fil) :
try :
fil = str(fil)
except :
return
os.system("play " + fil)
def playList(lis) :
if type(lis) != types.ListType :
return
for b in lis :
#print "(", b, ")"
play(b)
def tweet(args):
matches = getMatchingFiles(args)
# If we have more than one, prompt the user:
while len(matches) > 1 :
# Prettyprint the list of matches so the user can choose.
for m in range(0, len(matches)) :
dot = string.rfind(matches[m], ".")
if dot < 0 :
continue
print "%d. %s" % (m+1, prettify(matches[m][0:dot]))
print "%d. %s" % (len(matches)+1, "all")
try :
ans = raw_input("Which one? ")
except KeyboardInterrupt, e :
print
return
if (ans == "q") :
return
if (ans == "all") :
playList(matches)
return
try :
answer = int(ans)
if answer == len(matches)+1 :
playList(matches)
return
if answer <= 0 or answer > len(matches) :
return
play(matches[answer-1])
return
except ValueError, e:
# User typed something other than an int.
# Try to match it in our current list of matches.
newmatches = []
pats = ans.lower().split()
for m in matches:
match = os.path.basename(m).lower()
for pat in pats:
if match.find(pat) < 0:
# This previous match doesn't match one of the
# new patterns. So throw it out.
break
else: # match matched all the new patterns too. Keep it.
newmatches.append(m)
matches = newmatches
if len(matches) <= 0 :
return
play(matches[0])
return
if __name__ == '__main__':
tweet(sys.argv[1:])
Something went wrong with that request. Please try again.