#!/usr/bin/python # # USAGE: $0 frequency minutes outputfile # # $Id: fmcapture,v 1.2 2005/08/25 06:07:52 jake Exp jake $ # this script is for Linux # FreeBSD 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/audio1' # need full path to sox for execv() later CAPTURE_CMD = '/usr/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 linux/videodev.h VIDIOCGTUNER = 0xc0347604 VIDIOCGAUDIO = 0x80287610 VIDIOCSAUDIO = 0x40287611 VIDIOCSFREQ = 0x4004760f VIDEO_AUDIO_MUTE = 1 VIDEO_TUNER_LOW = 8 # open the radio device radio_fd = os.open('/dev/radio', os.O_RDONLY) # detect kilohertz or megahertz # MENTAL VIOLENCE: negate ioctl to workaround overflow bug in Python 2.4 video_tuner = fcntl.ioctl(radio_fd, ~int(~VIDIOCGTUNER & 0xFFFFFFFF), struct.pack("52x")) tuner, name, rangelow, rangehigh, vtflags, mode, signal = struct.unpack("i 32s I I I H H", video_tuner) if vtflags & VIDEO_TUNER_LOW: multiplier = 16000 else: multiplier = 16 # tune frequency fcntl.ioctl(radio_fd, VIDIOCSFREQ, struct.pack("I", int(frequency * multiplier))) # unmute # MENTAL VIOLENCE: negate ioctl to workaround overflow bug in Python 2.4 video_audio = fcntl.ioctl(radio_fd, ~int(~VIDIOCGAUDIO & 0xFFFFFFFF), struct.pack("40x")) audio, volume, bass, treble, vaflags, vaname, vamode, balance, step = struct.unpack("i H H H 2x I 16s H H H 2x", video_audio) vaflags = vaflags & ~VIDEO_AUDIO_MUTE video_audio = struct.pack("i H H H 2x I 16x H H H 2x", 0, volume, bass, treble, vaflags, vamode, balance, step) fcntl.ioctl(radio_fd, VIDIOCSAUDIO, video_audio) # # 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 vaflags = vaflags | VIDEO_AUDIO_MUTE video_audio = struct.pack("i H H H 2x I 16x H H H 2x", 0, volume, bass, treble, vaflags, vamode, balance, step) fcntl.ioctl(radio_fd, VIDIOCSAUDIO, video_audio) # 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' })