From: yomguy Date: Mon, 20 Oct 2008 11:45:05 +0000 (+0000) Subject: Add acpi tools, make temp oddcast config X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=ef2b86ee2b3b3c529924143084f94d14a4751a80;p=telecaster-cgi.git Add acpi tools, make temp oddcast config --- diff --git a/css/telecaster.css b/css/telecaster.css index 97917e1..f0a874a 100644 --- a/css/telecaster.css +++ b/css/telecaster.css @@ -1,29 +1,68 @@ -div#header { background-color: #030250; +div.header { background-color: #030250; color: #FFFFFF; padding: 0.5em; line-height: 10px; + font: 0.8125em/1em Verdana, sans-serif; + font-size: 1em; } -div#bg { background-color: #030250; +div.bg { background-color: #FFFFFF; color: #FFFFFF; } -div#main { background-color: #FFFFFF; - color: #000033; + +div.main { + clear: both; + width: 50%; + display: block; + background-color: transparent; + color: #000033; padding:1em; - margin: 0; + position: relative; + font: 0.8125em/1em Verdana, sans-serif; } -div#tools { background-color: #030250; + + +div.tools { background-color: #030250; color: #FFFFFF; + font-size: 1em; border: 1px solid #FFFFFF; padding:0.5em; margin: 0; } -div#colophon { background-color: #FFFFFF; + +div.colophon { background-color: #FFFFFF; color: #000033; font-size: 80%; float: right; + font: 0.8125em/1em Verdana, sans-serif; +} + +div.title { background-color: #030250; + color: #FFFFFF; + padding: 0.5em; + line-height: 10px; + font: 0.8125em/1em Verdana, sans-serif; } +div.hardware { clear: both; + font: 0.8125em/1em Verdana, sans-serif; + font-size: 1em; + position: absolute; + right: 1em; + text-align: left; + margin-top: 10px; + border: 1px dotted #999; + padding: 6px; + background-color: #eee; + display: block; +} + +div.form { background-color: #FFFFFF; + float: left; + color: #000033; + padding:1em; + margin: 0; +} diff --git a/etc/telecaster_mp3.cfg b/etc/telecaster_mp3.cfg index ed72e65..a12c9a5 100644 --- a/etc/telecaster_mp3.cfg +++ b/etc/telecaster_mp3.cfg @@ -1,7 +1,7 @@ Server=localhost Port=8000 ServerPassword=source2parisson -ServerMountpoint=/Pre-Barreau_-_ICP_-_CRFPA_-_Droit_administratif_Corrections.mp3 +ServerMountpoint=/Pre-Barreau_-_ICP_-_AE_-_Adm_Correction.mp3 ServerPublic=0 AutomaticReconnectSecs=10 Encode=MP3 Lame @@ -13,8 +13,8 @@ ServerType=Icecast2 ExternalFile=/tmp/test #YP Settings ServerStreamURL=http://www.pre-barreau.com -ServerName=Pre-Barreau_-_ICP_-_CRFPA_-_Droit_administratif_Corrections -ServerDescription=Pre-Barreau_-_ICP_-_CRFPA_-_Droit_administratif_Corrections_-_2_-_MARINHO_A._-_1er_cours +ServerName=Pre-Barreau_-_ICP_-_AE_-_Adm_Correction +ServerDescription=Pre-Barreau_-_ICP_-_AE_-_Adm_Correction_-_3_-_GIUSTINIANI_G._-_2e_cours ServerGenre=Teaching #Advanced Settings LogLevel=1 diff --git a/telecaster.py b/telecaster.py index 46f686e..471492c 100755 --- a/telecaster.py +++ b/telecaster.py @@ -3,7 +3,7 @@ """ telecaster - Copyright (c) 2006-2007 Guillaume Pellerin + Copyright (c) 2006-2008 Guillaume Pellerin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +20,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ -version = '0.3.4' +version = '0.3.5' +# Only for Unix and Linux systems import os import cgi @@ -33,6 +34,7 @@ import string import signal import unicodedata from tools import * +from tempfile import NamedTemporaryFile from mutagen.oggvorbis import OggVorbis from mutagen.id3 import ID3, TIT2, TP1, TAL, TDA, TCO, COM cgitb.enable() @@ -61,7 +63,7 @@ class Station(Conference): self.date = datetime.datetime.now().strftime("%Y") self.time = datetime.datetime.now().strftime("%x-%X") self.time1 = self.time.replace('/','_') - self.time2 = self.time1.replace(':','_') + self.time2 = self.time1.replace(':','_') self.time = self.time2.replace(' ','_') self.conf = xml2dict(conf_file) self.conf = self.conf['telecaster'] @@ -88,7 +90,8 @@ class Station(Conference): self.uid = os.getuid() self.odd_pid = get_pid('^oddcastv3 -n [^LIVE]', self.uid) self.rip_pid = get_pid('streamripper ' + self.url + self.mount_point, self.uid) - self.new_title = clean_string('_-_'.join(self.server_name)+'_-_'+self.professor+'_-_'+self.comment) + self.new_title = clean_string('_-_'.join(self.server_name)+'_-_'+self.session+'_-_'+self.professor+'_-_'+self.comment) + self.short_title = clean_string('_-_'.join(self.conference)+'_-_'+self.session+'_-_'+self.professor+'_-_'+self.comment) self.genre = 'Vocal' self.encoder = 'TeleCaster by Parisson' self.rsync_host = self.conf['server']['rsync_host'] @@ -100,6 +103,7 @@ class Station(Conference): os.makedirs(self.raw_dir) def set_oddcast_conf(self): + oddconf_temp = NamedTemporaryFile(suffix='.cfg') oddconf = open(self.odd_conf_file,'r') lines = oddconf.readlines() oddconf.close() @@ -123,17 +127,17 @@ class Station(Conference): else: newlines.append(line) - - oddconf = open(self.odd_conf_file,'w') - oddconf.writelines(newlines) - oddconf.close() + + oddconf_temp_file = open(oddconf_temp.name,'w') + oddconf_temp_file.writelines(newlines) + self.odd_conf = oddconf_temp.name def start_oddcast(self): - command = 'oddcastv3 -n "'+clean_string(self.conference)[0:16]+'" -c '+self.odd_conf_file+ \ + command = 'oddcastv3 -n "'+clean_string(self.conference)[0:16]+'" -c '+self.odd_conf+ \ ' alsa_pcm:capture_1 > /dev/null &' os.system(command) self.set_lock() - time.sleep(1) + time.sleep(0.1) def set_lock(self): lock = open(self.lock_file,'w') @@ -273,10 +277,19 @@ class WebView: def __init__(self, school_file): self.conf = xml2dict(school_file) self.conf = self.conf['telecaster'] - self.interface = 'eth1' - self.ip = get_ip_address(self.interface) + self.interfaces = ['eth0', 'eth1', 'eth2'] + ip = '' + for interface in self.interfaces: + try: + ip = get_ip_address(interface) + if ip: + self.ip = ip + break + except: + self.ip = 'localhost' self.url = 'http://' + self.ip self.port = self.conf['port'] + self.acpi = acpi.Acpi() self.format = self.conf['format'] self.title = self.conf['title'] self.departments = self.conf['department'] @@ -326,15 +339,15 @@ class WebView: print "\n" print "" - print "
" - print "
" + print "
" + print "
" print "

 TeleCaster - L'enregistrement et la diffusion audio en direct par internet

