#!/usr/bin/env python
"""
    Usage: ./watch_itunes.py [-u username] [-n interval] [-c columns] [-v] [-h]

    Uses ps / grep / egrep / awk and lsof to determine what songs iTunes is
    playing, both locally and remotely.  It can't tell which songs are being
    played by what hosts, but it can tell which remote hosts are actually
    playing your music (versus just being connected).

    Code Copyright (C) 2006, Christopher S. Swingley <cswingle@gmail.com>
    and Licensed under the terms of the GNU General Public License v2.  You
    can view the license at http://www.gnu.org/

    Contact the author at <cswingle@gmail.com> for corrections, comments,
    suggestions, etc.

    README: You may want to change the default 'username' on line 66 and the
    default 'columns' on line 61 in case it can't read these from the
    environment

"""
import re
import sys
import os
import time
import getopt

def usage():
    print "Usage: ./watch_itunes.py [-u username] [-n interval] [-c columns] [-v] [-h]"

try:
    opts, args = getopt.getopt(sys.argv[1:], "u:n:c:vh", ["username=", "interval=", "columns=", "verbose", "help"])
except getopt.GetoptError:
   usage()
   sys.exit(2) 

username = ""
debug = False
interval = 15
columns = 0
for o, a in opts:
    if o in ('-v', '--verbose'):
        debug = True
    if o in ('-u', '--username'):
        username = a
    if o in ('-n', '--interval'):
        interval = int(a)
    if o in ('-c', '--columns'):
        columns = int(a)
    if o in ('-h', '--help'):
        usage()
        sys.exit(0) 

# Columns and username detector (depends on 'COLUMNS' and 'USER' 
# environment variables)
env = os.environ
if not columns:
    if env.has_key('COLUMNS'):
        columns = int(env['COLUMNS'])
    else:
        columns = 80
if not username:
    if env.has_key('USER'):
        username = env['USER']
    else:
        username = "cswingle"

col_len = int((columns - 2) / 3)
if debug:
    print "Column length = %d" % col_len

daap_ip_re = re.compile('TCP [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:daap->([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)')
song_re = re.compile('/Users/%s/Music/iTunes/iTunes Music/(.*)' % username)

pid_command = "ps -axo 'pid command' | grep -v grep | grep 'iTunes ' | awk '{print $1}'"

if debug:
    print "Running: %s" % pid_command
(pidin, pidout) = os.popen4(pid_command)
pidlines = pidout.readlines()
pidin.close()
pidout.close()

if len(pidlines):
    pid = pidlines[0].strip()
else:
    print "iTunes does not appear to be running."
    sys.exit(1)

if debug:
    print "iTunes process ID = %s" % pid

while True:
    timestring = time.asctime(time.localtime())
    
    print timestring

    lsof_command = "lsof -p %s -n | egrep '(iTunes Music|ESTABLISHED)'" % pid

    if debug:
        print "Running: %s" % lsof_command
    (lsofin, lsofout) = os.popen4(lsof_command)
    lsoflines = lsofout.readlines()
    lsofin.close()
    lsofout.close()

    connection_count = 0
    play_count = 0
    ip_hash = {}
    song_hash = {}
    for lsofline in lsoflines:
        lsofline = lsofline.strip()
        if debug:
            print lsofline
        if daap_ip_re.search(lsofline):
            remote_ip = daap_ip_re.search(lsofline).group(1)
            if ip_hash.has_key(remote_ip):
                ip_hash[remote_ip] += 1
            else:
                ip_hash[remote_ip] = 1
        elif song_re.search(lsofline):
            song = song_re.search(lsofline).group(1)
            if song_hash.has_key(song):
                song_hash[song] += 1
            else:
                song_hash[song] = 1

    for ip in ip_hash.keys():
        if ip_hash[ip] > 1:
            print "%s is listening to music" % ip
        else:
            print "%s is connected but not listening to music" % ip
        connection_count += 1

    for song in song_hash.keys():
        (artist, album, title) = song.split('/')
        format_string = "%%-%ds %%-%ds %%-%ds" % (col_len, col_len, col_len)
        print format_string % (artist[:col_len], album[:col_len], title[:col_len])
        play_count += 1
   
    if not play_count:
        print "Nothing playing"

    time.sleep(interval)

