--- /dev/null
+table.jCalendar {
+ background: #b4cdea;
+ border-collapse: separate;
+ border-spacing: 2px;
+}
+table.jCalendar th {
+ background: #ffb267;
+ color: #fff;
+ font-weight: bold;
+ padding: 3px 5px;
+}
+table.jCalendar td {
+ background: #eee;
+ color: #000;
+ padding: 3px 5px;
+ text-align: center;
+}
+table.jCalendar td.other-month {
+ background: #ddd;
+ color: #aaa;
+}
+table.jCalendar td.today {
+ background: #666;
+ color: #fff;
+}
+table.jCalendar td.selected {
+ background: #f66;
+ color: #fff;
+}
+table.jCalendar td.selected:hover {
+ background: #f33;
+ color: #fff;
+}
+table.jCalendar td:hover, table.jCalendar td.dp-hover {
+ background: #fff;
+ color: #000;
+}
+table.jCalendar td.disabled, table.jCalendar td.disabled:hover {
+ background: #bbb;
+ color: #888;
+}
+
+/* For the popup */
+
+div.dp-popup {
+ position: relative;
+ background: #5183c2;
+ font-size: 80%;
+ padding: 2px;
+ line-height: 1.2em;
+}
+div#dp-popup {
+ position: absolute;
+ z-index: 199;
+}
+div.dp-popup h2 {
+ font-size: 12px;
+ text-align: center;
+ margin: 2px 0;
+ padding: 0;
+}
+a#dp-close {
+ font-size: 11px;
+ padding: 4px 0;
+ text-align: center;
+ display: block;
+}
+a#dp-close:hover {
+ text-decoration: underline;
+}
+div.dp-popup a {
+ color: #000;
+ text-decoration: none;
+ padding: 3px 2px 0;
+}
+div.dp-popup div.dp-nav-prev {
+ position: absolute;
+ top: 2px;
+ left: 4px;
+ width: 100px;
+}
+div.dp-popup div.dp-nav-prev a {
+ float: left;
+}
+/* Opera needs the rules to be this specific otherwise it doesn't change the cursor back to pointer after you have disabled and re-enabled a link */
+div.dp-popup div.dp-nav-prev a, div.dp-popup div.dp-nav-next a {
+ cursor: pointer;
+}
+div.dp-popup div.dp-nav-prev a.disabled, div.dp-popup div.dp-nav-next a.disabled {
+ cursor: default;
+}
+div.dp-popup div.dp-nav-next {
+ position: absolute;
+ top: 2px;
+ right: 4px;
+ width: 100px;
+}
+div.dp-popup div.dp-nav-next a {
+ float: right;
+}
+div.dp-popup a.disabled {
+ cursor: default;
+ color: #aaa;
+}
+div.dp-popup td {
+ cursor: pointer;
+}
+div.dp-popup td.disabled {
+ cursor: default;
+}
+
+++ /dev/null
-#! /usr/bin/env python
-
-import os
-import time
-import sys
-import extract
-from datetime import datetime, timedelta
-from optparse import OptionParser
-
-JOBS_DIR = '/tmp/jobs'
-
-class Job:
- def __init__(self, job_id):
- self.job_id = job_id
- self.filename = os.path.join(JOBS_DIR, self.job_id)
- line = file(self.filename).readline()
- self.cmd = line.split(':', 1)[0].strip()
- self.timestamp = os.stat(self.filename)[-3]
-
- def add_info(self, info):
- first_line = file(self.filename).readline()
- if not first_line.endswith('\n'):
- first_line += '\n'
- open(self.filename, 'w').write(first_line + info + '\n')
-
- def start(self):
- if os.fork():
- return
- firstline = file(self.filename).readline()
- open(self.filename, 'w').write('running\nEn cours de traitement ...\n')
- first_word, date, start, end = firstline.strip().split()
-
- year, month, day = date.split('-')
- start_hour, start_minutes = [int(x) for x in start.split(':')]
- end_hour, end_minutes = [int(x) for x in end.split(':')]
- output_filename = 'extrait-%s%s%s-%02d%02d-%02d%02d.wav' % (
- year, month, day, start_hour, start_minutes, end_hour, end_minutes)
- start_time = datetime(int(year), int(month), int(day), int(start_hour), int(start_minutes))
- end_time = datetime(int(year), int(month), int(day), int(end_hour), int(end_minutes))
- if end_time < start_time:
- end_time += timedelta(days=1)
- extract.extract(start_time, end_time, output_filename)
- open(self.filename, 'w').write('done:results/%s\n' % output_filename)
- sys.exit(0)
-
- def cleanup(self):
- if os.stat(self.filename)[-2]+300 > time.time():
- try:
- os.unlink(self.filename)
- except OSError:
- pass
-
- def __repr__(self):
- return '<Job id=%s>' % self.job_id
-
-
-if __name__ == '__main__':
- parser = OptionParser()
- parser.add_option('--source', dest='source', metavar='SOURCE')
- options, args = parser.parse_args()
- if options.source:
- if options.source.startswith('http://'):
- extract.source = extract.HttpSource(options.source)
- else:
- extract.source = extract.LocalSource(options.source)
-
- if not os.path.exists(JOBS_DIR):
- os.makedirs(JOBS_DIR)
- jobs = [Job(x) for x in os.listdir(JOBS_DIR)]
- jobs.sort(lambda x, y: cmp(x.timestamp, y.timestamp))
-
- running_jobs = [x for x in jobs if x.cmd == 'running']
-
- waiting = 0
- for job in jobs:
- if job.cmd == 'start':
- if running_jobs:
- job.add_info('Encore %s jobs ...' % (len(running_jobs)+waiting))
- waiting += 1
- else:
- running_jobs.append(job)
- job.start()
- elif job.cmd == 'done':
- job.cleanup()
--- /dev/null
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import time
+import cgi
+import os
+import sys
+import datetime
+import syslog
+
+syslog.openlog('pigebox')
+
+d = cgi.parse()
+
+if not d:
+ print 'Location: .'
+ print ''
+ print 'Hop'
+ sys.exit(0)
+
+end = '%s:%s' % (d.get('end_hour')[0], d.get('end_min')[0])
+
+start = datetime.datetime.strptime('%s %s:%s' % (
+ d.get('date')[0], d.get('start_hour')[0], d.get('start_min')[0]),
+ '%d/%m/%Y %H:%M')
+end = datetime.datetime.strptime('%s %s:%s' % (
+ d.get('date')[0], d.get('end_hour')[0], d.get('end_min')[0]),
+ '%d/%m/%Y %H:%M')
+if end < start:
+ end = end + datetime.timedelta(1)
+
+os.chdir('/home/alsa-record/')
+
+def get_filenames():
+ path = start.strftime('%Y/%m-%b/%d-%a/')
+ filenames = [os.path.join(path, x) for x in os.listdir(path)]
+ if end < start:
+ path = end.strftime('%Y/%m-%b/%d-%a/')
+ if os.path.exists(path):
+ filenames.extend([os.path.join(path, x) for x in os.listdir(path)])
+ filenames.sort()
+
+ filenames = [x for x in filenames if
+ x >= start.strftime('%Y/%m-%b/%d-%a/%Hh%M') and
+ x < end.strftime('%Y/%m-%b/%d-%a/%Hh%M')]
+ return filenames
+
+while True:
+ filenames = get_filenames()
+ 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 d.get('wav'):
+ ext = 'wav'
+ print 'Content-Type: audio/x-wav'
+else:
+ ext = 'ogg'
+ print 'Content-Type: audio/ogg'
+
+print 'Content-Disposition: attachment; filename=%s.%s\n' % \
+ (start.strftime('%Y-%m-%d-%Hh%M') + end.strftime('-%Hh%M'), ext)
+
+sys.stdout.flush()
+
+if ext == 'ogg':
+ command = ['sox'] + filenames + ['-t', 'ogg', '-C', '6', '-']
+else:
+ command = ['sox'] + filenames + ['-t', 'wav', '-']
+os.system(' '.join(command))
+
+++ /dev/null
-#! /usr/bin/env python
-
-import sys
-from datetime import datetime, timedelta
-import os
-import urllib2
-import md5
-import random
-from optparse import OptionParser
-import shutil
-
-def print_cmd(x):
- print x
-#os.system = print_cmd
-
-tmpdir = os.environ.get('TMPDIR', '/tmp/')
-
-
-class Source:
- def get_files(self, start, end):
- filenames = []
- t = start
- while t <= end:
- filenames.append(self.get_file(t))
- t = t + timedelta(seconds=15*60)
- return filenames
-
- def get_file(self, timestamp):
- formatted = timestamp.strftime('record-%Y-%m-%d-%a-%H-%M')
- t = self.get_current_file(formatted)
- if t:
- return t
- return self.get_archive_file(formatted)
-
-class LocalSource(Source):
- base_directory = '/var/www/current/record/'
-
- def __init__(self, base_dir):
- self.base_directory = base_dir
-
- def get_current_file(self, filename):
- fullpath = os.path.join(self.base_directory, 'current', filename + '.wav')
- if os.path.exists(fullpath):
- return fullpath
-
- def get_archive_file(self, filename):
- fullpath = os.path.join(self.base_directory, 'archives', filename + '.ogg')
- localwav = os.path.join(tmpdir, filename.replace('.ogg', '.wav'))
- os.system('oggdec %s --output %s' % (fullpath, localwav))
- return localwav
-
-class HttpSource(Source):
-
- def __init__(self, base_url):
- self.base_url = base_url
-
- def get_http_file(self, filename):
- dstfile = os.path.join(tmpdir, os.path.basename(filename))
- if os.path.exists(dstfile):
- return dstfile
- url = self.base_url + filename
- try:
- fd = urllib2.urlopen(url)
- except urllib2.HTTPError:
- return
- extension = filename.split('.')[-1]
- tmpfile = os.path.join(tmpdir, md5.md5(str(random.random())).hexdigest()) + '.' + extension
- dst = open(tmpfile, 'w')
- BLOCK_SIZE = 10*1000*1000
- while True:
- s = fd.read(BLOCK_SIZE)
- dst.write(s)
- if len(s) != BLOCK_SIZE:
- break
- dst.close()
- os.rename(tmpfile, dstfile)
- return dstfile
-
-
- def get_current_file(self, filename):
- return self.get_http_file('current/' + filename + '.wav')
-
- def get_archive_file(self, filename):
- dstfile = self.get_http_file('archives/' + filename + '.ogg')
- localwav = os.path.join(tmpdir, dstfile.replace('.ogg', '.wav'))
- os.system('oggdec %s --output %s' % (dstfile, localwav))
- return localwav
-
-
-def get_lower(date):
- lower = date.replace(minute = (date.minute - (date.minute % 15)))
- return lower
-
-def get_upper(date):
- upper = get_lower(date)
- return upper + timedelta(seconds=15*60)
-
-def extract(start, end, output):
- lower = get_lower(start)
- upper = get_lower(end - timedelta(seconds=60))
-
- filenames = source.get_files(lower, upper)
- if start.minute % 15 != 0:
- delay = (start.minute % 15) * 60
- tmpfile = os.path.join(tmpdir, md5.md5(str(random.random())).hexdigest()) + '.wav'
- os.system('sox %s %s trim %d %d' % (
- filenames[0], output, delay, 15*60-delay))
- filenames[0] = tmpfile
-
- if end.minute % 15 != 0:
- delay = (end.minute % 15) * 60
- tmpfile = os.path.join(tmpdir, md5.md5(str(random.random())).hexdigest()) + '.wav'
- os.system('sox %s %s trim 0 %d' % (filenames[-1], tmpfile, delay))
- filenames[-1] = tmpfile
-
- tmpfile = os.path.join(tmpdir, md5.md5(str(random.random())).hexdigest()) + '.wav'
- if len(filenames) > 1:
- os.system('sox %s %s' % (' '.join(filenames), tmpfile))
- shutil.move(tmpfile, output)
- else:
- shutil.copy(filenames[0], output)
-
-if __name__ == '__main__':
- global source
- source = HttpSource('http://nas.studio.priv/current/record/')
-
- parser = OptionParser()
- parser.add_option('--start', dest='start', metavar='TIME')
- parser.add_option('--stop', dest='stop', metavar='TIME')
- parser.add_option('--output', dest='output', metavar='FILENAME')
- options, args = parser.parse_args()
- if not (options.start and options.stop and options.output):
- parser.print_help()
- sys.exit(1)
- sys.exit(extract(
- datetime.strptime(options.start, '%Y-%m-%d %H:%M'),
- datetime.strptime(options.stop, '%Y-%m-%d %H:%M'),
- options.output))
+++ /dev/null
-#! /usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import cgi
-import os
-import sys
-import time
-import stat
-import md5
-import random
-
-from dojobs import JOBS_DIR
-
-d = cgi.parse_qs(os.environ.get('QUERY_STRING', ''))
-
-if not d:
- print 'Content-type: text/html\n'
- print open('static.html').read()
- sys.exit(0)
-
-
-print 'Content-type: text/plain\n'
-
-if d.get('cmd') == ['new']:
- try:
- date_val = d.get('date_val')[0]
- start_val = d.get('start_val')[0]
- end_val = d.get('end_val')[0]
- assert date_val
- assert start_val
- assert end_val
-
- start_time = '%s %s' % (date_val, start_val)
- end_time = '%s %s' % (date_val, end_val)
- try:
- time.strptime(start_time, '%d/%m/%Y %H:%M')
- except ValueError:
- time.strptime(start_time, '%Y-%m-%d %H:%M')
- try:
- time.strptime(end_time, '%d/%m/%Y %H:%M')
- except ValueError:
- time.strptime(end_time, '%Y-%m-%d %H:%M')
-
- job_number = md5.md5(str(random.random())).hexdigest()
- if not os.path.exists(JOBS_DIR):
- os.makedirs(JOBS_DIR)
- job_filename = os.path.join(JOBS_DIR, job_number)
- file(job_filename, 'w').write(
- 'start: %s %s %s' % (date_val, start_val, end_val))
- os.chmod(job_filename, 0666)
- print 'ok:' + job_number
-
- except IOError:
- print 'valeur manquante'
- sys.exit(0)
-
-if d.get('cmd') == ['status']:
- job_number = d.get('job')[0]
- job_filename = os.path.join(JOBS_DIR, job_number)
- if not os.path.exists(job_filename):
- print 'error (missing job definition)'
- else:
- fd = open(job_filename)
- cmd = fd.readline()
- secondline = fd.readline()
- first_word = cmd.split(':', 1)[0]
- if secondline:
- print secondline
- elif first_word == 'start':
- print 'commande enregistrée, traitement dans une petite minute ...'
- else:
- print cmd
-
-if d.get('cmd') == ['list']:
- try:
- filenames = [os.path.join(os.getcwd(), x) for x in os.listdir(os.getcwd() + '/results/') if \
- x.endswith('.ogg') or x.endswith('.wav')]
- except OSError:
- filenames = []
- def cmp_stat(x, y):
- return cmp(os.stat(x)[stat.ST_CTIME], os.stat(y)[stat.ST_CTIME])
- filenames.sort(cmp_stat)
- filenames.reverse()
-
- for x in filenames:
- print os.path.basename(x)
-
--- /dev/null
+<html>
+<head>
+
+<title>PigeBox</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+<link rel="stylesheet" type="text/css" href="pige.css" />
+<link rel="stylesheet" type="text/css" href="datePicker.css" />
+<script type="text/javascript" src="js/jquery.js"></script>
+<script type="text/javascript" src="js/bgiframe/jquery.bgiframe.min.js"></script>
+<script type="text/javascript" src="js/methods/date.js"></script>
+<script type="text/javascript" src="js/methods/date_fr.js"></script>
+<script type="text/javascript" src="js/datePicker/jquery.datePicker.js"></script>
+<script type="text/javascript" src="js/jquery.simplemodal.js"></script>
+
+</head>
+<body>
+
+<h1>PigeBox</h1>
+
+<form method="post" action="download.cgi">
+
+<p>
+Récupérer un extrait de la pige ...
+</p>
+
+
+<label for="date">Date</label>
+<input name="date" id="date" maxlength="10" type="text" class="date-pick" size="10" />
+
+<label for="start_start">Heure de début</label>
+<select name="start_hour" id="start_hour">
+ <option value="00">00</option> <option value="01">01</option> <option value="02">02</option>
+ <option value="03">03</option> <option value="04">02</option> <option value="05">02</option>
+ <option value="06">06</option> <option value="07">07</option> <option value="08">08</option>
+ <option value="09">09</option> <option value="10">10</option> <option value="11">11</option>
+ <option value="12">12</option> <option value="13">13</option> <option value="14">14</option>
+ <option value="15">15</option> <option value="16">16</option> <option value="17">17</option>
+ <option value="18">18</option> <option value="19">19</option> <option value="20">20</option>
+ <option value="21">21</option> <option value="22">22</option> <option value="23">23</option>
+</select>
+:
+<select name="start_min" id="start_min">
+ <option value="00">00</option>
+ <option value="15">15</option>
+ <option value="30">30</option>
+ <option value="45">45</option>
+</select>
+
+
+<label for="end_hour">Heure de fin</label>
+
+<select name="end_hour" id="end_hour">
+ <option value="00">00</option> <option value="01">01</option> <option value="02">02</option>
+ <option value="03">03</option> <option value="04">02</option> <option value="05">02</option>
+ <option value="06">06</option> <option value="07">07</option> <option value="08">08</option>
+ <option value="09">09</option> <option value="10">10</option> <option value="11">11</option>
+ <option value="12">12</option> <option value="13">13</option> <option value="14">14</option>
+ <option value="15">15</option> <option value="16">16</option> <option value="17">17</option>
+ <option value="18">18</option> <option value="19">19</option> <option value="20">20</option>
+ <option value="21">21</option> <option value="22">22</option> <option value="23">23</option>
+</select>
+:
+<select name="end_min" id="end_min">
+ <option value="00">00</option>
+ <option value="15">15</option>
+ <option value="30">30</option>
+ <option value="45">45</option>
+</select>
+<input type="submit" value="Valider"/>
+
+<input type="checkbox" value="wav" name="wav">.wav</input>
+
+</form>
+
+</body>
+</html>
+
+<script type="text/javascript">
+Date.format = 'dd/mm/yyyy';
+$(function() {
+ var endDate = new Date();
+ var startDate = new Date();
+ startDate.addDays(-92);
+ $('#date').datePicker({
+ startDate: startDate.asString(),
+ endDate: endDate.asString(),
+ }).next().html(
+ '<img src="js/calendar.png" width="16" height="16" />');
+});
+</script>
background: white url(indicator.gif) no-repeat top right;
padding: 1em;
}
+
+a img {
+ border: 0;
+}
+
+++ /dev/null
-<html>
-<head>
-
-<title>PigeBox</title>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-
-<link rel="stylesheet" type="text/css" href="pige.css" />
-<link rel="stylesheet" type="text/css" href="css/datePicker.css" />
-<script type="text/javascript" src="js/jquery.js"></script>
-<script type="text/javascript" src="js/bgiframe/jquery.bgiframe.min.js"></script>
-<script type="text/javascript" src="js/methods/date.js"></script>
-<script type="text/javascript" src="js/methods/date_fr.js"></script>
-<script type="text/javascript" src="js/datePicker/jquery.datePicker.js"></script>
-<script type="text/javascript" src="js/jquery.simplemodal.js"></script>
-
-</head>
-<body>
-
-<h1>PigeBox</h1>
-
-<form method="post">
-
-<p>
-Récupérer un extrait de la pige ...
-</p>
-
-
-<label for="date">Date</label>
-<!--<input name="date" id="date" maxlength="10" type="text" class="date-pick" size="10" />-->
-<select name="date" id="date">
- <option value="2009-07-28">28 juillet</option>
- <option value="2009-07-29">29 juillet</option>
- <option value="2009-07-30" selected="selected">30 juillet</option>
- <option value="2009-07-31">31 juillet</option>
- <option value="2009-08-01">1er août</option>
- <option value="2009-08-02">2 août</option>
-</select>
-
-<label for="start_time">Heure de début</label>
-<input name="start_time" id="start_time" maxlength="5" size="5" type="text" />
-
-<label for="end_time">Heure de fin</label>
-<input name="end_time" id="end_time" maxlength="5" size="5" type="text" />
-
-<button disabled="disabled">Valider</button>
-
-</form>
-
-<div id="status">
-</div>
-
-<ul id="downloads">
-</ul>
-
-</body>
-</html>
-
-<script type="text/javascript">
-Date.format = 'dd/mm/yyyy';
-
-
-function updateDownloads()
-{
- $.get(document.URL, {cmd: 'list'},
- function (data) {
- data = $.trim(data);
- data = data.split('\n');
- s = '';
- for (i=0; i < data.length; i++) {
- if (data[i].length == 0) continue;
- s += '<li><a href="' + data[i] + '">';
- s += data[i].substring(14, 16);
- s += '/';
- s += data[i].substring(12, 14);
- s += '/';
- s += data[i].substring(8, 12);
- s += ' ';
- s += data[i].substring(17, 19);
- s += ':';
- s += data[i].substring(19, 21);
- s += ' -> ';
- s += data[i].substring(22, 24);
- s += ':';
- s += data[i].substring(24, 26);
- s += '</a></li>\n';
- }
- $('#downloads').html(s);
- }
- );
-}
-
-function updateStatus(job_number)
-{
- //console.log('update status');
- $('#status').addClass('throbber');
- $.get(document.URL, { cmd: 'status', job: job_number},
- function (data) {
- $('#status').removeClass('throbber');
- data = $.trim(data);
- if (data == 'available') {
- $('#status').text('');
- return;
- }
- if (data.split(':')[0] == 'done') {
- updateDownloads();
- //console.log(document.URL + data.split(':')[1])
- $.modal.close();
- $('#status').text('').hide();
- document.location.href = document.URL + data.split(':')[1];
- return;
- }
-
- $('#status').text(data);
- window.setTimeout(updateStatus, 2500, job_number);
- }
- );
-}
-
-
-$(function() {
- var endDate = new Date();
- endDate.addDays(-2);
- var startDate = new Date();
- startDate.addDays(-92);
- // XXX: get start and end date from server
- /*
- $('#date').datePicker({
- startDate: startDate.asString(),
- endDate: endDate.asString(),
- }).next().html(
- '<img src="js/calendar.png" width="16" height="16" />');
- */
- $('form').submit(
- function () {
- if ($('#start_time').val().indexOf(':') == -1 ||
- $('#end_time').val().indexOf(':') == -1) {
- $('#status').text('Les heures doivent avoir le format hh:mm');
- return false;
- }
- $('#status').addClass('throbber').text('Envoi ...');
- $.get(document.URL, {
- cmd: 'new',
- date_val: $('#date').val(),
- start_val: $('#start_time').val(),
- end_val: $('#end_time').val() },
- function (data) {
- data = $.trim(data);
- if (data.substring(0, 2) != 'ok') {
- $('#status').removeClass('throbber').text(
- 'Erreur : ' + data);
- } else {
- job_number = data.substring(3, 35);
- $('#status').show().modal();
- updateStatus(job_number);
- }
- }
- );
- //console.log('submit');
- return false;
- }
- );
-
- $('input').change(
- function () {
- if ($('#date').val() != '' &&
- $('#start_time').val() != '' &&
- $('#end_time').val() != '') {
- $('button').attr('disabled', false);
- } else {
- $('button').attr('disabled', true);
- }
- }
- );
- $('#date').trigger('change');
-
- updateDownloads();
-});
-
-</script>