#!/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 -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' })