22from builtins
import range
23from builtins
import object
27from datetime
import timedelta
29from distros.mythtv_data.orddict
import OrdDict
30from distros.mythtv_data.uuiddb
import UuidDb
35_BE = MythTV.MythBE(db=_DB)
36_SETTINGS = _DB.settings[_DB.gethostname()]
44 return (_SETTINGS.BackendServerIP
is not None)
48 for name
in [
'version',
'branch',
'protocol',
'libapi',
'qtversion']:
49 data[name] =
'Unknown'
51 executables = (
'mythutil',
'mythbackend',
'mythfrontend')
53 for executable
in executables:
54 execpath = os.path.join(MythTV.static.INSTALL_PREFIX,
57 cmd = MythTV.System(execpath)
58 res = cmd.command(
'--version')
65 names = {
'MythTV Version' :
'version',
66 'MythTV Branch' :
'branch',
67 'Network Protocol':
'protocol',
68 'Library API' :
'libapi',
69 'QT Version' :
'qtversion'}
71 for line
in res.decode().split(
'\n'):
73 prop, val = line.split(
':')
74 data[names[prop.strip()]] = val.strip()
79 def td_to_secs(self,td):
return td.days*86400 + td.seconds
87 data = {
'scheduled': rdata,
92 progs = list(MythTV.Recorded.getAllEntries())
93 upcoming = list(_BE.getUpcomingRecordings())
94 livetv = [prog
for prog
in progs
if prog.recgroup ==
'LiveTV']
95 recs = [prog
for prog
in progs
if prog.recgroup !=
'LiveTV']
96 expireable = [prog
for prog
in recs
if prog.autoexpire]
99 for dataset
in (recs, expireable, livetv, upcoming):
102 deltas = [rec.endtime-rec.starttime
for rec
in dataset]
104 deltas = [rec.recendts-rec.recstartts
for rec
in dataset]
112 rdata.count = len(recs)
113 rdata.size = sum([rec.filesize
for rec
in recs])
114 rdata.time = times[0]
116 edata.count = len(expireable)
117 edata.size = sum([rec.filesize
for rec
in expireable])
118 edata.time = times[1]
120 ldata.count = len(livetv)
121 ldata.size = sum([rec.filesize
for rec
in livetv])
122 ldata.time = times[2]
124 udata.count = len(upcoming)
125 udata.time = times[3]
127 return {
'recordings': data}
136 recs = list(MythTV.OldRecorded.getAllEntries())
143 maxage = MythTV.utility.datetime(2001,1,1,0,0)
146 if (rec.starttime < oldest.starttime)
and (rec.starttime > maxage):
148 data.rectime += self.
td_to_secs(rec.endtime - rec.starttime)
149 if rec.recstatus == -3:
150 shows.append(rec.title)
153 data.db_age = self.
td_to_secs(MythTV.utility.datetime.now() - oldest.starttime)
154 data.showcount = len(set(shows))
155 return {
'historical': data}
162 usedsources = list(set([inp.sourceid
for inp
in CaptureCard.getAllEntries()]))
163 grabbers = list(set([
VideoSource(id).xmltvgrabber
for id
in usedsources]))
164 data.sourcecount = len(usedsources)
165 data.grabbers = grabbers
170 data.timezone =
'Unknown'
173 res = _BE.backendCommand(
'QUERY_TIME_ZONE').split(
'[]:[]')
174 data.timezone = res[0]
175 data.tzoffset = int(res[1])
179 def processdirs(paths):
185 stat = os.statvfs(path)
186 bsize = stat.f_frsize
187 total += stat.f_blocks*bsize
188 free += stat.f_bfree*bsize
203 sgnames = [rec.storagegroup
for rec
in MythTV.Recorded.getAllEntries()]
204 sgnames += [rec.storagegroup
for rec
in MythTV.Record.getAllEntries()]
205 sgnames = list(set(sgnames))
208 for host
in set([_DB.gethostname(), _BE.hostname]):
209 for sgname
in sgnames:
210 for sg
in _DB.getStorageGroup(sgname, host):
212 sgs.append(sg.dirname)
213 data.rectotal, data.recfree = processdirs(sgs)
215 sgs = [sg.dirname
for sg
in _DB.getStorageGroup(
'Videos', _DB.gethostname())
if sg.local]
216 data.videototal, data.videofree = processdirs(sgs)
218 return {
'storage': data}
224 return bool(int(val))
226 def _read_file(filename):
229 with open(filename,
'r')
as f:
231 firstline = line.split()
240 alsasnd =
"/proc/asound/version"
241 osssnd =
"/dev/sndstat"
243 if os.path.exists(alsasnd):
245 version = _read_file(alsasnd)[-1].rstrip(
".")
247 elif os.path.exists(osssnd):
248 version = _read_file(osssnd)[1]
251 return snd_type , version
253 def _process_search(processname):
255 for line
in os.popen(
"ps xa"):
256 fields = line.split()
258 process = fields[4].split(
"/")
259 if processname
in process :
265 if _process_search(
"jackd")
or _process_search(
"jackdbus"):
272 if _process_search(
"pulseaudio"):
280 data.device = _SETTINGS.AudioOutputDevice
281 data.passthrudevice = _SETTINGS.PassThruOutputDevice
282 data.passthruoverride = _bool(_SETTINGS.PassThruDeviceOverride)
283 data.stereopcm = _bool(_SETTINGS.StereoPCM)
284 data.sr_override = _bool(_SETTINGS.Audio48kOverride)
285 data.maxchannels = _SETTINGS.MaxChannels
286 data.defaultupmix = _bool(_SETTINGS.AudioDefaultUpmix)
287 data.upmixtype = _SETTINGS.AudioUpmixType
289 for k,v
in ((
'AC3PassThru',
'ac3'), (
'DTSPassThru',
'dts'),
290 (
'HBRPassthru',
'hbr'), (
'EAC3PassThru',
'eac3'),
291 (
'TrueHDPassThru',
'truehd'), (
'DTSHDPassThru',
'dtshd')):
292 if _bool(_SETTINGS[k]):
295 data.volcontrol = _bool(_SETTINGS.MythControlsVolume)
296 data.mixerdevice = _SETTINGS.MixerDevice
297 data.mixercontrol = _SETTINGS.MixerControl
299 data.pulse = _pulse()
300 data.audio_sys, data.audio_sys_version = _oss_alsa()
302 return {
'audio': data}
305 class DisplayProfileGroups( MythTV.database.DBData ):
pass
306 class DisplayProfiles(
OrdDict ):
307 def __new__(cls, *args, **kwargs):
308 inst = super(DisplayProfiles, cls).__new__(cls, *args, **kwargs)
309 inst.__dict__[
'_profilegroupid'] =
None
310 inst.__dict__[
'_profileid'] =
None
311 inst.__dict__[
'_db'] =
None
314 def __init__(self, profilegroupid, profileid, db=None):
315 self.
_db = MythTV.database.DBCache(db=db)
319 cursor.execute(
"""SELECT value,data FROM displayprofiles
320 WHERE profilegroupid=%s
322 (profilegroupid, profileid))
323 for k,v
in cursor.fetchall():
327 def fromProfileGroup(cls, profilegroupid, db=None):
328 db = MythTV.database.DBCache(db=db)
330 cursor.execute(
"""SELECT DISTINCT(profileid)
332 WHERE profilegroupid=%s""",
334 for profileid
in cursor.fetchall():
335 yield cls(profilegroupid, profileid[0], db)
338 data.name = _SETTINGS.DefaultVideoPlaybackProfile
341 profilegroupid = DisplayProfileGroups((data.name, _DB.gethostname()), _DB)\
343 for profile
in DisplayProfiles.fromProfileGroup(profilegroupid, _DB):
345 d.decoder = profile.pref_decoder
346 d.deint_pri = profile.pref_deint0
347 d.deint_sec = profile.pref_deint1
348 d.renderer = profile.pref_videorenderer
349 d.filters = profile.pref_filters
350 data.profiles.append(d)
352 return {
'playbackprofile':data}
358 c.execute(
"""SELECT VERSION()""")
359 data.version = c.fetchone()[0]
361 c.execute(
"""SHOW ENGINES""")
362 data.engines = [r[0]
for r
in c.fetchall()]
364 c.execute(
"""SHOW TABLE STATUS WHERE NAME='settings'""")
365 data.usedengine = c.fetchone()[1]
368 c.execute(
"""SELECT value,data FROM settings
369 WHERE value LIKE '%SchemaVer'""")
370 for k,v
in c.fetchall():
373 return {
'database':data}
377 avg = sum(data)/len(data)
378 return avg, (sum([(d-avg)**2
for d
in data])/len(data))**.5
383 data.match_stddev = 0
385 data.place_stddev = 0
387 r = re.compile(
'Scheduled ([0-9]*) items in [0-9.]* = ([0-9.]*) match \+ ([0-9.]*) place')
391 c.execute(
"""SELECT details FROM mythlog
392 WHERE module='scheduler'
393 AND message=
'Scheduled items'""")
395 runs = [r.match(d[0]).groups() for d
in c.fetchall()]
398 return {
'scheduler': data}
400 a,s = stddev([float(r[2])
for r
in runs])
401 for i,r
in reversed(list(enumerate(runs))):
402 if abs(float(r[2]) - a) > (3*s):
407 count = [float(r[0])
for r
in runs]
408 match = [float(r[1])
for r
in runs]
409 place = [float(r[2])
for r
in runs]
411 data.count = int(sum(count)/len(count))
412 data.match_avg, data.match_stddev = stddev(match)
413 data.place_avg, data.place_stddev = stddev(place)
415 return {
'scheduler': data}
423 virtualtypes = (
'DVB',
'HDHOMERUN',
'SATIP',
'ASI')
425 for card
in CaptureCard.getAllEntries(db=_DB):
426 isvirt = (card.cardtype
in virtualtypes)
427 loc = card.videodevice+
'@'+card.hostname
428 if card.cardtype
not in cardtypes:
429 cardtypes[card.cardtype] = [loc]
432 if loc
not in cardtypes[card.cardtype]:
433 cardtypes[card.cardtype].append(loc)
438 data = {
'tuners':
dict([(k,len(v))
for k,v
in list(cardtypes.items())])}
440 data[
'vtpertuner'] = sum(virtual)/float(virtual[0])
444 smoltfile=os.path.expanduser(
'~') +
"/.mythtv/smolt.info"
447 config_file= open(smoltfile)
448 for line
in config_file:
450 if line
and line[0] !=
"#" and line[-1] !=
"=":
451 var,val = line.rsplit(
"=",1)
452 config[var.strip()] = val.strip(
"\"")
457 myth_systemrole = config[
"systemtype" ]
459 myth_systemrole =
'0'
462 mythremote = config[
"remote" ]
464 mythremote =
'unknown'
467 return myth_systemrole , mythremote
471 c.execute(
"""SELECT level,count(level) FROM logging GROUP BY level""")
472 levels = (
'EMERG',
'ALERT',
'CRIT',
'ERR',
473 'WARNING',
'NOTICE',
'INFO')
476 for level,count
in c.fetchall():
477 if level
in range(len(levels)):
478 counts[levels[level]] = count
480 for k,v
in list(counts.items()):
482 return {
'logurgency':counts}
499 self.
_data.update(func())
503 self.
_data.theme = _SETTINGS.Theme
504 if _DB.settings.NULL.country
is not None:
505 self.
_data.country = _DB.settings.NULL.country
507 self.
_data.country = _SETTINGS.Country
508 self.
_data.channel_count = len([c
for c
in MythTV.Channel.getAllEntries()
if c.visible])
509 if _DB.settings.NULL.Language
is not None:
510 self.
_data.language = _DB.settings.NULL.Language.lower()
511 elif _SETTINGS.Language
is not None:
512 self.
_data.language = _SETTINGS.Language.lower()
515 self.
_data.language =
'not set'
518 if _DB.settings.NULL.SystemUUID
is None:
519 _DB.settings.NULL.SystemUUID =
UuidDb().gen_uuid()
520 self.
_data.uuid = _DB.settings.NULL.SystemUUID
531 for k,v
in sorted(data.items()):
532 lines.append(
'- %s:\n %s \n' %(k,v))
539 lines.append(
'MythTV Features')
540 lines.append(
'-----------------------------')
547 print(
'\n'.join(lines))
556if __name__ ==
'__main__':
558 pp = pprint.PrettyPrinter()
559 pp.pprint(get_data())
def ProcessVideoProfile(self)
def dump_rst(self, lines)
def ProcessPrograms(self)
def ProcessLogUrgency(self)
def _dump_rst_section(self, lines, title, data, line_break=True)
def ProcessScheduler(self)
def ProcessHistorical(self)
def ProcessTimeZone(self)
def ProcessSmoltInfo(self)
def create_mythtv_data(gate)