" print "
" def colophon(self): date = datetime.datetime.now().strftime("%Y") - print "
" - print "TeleCaster "+version+" © "+date+" Parisson. Tous droits réservés." + print "
" + print "TeleCaster "+version+" © "+date+" Parisson SARL. Tous droits réservés." print "
" def footer(self): @@ -342,12 +355,66 @@ class WebView: print "" print "" + def hardware_data(self): + self.acpi.update() + self.power_state = self.acpi.charging_state() + if self.power_state == 0: + power_info = "batterie" + elif self.power_state == 1 or self.power_state == 2: + 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: + percent = self.acpi.percent() + if percent < 10: + batt_charge = ''+str(percent)+' %' + else: + batt_charge = ''+str(percent)+' %' + + if self.ip == 'localhost': + ip_info = ''+self.ip+'' + else: + ip_info = ''+self.ip+'' + + print "
" + print "
Informations matérielles
" + print "" + print "" + print "" % power_info + #print "" + #print "" % batt_info + print "" + print "" % batt_charge + #print "" + #print "" % self.acpi.estimated_lifetime() + print "" + print "" % self.acpi.temperature(0) + print "" + print "" % ip_info + print "
Alimentation :%s
Etat batterie :%s
Capacité batterie :%s
Estimation durée batterie :%s
Temp core 1 :%s
Address IP :%s
" + print "
" + + def start_form(self, message=''): self.refresh = False self.header() - print "
" - print "
"+message+"
" - print "
Attention, il est important de remplir tous les champs, y compris le commentaire !
" + self.hardware_data() + print "
" + #print "
"+message+"
" + #print "
Attention, il est important de remplir tous les champs, y compris le commentaire !
" + print "
" print "" print "" print "" @@ -383,14 +450,16 @@ class WebView: for comment in self.comments: print "" print "" - + print "
Titre :"+self.title+"
" + print "
" + #print "
Cliquez ici pour écouter le flux continu 24/24 en direct
" print '
' print "
Cliquez ici pour accéder aux archives
" print "
Cliquez ici pour accéder aux archives de secours
" print "
" - print "
" + print "
" print "" print "" print "" @@ -400,7 +469,7 @@ class WebView: def encode_form(self, message=''): self.header() - print "
" + print "
" print "
"+message+"
" print "
ENCODAGE EN COURS !
" print "
" @@ -414,9 +483,10 @@ class WebView: session = conference_dict['session'] professor = conference_dict['professor'] comment = conference_dict['comment'] - self.refresh = False + self.refresh = True self.header() - print "
" + self.hardware_data() + print "
" print "
" if writing: @@ -440,7 +510,7 @@ class WebView: print "
" print "
Cliquez ici pour écouter cette formation en direct
" print "
" - print "
" + print "
" print "
" print "" print "" @@ -463,7 +533,6 @@ class TeleCaster: self.title = self.conf['infos']['name'] self.root_dir = self.conf['server']['root_dir'] self.lock_file = self.root_dir + os.sep + self.conf['server']['lock_file'] - self.odd_conf_file = self.conf['server']['lock_file'] self.title = self.conf['infos']['name'] self.uid = os.getuid() @@ -491,7 +560,7 @@ class TeleCaster: 'session': form["session"].value, 'professor': form["professor"].value, 'comment': form["comment"].value} - + s = Station(self.conf_file, self.conference_dict, self.lock_file) s.start() if get_pid('^oddcastv3 -n [^LIVE]', self.uid) != []: diff --git a/tools/acpi.py b/tools/acpi.py index 4cb3db5..9d1b6ca 100644 --- a/tools/acpi.py +++ b/tools/acpi.py @@ -2,9 +2,10 @@ ## ## $Id: acpi.py,v 1.23 2003/12/15 20:04:09 riemer Exp $ ## -## Copyright (C) 2002-2003 Tilo Riemer , +## Copyright (C) 2002-2008 Tilo Riemer , ## Luc Sorgue and -## Rds +## Rds and +## Guillaume Pellerin ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without @@ -60,494 +61,495 @@ ERR_CONFIGURATION_CHANGED = -5 #reload module? or function reconfigure? ERR_NOT_ALLOWED = -6 #access for some resource not allowed --> better idea? class AcpiError(Exception): - """ACPI exceptions""" + """ACPI exceptions""" - def __init__(self, errno): - self.errno = errno + def __init__(self, errno): + self.errno = errno - def __str__(self): - if self.errno == ERR_GENERIC: - return "Any ACPI error occured." - elif self.errno == ERR_NO_DEVICE: - return "ACPI is not configured on this host." - elif self.errno == ERR_NOT_IMPLEMENTED: - return "No implementation for this operating system." - elif self.errno == ERR_NO_LOW_LEVEL: - return "Acpi_lowlevel module not found." - elif self.errno == ERR_CONFIGURATION_CHANGED: - return "ACPI configuartion has been changed." - else: - return "Unknown error occured." + def __str__(self): + if self.errno == ERR_GENERIC: + return "Any ACPI error occured." + elif self.errno == ERR_NO_DEVICE: + return "ACPI is not configured on this host." + elif self.errno == ERR_NOT_IMPLEMENTED: + return "No implementation for this operating system." + elif self.errno == ERR_NO_LOW_LEVEL: + return "Acpi_lowlevel module not found." + elif self.errno == ERR_CONFIGURATION_CHANGED: + return "ACPI configuartion has been changed." + else: + return "Unknown error occured." # interface ################################################################### class Acpi: - """Interface class for ACPI""" - - def __init__(self): - res = sys.platform - if res.find("freebsd4") > -1: - self.acpi = None #throw exception - raise AcpiError, ERR_NOT_IMPLEMENTED - - elif res.find("netbsd1") > -1: - self.acpi = None #throw exception - raise AcpiError, ERR_NOT_IMPLEMENTED - - elif res.find("linux2") > -1: - self.acpi = AcpiLinux() - - elif res.find("linux") > -1: - #some systems return linux instead of linux2. We should - #show a warning or check by ourselves for Linux2 - self.acpi = AcpiLinux() - - else: - self.acpi = None #throw exception (os unknown) - raise AcpiError, ERR_NOT_IMPLEMENTED - - - def identity(self): - """Returns the identity of this module""" - return "acpi.py" - - def version(self): - """Returns the version of this module""" - return VERSION - - def update(self): - """Updates the ACPI state""" - self.acpi.update() - - def percent(self): - """Returns percentage capacity of all batteries""" - return self.acpi.percent() - - def capacity(self): - """Returns capacity of all batteries (in mWh)""" - return self.acpi.capacity() - - def nb_of_batteries(self): - """Returns the number of batteries""" - return self.acpi.nb_of_batteries() - - def charging_state(self): - """Returns ac state (off-/online/charging)""" - return self.acpi.charging_state() - - def estimated_lifetime(self): - """Returns Estimated Lifetime as real number""" - return self.acpi.estimated_lifetime() - - def temperature(self, idx): - """Returns Processor Temperature""" - return self.acpi.temperature(idx) - - def fan_state(self, idx): - """Returns fan states""" - return self.acpi.fan_state(idx) + """Interface class for ACPI""" + + def __init__(self): + res = sys.platform + if res.find("freebsd4") > -1: + self.acpi = None #throw exception + raise AcpiError, ERR_NOT_IMPLEMENTED + + elif res.find("netbsd1") > -1: + self.acpi = None #throw exception + raise AcpiError, ERR_NOT_IMPLEMENTED + + elif res.find("linux2") > -1: + self.acpi = AcpiLinux() + + elif res.find("linux") > -1: + #some systems return linux instead of linux2. We should + #show a warning or check by ourselves for Linux2 + self.acpi = AcpiLinux() + + else: + self.acpi = None #throw exception (os unknown) + raise AcpiError, ERR_NOT_IMPLEMENTED + + + def identity(self): + """Returns the identity of this module""" + return "acpi.py" + + def version(self): + """Returns the version of this module""" + return VERSION + + def update(self): + """Updates the ACPI state""" + self.acpi.update() + + def percent(self): + """Returns percentage capacity of all batteries""" + return self.acpi.percent() + + def capacity(self): + """Returns capacity of all batteries (in mWh)""" + return self.acpi.capacity() + + def nb_of_batteries(self): + """Returns the number of batteries""" + return self.acpi.nb_of_batteries() + + def charging_state(self): + """Returns ac state (off-/online/charging)""" + return self.acpi.charging_state() + + def estimated_lifetime(self): + """Returns Estimated Lifetime as real number""" + return self.acpi.estimated_lifetime() + + def temperature(self, idx): + """Returns Processor Temperature""" + return self.acpi.temperature(idx) + + def fan_state(self, idx): + """Returns fan states""" + return self.acpi.fan_state(idx) #unfinished: don't use it or better send us improvements ;-) - def frequency(self, idx): - """ Return the frequency of the processor""" - return self.acpi.frequency(idx) + def frequency(self, idx): + """ Return the frequency of the processor""" + return self.acpi.frequency(idx) - def performance_states(self, idx): - """ Return a list of available frequencies for the proc """ - return self.acpi.performance_states(idx) + def performance_states(self, idx): + """ Return a list of available frequencies for the proc """ + return self.acpi.performance_states(idx) - def set_frequency(self, f): - """ Set the processor frequency - Warning ! Needs root privileges to work """ - return self.acpi.set_frequency(f) + def set_frequency(self, f): + """ Set the processor frequency - Warning ! Needs root privileges to work """ + return self.acpi.set_frequency(f) # implementation for Linux #################################################### class AcpiLinux: - def __init__(self): - """init ACPI class and check for any ACPI features in /proc/acpi/""" + def __init__(self): + """init ACPI class and check for any ACPI features in /proc/acpi/""" - #we read all acpi stuff from here - self.proc_acpi_dir = "/proc/acpi" - #self.proc_acpi_dir = "/home/riemer/main/ACPI/proc/acpi" - - self.init_batteries() - self.init_fans() - #self.init_processors() - self.init_temperatures() - - self.update() + #we read all acpi stuff from here + self.proc_acpi_dir = "/proc/acpi" + #self.proc_acpi_dir = "/home/riemer/main/ACPI/proc/acpi" + + self.init_batteries() + self.init_fans() + #self.init_processors() + self.init_temperatures() + + self.update() - def update(self): - """Read current states of supported acpi components""" + def update(self): + """Read current states of supported acpi components""" - self.update_batteries() - self.update_fans() - #self.update_processors() - self.update_temperatures() + self.update_batteries() + self.update_fans() + #self.update_processors() + self.update_temperatures() - # battery related functions - def init_batteries(self): - """Checks for and initializes the batteries""" + # battery related functions + def init_batteries(self): + """Checks for and initializes the batteries""" - self.proc_battery_dir = self.proc_acpi_dir + "/battery" + self.proc_battery_dir = self.proc_acpi_dir + "/battery" # empty lists implies no battery, no capacity etc. - self.design_capacity = {} - self.life_capacity = {} - self.present_rate = {} - - # empty list of battery sub directories; implies no batteries available - self.battery_dir_entries = [] - - try: - battery_dir_entries = os.listdir(self.proc_battery_dir) - except OSError: - self.ac_line_state = ONLINE # no batteries: we assume that a cable is plugged in ;-) - return #nothing more to do - - - try: - for i in battery_dir_entries: - mode = os.stat(self.proc_battery_dir + "/" + i)[stat.ST_MODE] - if stat.S_ISDIR(mode): - self.battery_dir_entries.append(i) - except OSError: - # the battery module is not correctly loaded, or is broken. - # currently self.battery_dir_entries has no batteries or only - # the batteries which we could stat - # because the appended dirs should be okay we do not return here - pass - - self.ac_line_state = OFFLINE + self.design_capacity = {} + self.life_capacity = {} + self.present_rate = {} + + # empty list of battery sub directories; implies no batteries available + self.battery_dir_entries = [] + + try: + battery_dir_entries = os.listdir(self.proc_battery_dir) + except OSError: + self.ac_line_state = ONLINE # no batteries: we assume that a cable is plugged in ;-) + return #nothing more to do + + + try: + for i in battery_dir_entries: + mode = os.stat(self.proc_battery_dir + "/" + i)[stat.ST_MODE] + if stat.S_ISDIR(mode): + self.battery_dir_entries.append(i) + except OSError: + # the battery module is not correctly loaded, or is broken. + # currently self.battery_dir_entries has no batteries or only + # the batteries which we could stat + # because the appended dirs should be okay we do not return here + pass + + self.ac_line_state = OFFLINE #later: the newer acpi versions seems to generate always two BAT dirs... #check info for present: no - try: - for i in self.battery_dir_entries: - #print self.proc_battery_dir + "/" + i + "/info" - info_file = open(self.proc_battery_dir + "/" + i + "/info") - line = info_file.readline() - - while len(line) != 0: - if line.find("last full capacity:") == 0: - cap = line.split(":")[1].strip() - try: - self.design_capacity[i] = int(cap.split("m")[0].strip()) - except ValueError: - #no value --> conversion to int failed - self.design_capacity[i] = 0 - - line = info_file.readline() - info_file.close() - except IOError: - #print "No batt info found." - # the battery module is not correctly loaded... the file info should exist. - # wipe out all lists --> no battery infos - self.battery_dir_entries = [] - self.design_capacity = {} - self.life_capacity = {} - self.present_rate = {} - - - def update_batteries(self): - """Read current state of batteries""" - - try: - for i in self.battery_dir_entries: - state_file = open(self.proc_battery_dir + "/" + i + "/state") - line = state_file.readline() - - while len(line) != 0: - if line.find("remaining capacity") == 0: - cap = line.split(":")[1].strip() - try: - self.life_capacity[i] = int(cap.split("m")[0].strip()) - except ValueError: - self.life_capacity[i] = 0 + try: + for i in self.battery_dir_entries: + #print self.proc_battery_dir + "/" + i + "/info" + info_file = open(self.proc_battery_dir + "/" + i + "/info") + line = info_file.readline() + + while len(line) != 0: + if line.find("last full capacity:") == 0: + cap = line.split(":")[1].strip() + try: + self.design_capacity[i] = int(cap.split("m")[0].strip()) + except ValueError: + #no value --> conversion to int failed + self.design_capacity[i] = 0 + + line = info_file.readline() + info_file.close() + except IOError: + #print "No batt info found." + # the battery module is not correctly loaded... the file info should exist. + # wipe out all lists --> no battery infos + self.battery_dir_entries = [] + self.design_capacity = {} + self.life_capacity = {} + self.present_rate = {} + + + def update_batteries(self): + """Read current state of batteries""" + + try: + for i in self.battery_dir_entries: + state_file = open(self.proc_battery_dir + "/" + i + "/state") + line = state_file.readline() + + while len(line) != 0: + if line.find("remaining capacity") == 0: + cap = line.split(":")[1].strip() + try: + self.life_capacity[i] = int(cap.split("m")[0].strip()) + except ValueError: + self.life_capacity[i] = 0 # it's possible that in battery/*/info the charging state is unknown # --> then we must check ac_state... # iterating over all batteries this way is not smart. better implementation needed # better are funcs for capacity, acstate and prrate - # a little bit tricky... if loading of ac driver fails, we cant use info - # from /proc/ac_*/... - # if information in /proc/acpi/battery/*/state is wrong we had to - # track the capacity history. - # I assume that all battery state files get the same state. - if line.find("charging state") == 0: - state = line.split(":")[1].strip() - if state == "discharging": - self.ac_line_state = OFFLINE - elif state == "charging": - self.ac_line_state = CHARGING - else: - self.ac_line_state = ONLINE - - # Read the present energy consumption to - # estimate life time - - if line.find("present rate:") == 0: - try: - pr_rate = float(line.split(":")[1].strip().split("m")[0].strip()) - except ValueError: - pr_rate = 0 - - self.present_rate[i] = pr_rate - - line = state_file.readline() - state_file.close() - except IOError: - raise AcpiError, ERR_CONFIGURATION_CHANGED - - # maybe we should restart init_batteries instead of generating an error ? - # the user may have unplugged the battery. - #init_batteries() - # I prefer raising an exception because we would run into a recursion of - # member funcs what is not a good idea. - # the case that this error occurs should be very rare - - - def init_temperatures(self): - """Initializes temperature stuff""" - - self.proc_thermal_dir = self.proc_acpi_dir + "/thermal_zone" - - # empty list implies no thermal feature supported - self.temperatures = {} - - # empty list of thermal sub directories; implies no thermal infos available - self.thermal_dir_entries = [] - - try: - thermal_dir_entries = os.listdir(self.proc_thermal_dir) - except OSError: - return #nothing more to do - - try: - for i in thermal_dir_entries: - mode = os.stat(self.proc_thermal_dir + "/" + i)[stat.ST_MODE] - if stat.S_ISDIR(mode): - self.thermal_dir_entries.append(i) - except OSError: - # the thermal module is not correctly loaded, or is broken. - # because the appended dirs should be okay we do not return here - pass - - - def update_temperatures(self): - """Read current temperatures""" - - try: - for i in self.thermal_dir_entries: - file = open(self.proc_thermal_dir + "/" + i + "/temperature") - line = file.readline() - while len(line) != 0: - if line.find("temperature") == 0: - self.temperatures[i] = line.split(":")[1].strip() - line = file.readline() - file.close() - except IOError: - raise AcpiError,ERR_CONFIGURATION_CHANGED - - - def init_fans(self): - """Initialize fans""" - - self.proc_fan_dir = self.proc_acpi_dir + "/fan" - - self.fans = {} - - # empty list of fan sub directories; implies no fan infos available - self.fan_dir_entries = [] - - try: - fan_dir_entries = os.listdir(self.proc_fan_dir) - except OSError: - return #nothing more to do - - try: - for i in fan_dir_entries: - mode = os.stat(self.proc_fan_dir + "/" + i)[stat.ST_MODE] - if stat.S_ISDIR(mode): - self.fan_dir_entries.append(i) - except OSError: - # the fan module is not correctly loaded, or is broken. - # because the appended dirs should be okay we do not return here - pass - - - def update_fans(self): - """Read current state of fans""" - - try: - for i in self.fan_dir_entries: - file = open(self.proc_fan_dir + "/" + i + "/state") - line = file.readline() - while len(line) != 0: - if line.find("status") == 0: - if line.split(":")[1].strip() == 'on': - self.fans[i] = FAN_ON - else: - self.fans[i] = FAN_OFF - line = file.readline() - file.close() - except IOError: - raise AcpiError,ERR_CONFIGURATION_CHANGED - - - def init_processors(self): - """Initialize processors""" - - self.proc_processor_dir = self.proc_acpi_dir + "/processor" + # a little bit tricky... if loading of ac driver fails, we cant use info + # from /proc/ac_*/... + # if information in /proc/acpi/battery/*/state is wrong we had to + # track the capacity history. + # I assume that all battery state files get the same state. + if line.find("charging state") == 0: + state = line.split(":")[1].strip() + if state == "discharging": + self.ac_line_state = OFFLINE + elif state == "charging": + self.ac_line_state = CHARGING + else: + self.ac_line_state = ONLINE + + # Read the present energy consumption to + # estimate life time + + if line.find("present rate:") == 0: + try: + pr_rate = float(line.split(":")[1].strip().split("m")[0].strip()) + except ValueError: + pr_rate = 0 + + self.present_rate[i] = pr_rate + + line = state_file.readline() + state_file.close() + except IOError: + raise AcpiError, ERR_CONFIGURATION_CHANGED + + # maybe we should restart init_batteries instead of generating an error ? + # the user may have unplugged the battery. + #init_batteries() + # I prefer raising an exception because we would run into a recursion of + # member funcs what is not a good idea. + # the case that this error occurs should be very rare + + + def init_temperatures(self): + """Initializes temperature stuff""" + + self.proc_thermal_dir = self.proc_acpi_dir + "/thermal_zone" + + # empty list implies no thermal feature supported + self.temperatures = {} + + # empty list of thermal sub directories; implies no thermal infos available + self.thermal_dir_entries = [] + + try: + thermal_dir_entries = os.listdir(self.proc_thermal_dir) + #thermal_dir_entries.append('') + except OSError: + return #nothing more to do + + try: + for i in thermal_dir_entries: + mode = os.stat(self.proc_thermal_dir + "/" + i)[stat.ST_MODE] + if stat.S_ISDIR(mode): + self.thermal_dir_entries.append(i) + except OSError: + # the thermal module is not correctly loaded, or is broken. + # because the appended dirs should be okay we do not return here + pass + + + def update_temperatures(self): + """Read current temperatures""" + + try: + for i in self.thermal_dir_entries: + file = open(self.proc_thermal_dir + "/" + i + "/temperature") + line = file.readline() + while len(line) != 0: + if line.find("temperature") == 0: + self.temperatures[i] = line.split(":")[1].strip() + line = file.readline() + file.close() + except IOError: + raise AcpiError,ERR_CONFIGURATION_CHANGED + + + def init_fans(self): + """Initialize fans""" + + self.proc_fan_dir = self.proc_acpi_dir + "/fan" + + self.fans = {} + + # empty list of fan sub directories; implies no fan infos available + self.fan_dir_entries = [] + + try: + fan_dir_entries = os.listdir(self.proc_fan_dir) + except OSError: + return #nothing more to do + + try: + for i in fan_dir_entries: + mode = os.stat(self.proc_fan_dir + "/" + i)[stat.ST_MODE] + if stat.S_ISDIR(mode): + self.fan_dir_entries.append(i) + except OSError: + # the fan module is not correctly loaded, or is broken. + # because the appended dirs should be okay we do not return here + pass + + + def update_fans(self): + """Read current state of fans""" + + try: + for i in self.fan_dir_entries: + file = open(self.proc_fan_dir + "/" + i + "/state") + line = file.readline() + while len(line) != 0: + if line.find("status") == 0: + if line.split(":")[1].strip() == 'on': + self.fans[i] = FAN_ON + else: + self.fans[i] = FAN_OFF + line = file.readline() + file.close() + except IOError: + raise AcpiError,ERR_CONFIGURATION_CHANGED + + + def init_processors(self): + """Initialize processors""" + + self.proc_processor_dir = self.proc_acpi_dir + "/processor" # TODO: adapt it for multiple CPUs --> we need a matrix instead of a vector!!! - self.perf_states = {} #empty list implies no processor support - - # empty list of processor sub directories; implies no processor infos available - self.processor_dir_entries = [] - - try: - processor_dir_entries = os.listdir(self.proc_processor_dir) - except OSError: - return #nothing more to do - - try: - for i in processor_dir_entries: - mode = os.stat(self.proc_processor_dir + "/" + i)[stat.ST_MODE] - if stat.S_ISDIR(mode): - self.processor_dir_entries.append(i) - except OSError: - # the processor module is not correctly loaded, or is broken. - # because the appended dirs should be okay we do not return here - pass - - try: - for i in self.processor_dir_entries: - file = open(self.proc_processor_dir + "/" + i + "/performance") - line = file.readline() - while(len(line)!=0): - if line.find("MHz") > -1: - state = line.split(":")[0].strip().split("P")[-1] - freq = line.split(":")[1].split(",")[0].strip() - self.perf_states[freq] = state - line = file.readline() - file.close() - except IOError: - self.processor_dir_entries = [] - self.perf_states = {} #reset list --> should we throw an exception? No! - return - - - def update_processors(self): - """Read current state of processors""" - - try: - for i in self.processor_dir_entries: - file = open(self.proc_processor_dir + "/" + i + "/performance") - line = file.readline() - - while(len(line)!=0): - if line.find("*") > -1: - self.freq = line.split(":")[1].strip().split(",")[0] - line = f.readline() - file.close() - except IOError: - raise AcpiError,ERR_CONFIGURATION_CHANGED - - - def percent(self): - """Returns percentage capacity of all batteries""" - - life_capacity = 0 - design_capacity = 0 - for i,c in self.life_capacity.items(): - life_capacity = life_capacity + c - design_capacity = design_capacity + self.design_capacity[i] - - if design_capacity == 0: - return 0 - - # should we use try catch instead of the check above? - return (life_capacity * 100) / design_capacity - - - def capacity(self): - """Returns capacity of all batteries""" - capacity = 0 - for i,c in self.life_capacity.items(): - capacity = capacity + c - return capacity - - - def nb_of_batteries(self): - #returns the number of batteries - #if it returns 0, maybe ACPI is not available or - #battery driver is not loaded - return len(self.battery_dir_entries) - - - def charging_state(self): - return self.ac_line_state - - - def estimated_lifetime(self): - - # what should we return if state==charging? - # it's not clean to return a time in one case and any - # English string in another case. - # The user can check for ac-state before call this func - time = 0 - for batt,life_capacity in self.life_capacity.items(): - if self.present_rate[batt] > 0: - time = time + life_capacity/self.present_rate[batt] - return time - - - # we need funcs like max_temperature and average_temperature - def temperature(self, idx): - #print self.temperatures - #print self.thermal_dir_entries[idx] - return self.temperatures(self.thermal_dir_entries(idx)) - - - def fan_state(self, idx): - #print self.fans - return self.fans[self.fan_dir_entries[idx]] - - - def performance_states(self, idx): - return self.perf_states[idx].keys() + self.perf_states = {} #empty list implies no processor support + + # empty list of processor sub directories; implies no processor infos available + self.processor_dir_entries = [] + + try: + processor_dir_entries = os.listdir(self.proc_processor_dir) + except OSError: + return #nothing more to do + + try: + for i in processor_dir_entries: + mode = os.stat(self.proc_processor_dir + "/" + i)[stat.ST_MODE] + if stat.S_ISDIR(mode): + self.processor_dir_entries.append(i) + except OSError: + # the processor module is not correctly loaded, or is broken. + # because the appended dirs should be okay we do not return here + pass + + try: + for i in self.processor_dir_entries: + file = open(self.proc_processor_dir + "/" + i + "/performance") + line = file.readline() + while(len(line)!=0): + if line.find("MHz") > -1: + state = line.split(":")[0].strip().split("P")[-1] + freq = line.split(":")[1].split(",")[0].strip() + self.perf_states[freq] = state + line = file.readline() + file.close() + except IOError: + self.processor_dir_entries = [] + self.perf_states = {} #reset list --> should we throw an exception? No! + return + + + def update_processors(self): + """Read current state of processors""" + + try: + for i in self.processor_dir_entries: + file = open(self.proc_processor_dir + "/" + i + "/performance") + line = file.readline() + + while(len(line)!=0): + if line.find("*") > -1: + self.freq = line.split(":")[1].strip().split(",")[0] + line = f.readline() + file.close() + except IOError: + raise AcpiError,ERR_CONFIGURATION_CHANGED + + + def percent(self): + """Returns percentage capacity of all batteries""" + + life_capacity = 0 + design_capacity = 0 + for i,c in self.life_capacity.items(): + life_capacity = life_capacity + c + design_capacity = design_capacity + self.design_capacity[i] + + if design_capacity == 0: + return 0 + + # should we use try catch instead of the check above? + return (life_capacity * 100) / design_capacity + + + def capacity(self): + """Returns capacity of all batteries""" + capacity = 0 + for i,c in self.life_capacity.items(): + capacity = capacity + c + return capacity + + + def nb_of_batteries(self): + #returns the number of batteries + #if it returns 0, maybe ACPI is not available or + #battery driver is not loaded + return len(self.battery_dir_entries) + + + def charging_state(self): + return self.ac_line_state + + + def estimated_lifetime(self): + + # what should we return if state==charging? + # it's not clean to return a time in one case and any + # English string in another case. + # The user can check for ac-state before call this func + time = 0 + for batt,life_capacity in self.life_capacity.items(): + if self.present_rate[batt] > 0: + time = time + life_capacity/self.present_rate[batt] + return time + + + # we need funcs like max_temperature and average_temperature + def temperature(self, idx): + #print self.temperatures + #print self.thermal_dir_entries[idx] + return self.temperatures[self.thermal_dir_entries[idx]] + + + def fan_state(self, idx): + #print self.fans + return self.fans[self.fan_dir_entries[idx]] + + + def performance_states(self, idx): + return self.perf_states[idx].keys() - def frequency(self, idx): - #print self.freq - return self.freq[idx] + def frequency(self, idx): + #print self.freq + return self.freq[idx] # TODO: adapt it for multiple CPUs - def set_frequency(self, f): - #I think we should throw exceptions if someone goes wrong here - - if self.perf_states.has_key(f): - state = self.perf_states[f] - try: - pr = os.listdir("/proc/acpi/processor")[0] - except OSError: - raise AcpiError, ERR_NOT_ALLOWED - - try: - f = open("/proc/acpi/processor/"+pr+"/performance","w") - except IOError: - raise AcpiError, ERR_NOT_ALLOWED - - f.write(state) - f.close() - else: - raise AcpiError, ERR_NOT_ALLOWED + def set_frequency(self, f): + #I think we should throw exceptions if someone goes wrong here + + if self.perf_states.has_key(f): + state = self.perf_states[f] + try: + pr = os.listdir("/proc/acpi/processor")[0] + except OSError: + raise AcpiError, ERR_NOT_ALLOWED + + try: + f = open("/proc/acpi/processor/"+pr+"/performance","w") + except IOError: + raise AcpiError, ERR_NOT_ALLOWED + + f.write(state) + f.close() + else: + raise AcpiError, ERR_NOT_ALLOWED