#! /usr/bin/env python # -*- coding: utf-8 -*- import time import cgi import os import sys import datetime import syslog try: from config import BASE_DIR, PATH_LAYOUT, FILENAME_LAYOUT except ImportError: BASE_DIR = '/home/alsa-record/' PATH_LAYOUT = '%Y/%m-%b/%d-%a/' FILENAME_LAYOUT = '%Hh%M' if isinstance(BASE_DIR, basestring): BASE_DIR = [BASE_DIR] for i, dirname in enumerate(BASE_DIR): if not dirname.endswith('/'): BASE_DIR[i] = dirname + '/' syslog.openlog('pigebox') cgi_params = cgi.parse() if os.environ.get('PATH_INFO'): # filename has to be of date-start-end.extension # - date must be %Y%m%d # - start and end must be one of %Hh%Mm%S.%f, %Hh%Mm%S, %Hh%Mm, %Hh%M # - extension must be one of wav, ogg, flac # # ex: 20160515-13h45-14h00m05.flac filename = os.path.basename(os.environ.get('PATH_INFO')) basename, ext = filename.rsplit('.', 1) date_str, start_str, end_str = basename.split('-') date = datetime.datetime.strptime(date_str, '%Y%m%d') start_time = None end_time = None for time_format in ('%Hh%Mm%S.%f', '%Hh%Mm%S', '%Hh%Mm', '%Hh%M'): if start_time is None: try: start_time = datetime.datetime.strptime(start_str, time_format) except ValueError: pass if end_time is None: try: end_time = datetime.datetime.strptime(end_str, time_format) except ValueError: pass start = datetime.datetime(date.year, date.month, date.day, start_time.hour, start_time.minute, start_time.second, start_time.microsecond) end = datetime.datetime(date.year, date.month, date.day, end_time.hour, end_time.minute, end_time.second, end_time.microsecond) elif cgi_params: start = datetime.datetime.strptime('%s %s:%s' % ( cgi_params.get('date')[0], cgi_params.get('start_hour')[0], cgi_params.get('start_min')[0]), '%d/%m/%Y %H:%M') end = datetime.datetime.strptime('%s %s:%s' % ( cgi_params.get('date')[0], cgi_params.get('end_hour')[0], cgi_params.get('end_min')[0]), '%d/%m/%Y %H:%M') if cgi_params.get('wav'): ext = 'wav' else: ext = 'ogg' filename = '%s-%s.%s' % ( start.strftime('%Y-%m-%d-%Hh%M'), end.strftime('%Hh%M'), ext) else: print 'Location: .' print '' print 'Hop' sys.exit(0) if end < start: end = end + datetime.timedelta(1) floor_start = start if floor_start.second or floor_start.microsecond: floor_start = floor_start.replace(second=0, microsecond=0) floor_start = floor_start.replace(minute=floor_start.minute/15*15) ceil_end = end if ceil_end.second or ceil_end.microsecond: ceil_end = ceil_end.replace(minute=ceil_end.minute+1, second=0, microsecond=0) if ceil_end.minute%15: if ceil_end.minute / 15 == 3: ceil_end = ceil_end.replace(minute=0) ceil_end += datetime.timedelta(seconds=3600) else: ceil_end = ceil_end.replace(minute=(1+(ceil_end.minute/15))*15) def get_filenames(base_dir): path = os.path.join(base_dir, start.strftime(PATH_LAYOUT)) if not path: filenames = [x for x in os.listdir('.')] else: filenames = [os.path.join(path, x) for x in os.listdir(path)] if end.hour < start.hour: path = os.path.join(base_dir, end.strftime(PATH_LAYOUT)) if os.path.exists(path): filenames.extend([os.path.join(path, x) for x in os.listdir(path)]) filenames = [x for x in filenames if x[len(base_dir):] >= floor_start.strftime(PATH_LAYOUT + FILENAME_LAYOUT) and x[len(base_dir):] < ceil_end.strftime(PATH_LAYOUT + FILENAME_LAYOUT)] return filenames while True: filenames = [] for base_dir in BASE_DIR: filenames.extend(get_filenames(base_dir)) filenames.sort() without_extension = [os.path.splitext(x)[0] for x in filenames] for f in without_extension: if without_extension.count(f) > 1: # currently encoding, wait a moment and try again print 'X-Currently-Encoding: please wait' time.sleep(5) break else: break syslog.syslog(syslog.LOG_INFO, 'extraction (%s to %s)' % ( start.strftime('%Y-%m-%d %Hh%M'), end.strftime('%Hh%M'))) if ext == 'wav': print 'Content-Type: audio/x-wav' else: print 'Content-Type: audio/ogg' print 'Content-Disposition: attachment; filename=%s\n' % filename sys.stdout.flush() if ext == 'ogg': command = ['sox'] + filenames + ['-t', 'ogg', '-C', '6', '-'] elif ext == 'flac': command = ['sox'] + filenames + ['-t', 'flac', '-'] else: command = ['sox'] + filenames + ['-t', 'wav', '-'] # trim command.append('trim') command.append('=%s.%06d' % ((start - floor_start).seconds, (start - floor_start).microseconds)) command.append('=%s.%06d' % ((end - floor_start).seconds, (end - floor_start).microseconds)) if cgi_params.get('fade'): # fade duration, ex: 0.2 command.append('fade') command.append(cgi_params.get('fade')[0]) command.append('0') # apply fade to both start and end if cgi_params.get('norm'): # normalize command.append('gain') command.append('-n') command.append(cgi_params.get('norm')[0]) if '--test' in sys.argv: print ' '.join(command) else: os.system(' '.join(command))