#!/usr/local/bin/python
#
# USAGE: $0 frequency minutes outputfile
#
# $Id: fmcapture,v 1.1 2005/08/23 20:45:37 jake Exp jake $
# this script is for D-Link DSB-R100 on FreeBSD 5.4
# Linux counterpart available at http://angerman.net

__author__ = "Gary Burd"
__copyright__ = "Copyright 2003, Gary Burd"
__license__ = "GPL"
__version__ = "0.2"

import struct
import os
import fcntl
import sys
import time
import signal
from signal import SIGINT

# where line-in resides
DEV_AUDIO = '/dev/audio'

# need full path to sox for execv() later
CAPTURE_CMD = '/usr/local/bin/sox -c2 -r32000 -tossdsp %s -t wav -r 44100 -c 2 -' % DEV_AUDIO
#CAPTURE_CMD = '/usr/local/bin/sox -c2 -w -r32000 -tossdsp %s -t wav -r 44100 -w -c 2 -' % DEV_AUDIO
#CAPTURE_CMD = '/usr/bin/sox -t ossdsp /dev/dsp -t .wav -r 44100 -c 2 -'
#ENCODE_CMD = '/usr/local/bin/lame -S --quiet --silent --lowpass 15000 - -'

#
# Get arguments.
#

try:
    frequency = float(sys.argv[1])
    minutes = int(sys.argv[2]) * 60
    path = sys.argv[3]
except:
    print '''Usage: %s frequency minutes output-path''' % sys.argv[0]
    sys.exit(1)

# Path can contain time.strftime inserts. 
# Example: /mp3s/cartalk/%Y-%m-%d

path = time.strftime(path)

# 
# Tune the radio
#

# constants from sys/dev/usb/dsbr100io.h
FM_SET_FREQ =  0xC00455C8
FM_STOP     = 0xC00455CB

# open the radio device
radio_fd = os.open('/dev/ufm0', os.O_RDWR)

# tune frequency
# MENTAL VIOLENCE: negate ioctl to workaround overflow bug in Python 2.4
fcntl.ioctl(radio_fd, ~int(~FM_SET_FREQ & 0xFFFFFFFF), struct.pack("I", int(frequency * 1000000)))

# (no need to unmute in bsd)

#
# Capture the uncompressed sound
#

uncompressed_file = open(path, 'wb');

try:
    pid = os.fork()
    if pid == 0:
        os.dup2(uncompressed_file.fileno(), 1)
        uncompressed_file.close()
        args = CAPTURE_CMD.split()
        os.execv(args[0], args)

    time.sleep(minutes)

finally:
    os.kill(pid, SIGINT)
    os.wait()

    # mute
    # MENTAL VIOLENCE: negate ioctl to workaround overflow bug in Python 2.4
    fcntl.ioctl(radio_fd, ~int(~FM_STOP & 0xFFFFFFFF), struct.pack("s", "foo"))
    # close
    os.close(radio_fd)  

#
# Compress the temporay file.
#
#
#uncompressed_file.seek(0)
#compressed_file = open(path, 'wb')
#
#os.dup2(uncompressed_file.fileno(), 0)
#os.dup2(compressed_file.fileno(), 1)
#
#uncompressed_file.close()
#compressed_file.close()
#
#os.nice(10)
#
# Set TERM environment variable to keep lame quiet.
#
#args = ENCODE_CMD.split()
#os.execve(args[0], args, { 'TERM': 'dumb' })
