#!/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 Hauppauge Win TV Go FM on FreeBSD 6.2 # 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 dev/bktr/ioctl_bt848.h BT848_SAUDIO = 0x8004782E AUDIO_INTERN = 0x2 AUDIO_EXTERN = 0x1 RADIO_SETFREQ = 0x8004783B # open the radio device radio_fd = os.open('/dev/tuner', os.O_RDWR) # tune frequency # MENTAL VIOLENCE: negate ioctl to workaround overflow bug in Python 2.4 fcntl.ioctl(radio_fd, ~int(~BT848_SAUDIO & 0xFFFFFFFF), struct.pack("I", AUDIO_INTERN)) fcntl.ioctl(radio_fd, ~int(~RADIO_SETFREQ & 0xFFFFFFFF), struct.pack("I", int(frequency * 100))) # (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(~BT848_SAUDIO & 0xFFFFFFFF), struct.pack("I", AUDIO_EXTERN)) # 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' })