From 20d15232e7d431a8f5fe91aaf8e56b02f629d58d Mon Sep 17 00:00:00 2001 From: yomguy <> Date: Fri, 17 Sep 2010 18:49:30 +0000 Subject: [PATCH] - cleanup various infos - CHANGE conf to get old session parameters (sessions.xml not needed anymore) - cleanup vebview - fix deefuzzer bug when no network - BUG: page reload after starting (even when all processes are starting well) --- INSTALL | 2 + conf/etc/telecaster/telecaster.xml | 309 +++++++++++++++++++++++++++-- install.py | 12 +- station.py | 143 ++++--------- telecaster.py | 18 +- tools/__init__.py | 3 +- tools/tools.py | 34 +++- webview.py | 96 +++------ 8 files changed, 417 insertions(+), 200 deletions(-) diff --git a/INSTALL b/INSTALL index 85f986a..14b2c1d 100644 --- a/INSTALL +++ b/INSTALL @@ -22,6 +22,8 @@ $ sudo aptitude install python python-dev python-xml python-libxml2 python-setup icecast2 apache2 apache2-suexec jackd libjack-dev vorbis-tools procps meterbridge fluxbox \ vnc4server vncviewer swh-plugins jack-rack libshout3 libshout3-dev libmad0-dev libogg-dev g++ +On Debian Squeeze or recent Ubuntu, change libjack-dev to libjack-jackd2-dev + Optional:: $ sudo aptitude install libfaac-dev libmp3lame-dev libflac-dev diff --git a/conf/etc/telecaster/telecaster.xml b/conf/etc/telecaster/telecaster.xml index 2bcd696..c3c1d4e 100644 --- a/conf/etc/telecaster/telecaster.xml +++ b/conf/etc/telecaster/telecaster.xml @@ -3,19 +3,11 @@ Pre-Barreau Pre-Barreau La preparation au Barreau de Paris - http:///telecaster-04.parisson.com + telecaster-04.parisson.com Vocal - - - stream.parisson.com - 8000 - source2parisson - 0 - /etc/telecaster/deefuzzer.xml - - /var/www/rss/ - - + + /etc/telecaster/deefuzzer.xml + true /home/prebarreau/media @@ -31,4 +23,297 @@ jack_rack:out_1 + + + CRFPA + + + Droit_administratif_Corrections + + + Droit_administratif_Cours + + + Droit_des_obligations_Corrections + + + Droit_des_obligations_Cours + + + Droit_commercial_des_affaires_Corrections + + + Droit_commercial_des_affaires_Cours + + + Droit_communautaire_et_europeen_Corrections + + + Droit_communautaire_et_europeen_Cours + + + Droit_de_la_famille_et_des_personnes_Corrections + + + Droit_de_la_famille_et_des_personnes_Cours + + + Droit_du_travail_Corrections + + + Droit_du_travail_Cours + + + Droit_fiscal_Corrections + + + Droit_fiscal_Cours + + + Droit_international_prive_Corrections + + + Droit_international_prive_Cours + + + Droit_patrimonial_Corrections + + + Droit_patrimonial_Cours + + + Droit_public_des_activites_economiques_Corrections + + + Droit_public_des_activites_economiques_Cours + + + Droit_penal_Corrections + + + Droit_penal_Cours + + + Droit_Libertes_publiques_Cours + + + Note_de_synthese_Corrections + + + Procedure_administrative_et_contentieuse_Corrections + + + Procedure_administrative_et_contentieuse_Cours + + + Procedure_civile_Corrections + + + Procedure_civile_Cours + + + Procedures_collectives_et_suretes_Corrections + + + Procedures_collectives_et_suretes_Cours + + + Procedure_penale_Corrections + + + Procedure_penale_Cours + + + TEST + + + + + + + AE + + + Administratif_Cours + + + Adm_Correction + + + Civil_Correction + + + Commercial_Correctio + + + Commercial_Cours + + + Deontologie_Cours + + + Droit civil - Cours + + + Methodo_Oraux + + + Penal_Correction + + + Penal_Cours + + + Procedures_Cours + + + Reunion_info + + + Social_Corrections + + + Social_Cours + + + REUNION + + + TEST + + + + + + ENM + + + TEST + + + REUNION + + + + + + + FJP + + + Actualisation + + + TEST + + + REUNION + + + + + + MARINHO A. + + + GIUSTINIANI G. + + + BOFFA R. + + + MEUNIER J. + + + THERY C. + + + JLB + + + AZZI T. + + + ETIENNEY A. + + + MARKUS J. + + + ANDREU L. + + + ROUMIER W. + + + HAIK R. + + + POISSON S. + + + CARTIER-BRESSON A. + + + MBONGO P. + + + MATHONNET P. + + + FOULQUIER N. + + + RILOV. F + + + JEANSEN E. + + + LA J. + + + MECARELLI G. + + + COLLET M. + + + GILBERT S. + + + VIAL C. + + + PAGNERRE E. + + + PANOU C. + + + GILBERT S. + + + ROBBE S. + + + + 1ere_sem + 2e_sem + 3e_sem + 4e_sem + 5e_sem + 6e_sem + 7e_sem + 8e_sem + 9e_sem + 10e_sem + 11e_sem + 12e_sem + 13e_sem + 14e_sem + 15e_sem + 16e_sem + + diff --git a/install.py b/install.py index 5358ac8..e4f675d 100644 --- a/install.py +++ b/install.py @@ -45,6 +45,9 @@ install_dir = '/var/www/telecaster' if not os.path.exists(install_dir): os.mkdir(install_dir) +user = raw_input('Give a user to use the TeleCaster system : ') +print 'Installing...' + os.system('cp -ra ./* ' + install_dir + os.sep) os.system('rm -rf ' + install_dir + os.sep + 'tools/edcast-jack') os.system('rm -rf ' + install_dir + os.sep + 'tools/deefuzzer') @@ -53,9 +56,9 @@ etc_dir = '/etc' conf_dir = etc_dir + os.sep + 'telecaster' if not os.path.exists(conf_dir): os.mkdir(conf_dir) - os.system('chown -R root:root ./conf/etc/') os.system('cp -ra ./conf/etc/* ' + etc_dir + os.sep) - + os.system('chown -R root:root ' + etc_dir) + init_dir = '/etc/rc2.d' init_link = init_dir + os.sep + 'S97jackd' if not os.path.exists(init_link): @@ -65,7 +68,6 @@ init_link = init_dir + os.sep + 'S99vncserver' if not os.path.exists(init_link): os.system('ln -s /etc/init.d/vncserver ' + init_link) -user = raw_input('Give a user to use the TeleCaster system : ') os.system('chown -R ' + user + ':' + user + ' ' + install_dir) home = os.sep + 'home' + os.sep + user + os.sep home_dirs = ['fluxbox', 'vnc'] @@ -74,8 +76,8 @@ for dir in home_dirs: home_dir = home + '.' + dir if not os.path.exists(home_dir): os.mkdir(home_dir) - os.system('cp ' + conf_dir + os.sep + 'home' + os.sep + dir + '/* ' + home_dir) - os.system('chown -R ' + user + ':' + user + ' ' + home_dir) + os.system('cp ' + conf_dir + os.sep + 'home' + os.sep + dir + '/* ' + home_dir) + os.system('chown -R ' + user + ':' + user + ' ' + home_dir) #var_dir = '/var/www/telecaster' #if not os.path.exists(var_dir): diff --git a/station.py b/station.py index 6bf3426..7c77c3d 100644 --- a/station.py +++ b/station.py @@ -85,15 +85,8 @@ class Station(Conference): self.conf = self.conf['telecaster'] self.user = pwd.getpwuid(os.getuid())[0] self.user_dir = '/home' + os.sep + self.user + os.sep + '.telecaster' - self.url_ext = self.conf['infos']['url'] self.rec_dir = self.conf['media']['rec_dir'] - self.host = self.conf['server']['host'] - self.port = self.conf['server']['port'] - self.rss_dir = self.conf['server']['rss']['dir'] - self.rss_file = 'telecaster.xml' - self.password = self.conf['server']['sourcepassword'] - self.url_int = 'http://'+self.host+':'+self.port - self.deefuzzer_default_conf_file = self.conf['server']['deefuzzer_default_conf'] + self.deefuzzer_default_conf_file = self.conf['deefuzzer']['conf'] self.deefuzzer_user_file = self.user_dir + os.sep + 'deefuzzer.xml' self.bitrate = self.conf['media']['bitrate'] self.dict['Bitrate'] = str(self.bitrate) + ' kbps' @@ -107,9 +100,7 @@ class Station(Conference): self.server_name = [self.title, self.department, self.conference] self.ServerDescription = clean_string('-'.join(self.description)) self.ServerName = clean_string('-'.join(self.server_name)) - self.mount_point = clean_string(self.title) + '-' + \ - clean_string(self.department) + '-' + \ - clean_string(self.conference) + self.mount_point = '-'.join([clean_string(self.title), clean_string(self.department), clean_string(self.conference)]) self.filename = clean_string('-'.join(self.description[1:])) + '-' + self.time_txt + '.' + self.format self.output_dir = self.rec_dir + os.sep + self.date + os.sep + self.department self.file_dir = self.output_dir + os.sep + self.ServerName @@ -133,50 +124,42 @@ class Station(Conference): else: self.jack_inputs.append(jack_inputs['name']) - # DeeFuzzzer setup self.deefuzzer_dict = xml2dict(self.deefuzzer_default_conf_file) - self.station_local = self.deefuzzer_dict['deefuzzer']['station'][0] - self.station_distant = self.deefuzzer_dict['deefuzzer']['station'][1] - - self.station_local['infos']['short_name'] = self.mount_point - self.station_local['infos']['name'] = self.ServerName - self.station_local['infos']['description'] = self.ServerDescription.replace(' ','_') - self.station_local['infos']['genre'] = self.genre - self.station_local['server']['host'] = '127.0.0.1' - self.station_local['server']['port'] = self.port - self.station_local['server']['sourcepassword'] = self.password - self.station_local['media']['bitrate'] = self.bitrate - self.station_local['media']['dir'] = self.play_dir - self.station_local['media']['voices'] = str(len(self.jack_inputs)) - self.station_local['record']['mode'] = '1' - self.station_local['record']['dir'] = self.file_dir - self.station_local['relay']['mode'] = '1' - self.station_local['relay']['author'] = self.professor - - self.station_distant['infos']['short_name'] = self.mount_point - self.station_distant['infos']['name'] = self.ServerName - self.station_distant['infos']['description'] = self.ServerDescription.replace(' ','_') - self.station_distant['infos']['genre'] = self.genre - self.station_distant['server']['host'] = self.host - self.station_distant['server']['port'] = self.port - self.station_distant['server']['sourcepassword'] = self.password - self.station_distant['media']['bitrate'] = self.bitrate - self.station_distant['media']['dir'] = self.play_dir - self.station_distant['media']['voices'] = str(len(self.jack_inputs)) - self.station_distant['record']['mode'] = '0' - self.station_distant['record']['dir'] = self.file_dir - self.station_distant['relay']['mode'] = '1' - self.station_distant['relay']['author'] = self.professor - - self.deefuzzer_local_port = self.station_local['control']['port'] + self.deefuzzer_osc_ports = [] + self.server_ports = [] + + for station in self.deefuzzer_dict['deefuzzer']['station']: + if station['control']['mode'] == 1: + self.deefuzzer_osc_ports.append(station['control']['port']) + self.server_ports.append(station['server']['port']) + if station['server']['host'] == 'localhost' or station['server']['host'] == '127.0.0.1': + self.conf['play_port'] = station['server']['port'] + else: + self.conf['play_port'] = '8000' + + def deefuzzer_setup(self): + i = 0 + for station in self.deefuzzer_dict['deefuzzer']['station']: + station['infos']['short_name'] = self.mount_point + station['infos']['name'] = self.ServerName + station['infos']['description'] = self.ServerDescription.replace(' ','_') + station['infos']['genre'] = self.genre + station['media']['bitrate'] = self.bitrate + station['media']['dir'] = self.play_dir + station['media']['voices'] = str(len(self.jack_inputs)) + station['record']['dir'] = self.file_dir + station['relay']['mode'] = '1' + station['relay']['author'] = self.professor + self.deefuzzer_dict['deefuzzer']['station'][i] = station + i += 1 self.deefuzzer_xml = dicttoxml(self.deefuzzer_dict) - def write_deefuzzer_conf(self): + def deefuzzer_write_conf(self): conf_file = open(self.deefuzzer_user_file,'w') conf_file.write(self.deefuzzer_xml) conf_file.close() - def start_deefuzzer(self): + def deefuzzer_start(self): command = 'deefuzzer ' + self.deefuzzer_user_file + ' &' os.system(command) self.set_lock() @@ -191,13 +174,14 @@ class Station(Conference): def del_lock(self): os.remove(self.lock_file) - def stop_deefuzzer(self): - os.system('kill -9 '+self.deefuzzer_pid[0]) + def deefuzzer_stop(self): + os.system('kill -9 '+self.deefuzzer_pid[0]) - def stop_rec(self): + def rec_stop(self): if len(self.deefuzzer_pid) != 0: - target = liblo.Address(self.deefuzzer_local_port) - liblo.send(target, "/record", 0) + for port in self.deefuzzer_osc_ports: + target = liblo.Address(port) + liblo.send(target, "/record", 0) def mp3_convert(self): os.system('oggdec -o - '+ self.file_dir+os.sep+self.filename+' | lame -S -m m -h -b '+ self.bitrate + \ @@ -239,53 +223,12 @@ class Station(Conference): def start(self): self.set_lock() - self.write_deefuzzer_conf() - self.start_deefuzzer() - #self.update_rss() + self.deefuzzer_setup() + self.deefuzzer_write_conf() + self.deefuzzer_start() def stop(self): - self.stop_rec() - time.sleep(2) - self.stop_deefuzzer() - #if self.format == 'ogg': - # self.write_tags_ogg() - #elif self.format == 'mp3': - # self.write_tags_mp3() + self.rec_stop() + time.sleep(1) + self.deefuzzer_stop() self.del_lock() - #self.mp3_convert() - #self.rsync_out() - - def update_rss(self): - rss_item_list = [] - if not os.path.exists(self.rss_dir): - os.makedirs(self.rss_dir) - - time_now = datetime.datetime.now().strftime("%x-%X") - - media_description = '' - media_description_item = '' - for key in self.dict.keys(): - if self.dict[key] != '': - media_description += media_description_item % (key.capitalize(), self.dict[key]) - media_description += '
%s: %s
' - - media_link = self.url_ext + '/rss/' + self.rss_file - media_link = media_link.decode('utf-8') - - rss_item_list.append(RSSItem( - title = self.ServerName, - link = media_link, - description = media_description, - guid = Guid(media_link), - pubDate = self.time_txt,) - ) - - rss = RSS2(title = self.title + ' - ' + self.department, - link = self.url_ext, - description = self.ServerDescription.decode('utf-8'), - lastBuildDate = str(time_now), - items = rss_item_list,) - - #f = open(self.rss_dir + os.sep + self.rss_file, 'w') - #rss.write_xml(f, 'utf-8') - #f.close() diff --git a/telecaster.py b/telecaster.py index 2485f2a..20df966 100755 --- a/telecaster.py +++ b/telecaster.py @@ -35,7 +35,7 @@ # Author: Guillaume Pellerin """ -version = '0.4.1' +version = '0.4.2' import os @@ -53,13 +53,14 @@ class TeleCaster: """Manage the calls of Station and Webview to get the network and disk streams""" - def __init__(self, conf_file, session_file): + def __init__(self, conf_file): """Main function""" self.conf_file = conf_file - self.session_file = session_file conf_dict = xml2dict(self.conf_file) self.conf = conf_dict['telecaster'] self.title = self.conf['infos']['name'] + self.log_file = self.conf['log'] + self.logger = Logger(self.log_file) self.uid = os.getuid() self.url = self.conf['infos']['url'] self.user = pwd.getpwuid(os.getuid())[0] @@ -73,7 +74,7 @@ class TeleCaster: deefuzzer_pid = get_pid('/usr/bin/deefuzzer', self.uid) writing = edcast_pid != [] casting = deefuzzer_pid != [] - form = WebView(self.session_file, self.url, version) + form = WebView(self.conf, version) if deefuzzer_pid == [] and form.has_key("action") and \ form.has_key("department") and form.has_key("conference") and \ @@ -89,29 +90,32 @@ class TeleCaster: s = Station(self.conf_file, self.conference_dict, self.lock_file) s.start() - time.sleep(1) + self.logger.write_info('starting') + time.sleep(2) self.main() elif deefuzzer_pid != [] and os.path.exists(self.lock_file) and not form.has_key("action"): self.conference_dict = get_conference_from_lock(self.lock_file) form.stop_form(self.conference_dict, writing, casting) + self.logger.write_info('page stop') elif deefuzzer_pid and form.has_key("action") and form["action"].value == "stop": if os.path.exists(self.lock_file): self.conference_dict = get_conference_from_lock(self.lock_file) s = Station(self.conf_file, self.conference_dict, self.lock_file) s.stop() + self.logger.write_info('stopping') time.sleep(1) self.main() elif deefuzzer_pid == []: form.start_form(writing, casting) + self.logger.write_info('page start') conf_file = '/etc/telecaster/telecaster.xml' -session_file = '/etc/telecaster/sessions.xml' if __name__ == '__main__': - t = TeleCaster(conf_file, session_file) + t = TeleCaster(conf_file) t.main() diff --git a/tools/__init__.py b/tools/__init__.py index 8ce7f8b..40a6199 100644 --- a/tools/__init__.py +++ b/tools/__init__.py @@ -3,5 +3,4 @@ from xmltodict import * from tools import * from acpi import * from PyRSS2Gen import * - - +from logger import Logger diff --git a/tools/tools.py b/tools/tools.py index 50349c1..776bf97 100644 --- a/tools/tools.py +++ b/tools/tools.py @@ -45,6 +45,27 @@ from xmltodict import * import socket import fcntl import struct +import subprocess + +class SubProcessPipe: + def __init__(self, command, stdin=None): + """Read media and stream data through a generator. + Taken from Telemeta (see http://telemeta.org)""" + + self.buffer_size = 0xFFFF + + if not stdin: + stdin = subprocess.PIPE + + self.proc = subprocess.Popen(command.encode('utf-8'), + shell = True, + bufsize = self.buffer_size, + stdin = stdin, + stdout = subprocess.PIPE, + close_fds = True) + + self.input = self.proc.stdin + self.output = self.proc.stdout def get_ip_address(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -77,16 +98,21 @@ def xml2dict(conf_file): def get_pid(proc,uid): """Get a process pid filtered by arguments and uid""" - (list1, list2) = os.popen4('pgrep -fl -U '+str(uid)+' '+'"'+proc+'"') - procs = list2.readlines() + command = 'pgrep -fl -U '+str(uid)+' '+'"'+proc+'"' + proc = SubProcessPipe(command) + list = proc.output + procs = list.readlines() pids = [] if procs != '': for proc in procs: pid = proc.split(' ')[0] command = ' '.join(proc.split(' ')[1:])[:-1] pids.append(pid) - return pids - + if len(pids) == 1: + return [] + else: + return [pids[0]] + def get_params_from_lock(lock_file): lockfile = open(lock_file,'r') params = lockfile.readline() diff --git a/webview.py b/webview.py index 04f1c08..cce7e0d 100644 --- a/webview.py +++ b/webview.py @@ -4,7 +4,7 @@ """ telecaster - Copyright (c) 2006-2008 Guillaume Pellerin + Copyright (c) 2006-2010 Guillaume Pellerin # This software is governed by the CeCILL license under French law and # abiding by the rules of distribution of free software. You can use, @@ -52,11 +52,10 @@ cgitb.enable() class WebView(FieldStorage): """Gives the web CGI frontend""" - def __init__(self, school_file, url, version): + def __init__(self, conf, version): FieldStorage.__init__(self) + self.conf = conf self.version = version - self.conf = xml2dict(school_file) - self.conf = self.conf['telecaster'] self.interfaces = ['eth0', 'eth1', 'eth2'] ip = '' for interface in self.interfaces: @@ -67,22 +66,20 @@ class WebView(FieldStorage): break except: self.ip = 'localhost' - if 'host' in self.conf: - self.host = self.conf['host'] + if 'url' in self.conf['infos']: + self.url = 'http://' + self.conf['infos']['url'] else: - self.host = self.ip - self.url = 'http://' + self.host + self.url = 'http://' + self.ip self.rss_url = self.url+'/rss/telecaster.xml' - self.port = self.conf['port'] + self.port = '8000' self.acpi = acpi.Acpi() - self.format = self.conf['format'] - self.title = self.conf['title'] + self.format = self.conf['media']['format'] + self.short_name = self.conf['infos']['short_name'] + self.title = self.conf['infos']['name'] + ' - ' + self.conf['infos']['description'] self.departments = self.conf['department'] self.professors = self.conf['professor'] self.professors.sort() self.comments = self.conf['comment'] - #print self.departments - #self.conferences = self.conf['department']['conferences'] self.len_departments = len(self.departments) self.len_professors = len(self.professors) self.conference_nb_max = 40 @@ -95,7 +92,7 @@ class WebView(FieldStorage): def header(self): # Required header that tells the browser how to render the HTML. - print "Content-Type: text/html\n\n" + print "Content-Type: text/html\n" print "" print "" print "" @@ -173,16 +170,7 @@ class WebView(FieldStorage): power_info = "secteur" else: power_info = "" - - #if self.power_state == 0: - #batt_info = "en décharge" - #elif self.power_state == 1: - #batt_info = "chargée" - #elif self.power_state == 2: - #batt_info = "en charge" - #else: - #batt_info = "" - + if self.acpi.percent() == 127: batt_charge = '100 %' else: @@ -205,14 +193,14 @@ class WebView(FieldStorage): print "
" print "
Status
" print "" + print "" + print "" % self.conf['infos']['url'] + print "" + print "" % ip_info print "" print "" % power_info - #print "" - #print "" % batt_info print "" print "" % batt_charge - #print "" - #print "" % self.acpi.estimated_lifetime() try: print "" % self.acpi.temperature(0) except: @@ -221,8 +209,6 @@ class WebView(FieldStorage): print "" % self.acpi.temperature(1) except: pass - print "" - print "" % ip_info print "" print "" % jackd_info print "" print "" print "" - - #print "" - print "
Name : %s
IP address : %s
Power : %s
Etat batterie :%s
Battery charge : %s
Estimation durée batterie :%s
Temp core 1 : %s
Temp core 2 : %s
IP address : %s
JACK audio server : %s
" @@ -241,10 +227,11 @@ class WebView(FieldStorage): def start_form(self, writing, casting, message=''): - self.refresh = False - self.header() self.casting = writing self.writing = casting + self.refresh = False + + self.header() self.hardware_data() print "
" print "
" @@ -270,49 +257,31 @@ class WebView(FieldStorage): print "
Commentaire :
" print "
" - #print "
Cliquez ici pour écouter le flux continu 24/24 en direct
" print "
" print "
" - #print "" print "" print "" - print "\"\"Archives" - print "\"\"Trash" - #print "" + print "\"\"Archives" + print "\"\"Trash" print "
" print "
" print "" self.colophon() self.footer() - def encode_form(self, message=''): - self.header() - print "
" - print "
"+message+"
" - print "
ENCODAGE EN COURS !
" - print "
" - self.colophon() - self.footer() - def stop_form(self, conference_dict, writing, casting): - """Stop page""" department = conference_dict['department'] conference = conference_dict['conference'] session = conference_dict['session'] professor = conference_dict['professor'] comment = conference_dict['comment'] + self.mount_point ='-'.join([clean_string(self.short_name),clean_string(department), clean_string(conference)])+'.'+self.format+'.m3u' self.writing = writing self.casting = casting self.refresh = True + self.header() self.hardware_data() print "
" @@ -324,28 +293,15 @@ class WebView(FieldStorage): print "Professeur : "+professor+"" print "Commentaire : "+comment+"" print "" - #print "
Cliquez ici pour écouter cette formation en direct
" print "
" - - #print """
- #

- #
- # - #
- # - #
- #
- # - #
""" - print "
" print "
" print "
" print "" - print "\"\"Play" + print "\"\"Play" print "" - print "\"\"Archives" - print "\"\"Trash" + print "\"\"Archives" + print "\"\"Trash" print "
" print "
" print "
" -- 2.39.5