import gtk
import pango
-DIFF_FILE = "/tmp/hda-analyze.diff"
-
from hda_codec import HDACodec, HDA_card_list, \
EAPDBTL_BITS, PIN_WIDGET_CONTROL_BITS, \
PIN_WIDGET_CONTROL_VREF, DIG1_BITS, GPIO_IDS, \
from hda_guilib import *
from hda_graph import create_graph
-CODEC_TREE = {}
-DIFF_TREE = {}
-
def gethttpfile(url, size=1024*1024):
from urllib import splithost
from httplib import HTTP
cnt += 1
return cnt
-def do_diff1(codec, diff1):
- from difflib import unified_diff
- diff = unified_diff(diff1.split('\n'), codec.dump().split('\n'), n=8, lineterm='')
- diff = '\n'.join(list(diff))
- if len(diff) > 0:
- diff = 'Diff for codec %i/%i (%s):\n' % (codec.card, codec.device, codec.name) + diff
- return diff
-
-def do_diff():
- diff = ''
- hw = 0
- for card in CODEC_TREE:
- for codec in CODEC_TREE[card]:
- c = CODEC_TREE[card][codec]
- if c.hwaccess:
- hw += 1
- diff += do_diff1(c, DIFF_TREE[card][codec])
- if len(diff) > 0:
- open(DIFF_FILE, "w+").write(diff + '\n')
- print "Diff was stored to: %s" % DIFF_FILE
- return (diff and hw > 0) and True or False
-
(
TITLE_COLUMN,
CARD_COLUMN,
TRACKER.add(self)
def __destroy(self, widget):
- if do_diff():
- dialog = gtk.MessageDialog(self,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
- gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
- "HDA-Analyzer: Would you like to revert\n"
- "settings for all HDA codecs?")
- response = dialog.run()
- dialog.destroy()
-
- if response == gtk.RESPONSE_YES:
- for card in CODEC_TREE:
- for codec in CODEC_TREE[card]:
- CODEC_TREE[card][codec].revert()
- print "Settings for all codecs were reverted..."
-
TRACKER.close(self)
def simple_dialog(self, type, msg):
else:
n = codec.get_node(node)
- for child in self.node_window.get_children():
+ for child in self.node_window.get_children()[:]:
self.node_window.remove(child)
+ child.destroy()
if not n:
if not codec:
for card in CODEC_TREE:
for codec in CODEC_TREE:
create_graph(CODEC_TREE[card][codec])
- HDAAnalyzer()
+ else:
+ HDAAnalyzer()
gtk.main()
return 1
self.codec = codec
self.nid = nid
self.dir = dir
+ self.cloned = False
self.reread()
def reread(self):
caps = self.codec.param_read(self.nid,
PARAMS[self.dir == HDA_OUTPUT and 'AMP_OUT_CAP' or 'AMP_IN_CAP'])
if caps == ~0 or caps == 0:
- self.ofs = None
- self.nsteps = None
- self.stepsize = None
- self.mute = None
+ if self.dir == HDA_INPUT:
+ ccaps = self.codec.amp_caps_in
+ else:
+ ccaps = self.codec.amp_caps_out
+ if ccaps:
+ ccaps.clone(self)
+ else:
+ self.ofs = self.nsteps = self.stepsize = self.mute = None
else:
self.ofs = caps & 0x7f
self.nsteps = (caps >> 8) & 0x7f
self.stepsize = (caps >> 16) & 0x7f
self.mute = (caps >> 31) & 1 and True or False
+ def clone(self, ampcaps):
+ ampcaps.ofs = self.ofs
+ ampcaps.nsteps = self.steps
+ ampcaps.stepsize = self.stepsize
+ ampcaps.mute = self.mute
+ ampcaps.cloned = True
+
+ def get_val_db(self, val):
+ if self.ofs is None:
+ return None
+ if val & 0x80:
+ return -999999
+ range = (self.stepsize + 1) * 25
+ off = -self.ofs * range
+ if val >= self.nsteps:
+ db = off + self.nsteps * range
+ if val != 0 or self.nsteps != 0:
+ print "val > nsteps? for nid 0x%02x" % self.nid, val, self.nsteps
+ else:
+ db = off + val * range
+ return db
+
+ def get_val_perc(self, val):
+ if self.ofs is None:
+ return None
+ if self.nsteps == 0:
+ return 0
+ return (val * 100) / self.nsteps
+
+ def get_val_str(self, val):
+ if self.ofs is None:
+ return "0x%02x" % val
+ else:
+ db = self.get_val_db(val & 0x7f)
+ res = val & 0x80 and "{mute-" or "{"
+ res += "0x%02x" % (val & 0x7f)
+ res += ":%02i.%idB" % (db / 100, db % 100)
+ res += ":%i%%}" % (self.get_val_perc(val & 0x7f))
+ return res
+
class HDAAmpVal:
- def __init__(self, codec, node, dir):
+ def __init__(self, codec, node, dir, caps):
self.codec = codec
self.node = node
self.dir = dir
+ if caps.ofs == None:
+ self.caps = dir == HDA_INPUT and codec.amp_caps_in or codec.amp_caps_out
+ else:
+ self.caps = caps
self.nid = node.nid
self.stereo = node.stereo
self.indices = 1
def set_mute(self, idx, mute):
val = self.vals[idx]
if mute:
+ changed = (self.vals[idx] & 0x80) == 0
self.vals[idx] |= 0x80
else:
+ changed = (self.vals[idx] & 0x80) == 0x80
self.vals[idx] &= ~0x80
self.__write_val(idx)
+ return changed
def set_value(self, idx, val):
+ changed = (self.vals[idx] & 0x7f) != val
self.vals[idx] &= ~0x7f
self.vals[idx] |= val & 0x7f
self.__write_val(idx)
+ return changed
def reread(self):
dir = self.dir == HDA_OUTPUT and (1<<15) or (0<<15)
for idx in range(len(self.vals)):
self.__write_val(idx)
+ def get_val(self, idx):
+ if self.stereo:
+ return [self.vals[idx*2], self.vals[idx*2+1]]
+ return self.vals[idx]
+
+ def get_val_db(self, idx):
+ vals = self.get_val(idx)
+ res = []
+ for val in vals:
+ res.append(self.caps.get_val_db(val))
+ return res
+
+ def get_val_str(self, idx):
+
+ def niceval(val):
+ return self.caps.get_val_str(val)
+
+ if self.stereo:
+ return '[' + niceval(self.vals[idx*2]) + ' ' + niceval(self.vals[idx*2+1]) + ']'
+ return niceval(self.vals[idx])
+
class HDARootNode:
def __init__(self, codec, _name):
return self.wtype_name() + " [0x%02x]" % self.nid
def set_active_connection(self, val):
+ changed = False
if self.active_connection != None:
+ changed = self.active_connection != val
self.codec.rw(self.nid, VERBS['SET_CONNECT_SEL'], val)
self.active_connection = self.codec.rw(self.nid, VERBS['GET_CONNECT_SEL'], 0)
+ return changed
def reread(self):
self.origin_active_connection = self.active_connection
if self.in_amp:
self.amp_caps_in = HDAAmpCaps(self.codec, self.nid, HDA_INPUT)
- self.amp_vals_in = HDAAmpVal(self.codec, self, HDA_INPUT)
+ self.amp_vals_in = HDAAmpVal(self.codec, self, HDA_INPUT, self.amp_caps_in)
if self.out_amp:
self.amp_caps_out = HDAAmpCaps(self.codec, self.nid, HDA_OUTPUT)
- self.amp_vals_out = HDAAmpVal(self.codec, self, HDA_OUTPUT)
+ self.amp_vals_out = HDAAmpVal(self.codec, self, HDA_OUTPUT, self.amp_caps_out)
if self.wtype_id == 'PIN':
jack_conns = ["Jack", "N/A", "Fixed", "Both"]
jack_types = ["Line Out", "Speaker", "HP Out", "CD", "SPDIF Out",
def eapdbtl_set_value(self, name, value):
mask = 1 << EAPDBTL_BITS[name]
+ value = value and True or False
+ changed = (self.pincap_eapdbtls & mask) and not value or value
if value:
self.pincap_eapdbtls |= mask
else:
self.pincap_eapdbtls &= ~mask
self.codec.rw(self.nid, VERBS['SET_EAPD_BTLENABLE'], self.pincap_eapdbtls)
self.reread_eapdbtl()
+ return changed
def reread_pin_widget_control(self):
pinctls = self.codec.rw(self.nid, VERBS['GET_PIN_WIDGET_CONTROL'], 0)
def pin_widget_control_set_value(self, name, value):
if name in PIN_WIDGET_CONTROL_BITS:
mask = 1 << PIN_WIDGET_CONTROL_BITS[name]
+ value = value and True or False
+ changed = (self.pinctls & mask) and not value or value
if value:
self.pinctls |= mask
else:
self.pinctls &= ~mask
elif name == 'vref' and self.pincap_vref:
idx = PIN_WIDGET_CONTROL_VREF.index(value)
+ changed = (self.pinctls & 0x07) != idx
self.pinctls &= ~0x07
self.pinctls |= idx
self.codec.rw(self.nid, VERBS['SET_PIN_WIDGET_CONTROL'], self.pinctls)
self.reread_pin_widget_control()
+ return changed
def reread_vol_knb(self):
cap = self.codec.rw(self.nid, VERBS['GET_VOLUME_KNOB_CONTROL'], 0)
def vol_knb_set_value(self, name, value):
if name == 'direct':
+ value = value and True or False
+ changed = (self.vol_knb & (1 << 7)) and not value or value
if value:
self.vol_knb |= (1 << 7)
else:
self.vol_knb &= ~(1 << 7)
elif name == 'value':
- self.vol_knb &= 0x7f
+ changed = (self.vol_knb & 0x7f) != value
+ self.vol_knb &= ~0x7f
self.vol_knb |= value
self.codec.rw(self.nid, VERBS['SET_VOLUME_KNOB_CONTROL'], self.vol_knb)
- self.reread_vol_knb()
+ self.reread_vol_knb()
+ return changed
def reread_sdi_select(self):
self.sdi_select = None
self.origin_sdi_select = sdi
def sdi_select_set_value(self, value):
+ changed = False
if self.sdi_select != None:
+ changed = (self.sdi_select & 0x0f) != value
self.sdi_select = value & 0x0f
self.codec.rw(self.nid, VERBS['SET_SDI_SELECT'], self.sdi_select)
self.reread_sdi_select()
+ return changed
def reread_dig1(self):
self.dig1 = []
def dig1_set_value(self, name, value):
if name == 'category':
+ changed = ((self.digi1 >> 8) & 0x7f) != (value & 0x7f)
self.digi1 &= ~0x7f00
self.digi1 |= (value & 0x7f) << 8
self.codec.rw(self.nid, VERBS['SET_DIGI_CONVERT_2'], (self.digi1 >> 8) & 0xff)
else:
mask = 1 << DIG1_BITS[name]
+ value = value and True or False
+ changed = (self.digi1 & mask) and not value or value
if value:
self.digi1 |= mask
else:
self.digi1 &= ~mask
self.codec.rw(self.nid, VERBS['SET_DIGI_CONVERT_1'], self.digi1 & 0xff)
self.reread_dig1()
+ return changed
def revert(self):
if self.origin_active_connection != None:
def get_controls(self):
return self.codec.get_controls(self.nid)
+ def get_conn_amp_vals_str(self, dst_node):
+ # return amp values for connection between this and dst_node
+ res = []
+ if self.out_amp:
+ res.append(self.amp_vals_out.get_val_str(0))
+ else:
+ res.append(None)
+ if dst_node.in_amp:
+ idx = 0
+ if dst_node.amp_vals_in.indices == dst_node.connections:
+ if not self.nid in dst_node.connections:
+ raise ValueError, "nid 0x%02x is not connected to nid 0x%02x (%s, %s)" % (dst_node.nid, self.nid, repr(self.connections), repr(dst_node.connections))
+ idx = dst_node.connections.index(self.nid)
+ res.append(dst_node.amp_vals_in.get_val_str(idx))
+ else:
+ res.append(None)
+ return res
+
+ def is_conn_active(self, dst_node):
+ # disabled route for PIN widgets
+ if self.wtype_id == 'PIN' and not 'IN' in self.pinctl:
+ return None
+ if dst_node.wtype_id == 'PIN' and not 'OUT' in dst_node.pinctl:
+ return None
+ res = [None, None]
+ if self.out_amp:
+ vals = self.amp_vals_out.get_val_db(0)
+ for idx in range(len(vals)):
+ if res[idx]:
+ res[idx] += vals[idx]
+ else:
+ res[idx] = vals[idx]
+ if dst_node.in_amp:
+ idx = 0
+ if dst_node.amp_vals_in.indices == dst_node.connections:
+ if not self.nid in dst_node.connections:
+ raise ValueError, "nid 0x%02x is not connected to nid 0x%02x (%s, %s)" % (dst_node.nid, self.nid, repr(self.connections), repr(dst_node.connections))
+ idx = dst_node.connections.index(self.nid)
+ vals = dst_node.amp_vals_in.get_val_db(idx)
+ for idx in range(len(vals)):
+ if res[idx]:
+ res[idx] += vals[idx]
+ else:
+ res[idx] = vals[idx]
+ if res[0] is None and res[1] is None:
+ return True
+ for r in res:
+ if r >= -1200:
+ return True
+ return False
+
class HDAGPIO:
def __init__(self, codec, nid):
else:
self.val[name] &= ~(1 << bit)
if old == self.test(name, bit):
- return
+ return False
self.write(name)
+ return True
def revert(self):
for i in GPIO_IDS:
-#!/usr/bin/env python
+4#!/usr/bin/env python
#
# Copyright (c) 2008-2010 by Jaroslav Kysela <perex@perex.cz>
#
self.dst_routes = []
self.win = None
+ def longdesc(self):
+ return "0x%02x" % self.node.nid
+
def expose(self, cr, event, graph):
width = self.myarea[2]
self.highlight = False
self.marked = False
- def shortdest(self):
+ def shortdesc(self):
return "0x%02x->0x%02x" % (self.src.node.nid, self.dst.node.nid)
def longdesc(self):
return "%s 0x%02x -> %s 0x%02x" % (src.wtype_id.replace('_', '-'),
src.nid, dst.wtype_id.replace('_', '-'), dst.nid)
+ def statusdesc(self):
+
+ def niceprint(prefix, val):
+ if val is None:
+ return prefix
+ return ' ' + prefix + ' ' + val
+
+ src = self.src.node
+ dst = self.dst.node
+ vals = src.get_conn_amp_vals_str(dst)
+ src = "%s 0x%02x" % (src.wtype_id.replace('_', '-'), src.nid)
+ dst = "%s 0x%02x" % (dst.wtype_id.replace('_', '-'), dst.nid)
+ res = niceprint("SRC " + src, vals[0]) + ' -> ' + \
+ niceprint("DST " + dst, vals[1])
+ return res
+
def expose(self, cr, event):
width = self.src.myarea[2]
height = self.src.myarea[3]
cr.set_line_width(1.5)
cr.set_source_rgb(1, 0, 0)
else:
- cr.set_line_width(0.5)
- cr.set_source_rgb(0, 0, 0)
- if len(line) > 4:
- cr.set_source_rgb(0, 1, 0)
+ inactive = self.src.node.is_conn_active(self.dst.node)
+ if inactive is None:
+ cr.set_line_width(0.35)
+ cr.set_source_rgb(0, 0, 0)
+ elif inactive is False:
+ cr.set_line_width(0.35)
+ cr.set_source_rgb(0, 0, 1)
+ else:
+ cr.set_line_width(1.5)
+ cr.set_source_rgb(0, 0, 1)
cr.move_to(line[0], line[1])
cr.line_to(line[2], line[3])
cr.stroke()
x1, y1, x2, y2 = line
if x1 > x2 or y1 > y2:
x2, y2, x1, y1 = line
- if x1 == x2 and abs(x1 - x) < 2:
+ if x1 == x2 and abs(x1 - x) < 3:
if y1 <= y and y2 >= y:
return True
- elif y1 == y2 and abs(y1 - y) < 2:
+ elif y1 == y2 and abs(y1 - y) < 3:
if x1 <= x and x2 >= x:
return True
class CodecGraphLayout(gtk.Layout):
- def __init__(self, adj1, adj2, codec, mytitle):
+ def __init__(self, adj1, adj2, codec, mytitle, statusbar):
gtk.Layout.__init__(self, adj1, adj2)
self.set_events(0)
self.add_events(gtk.gdk.EXPOSURE_MASK | gtk.gdk.POINTER_MOTION_MASK |
- gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK)
+ gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK |
+ gtk.gdk.LEAVE_NOTIFY_MASK)
self.expose_handler = self.connect("expose-event", self.expose)
self.click_handler = self.connect("button-press-event", self.button_click)
self.release_handler = self.connect("button-release-event", self.button_release)
self.motion_handler = self.connect("motion-notify-event", self.mouse_move)
+ self.mouse_leave_handler = self.connect("leave-notify-event", self.mouse_leave)
self.popup_win = None
self.popup = None
+ self.statusbar = statusbar
self.codec = codec
self.mytitle = mytitle
self.graph = codec.graph(dump=False)
self.startnode = None
self.endnode = None
+
+ self.changed_handler = HDA_SIGNAL.connect("hda-node-changed", self.hda_node_changed)
+
ok = False
for extra in [150, 200, 300]:
if self.build(extra):
if self.popup_win:
self.popup_win.destroy()
- def build(self, extra=50):
+ def __build(self, extra=50):
self.nodes = []
self.routes = []
maxconns = 0
sx = len(self.graph[0])*(nodesize+extra)+extra
sy = len(self.graph)*(nodesize+extra)+extra
self.set_size(sx, sy)
+ total = 0
+ for node in self.nodes:
+ if not node.node.connections:
+ continue
+ for conn in node.node.connections:
+ for node1 in self.nodes:
+ if node1.node.nid == conn:
+ total += 1
+ break
+ total *= 2
+ total += 1
+ position = 0
for node in self.nodes:
if not node.node.connections:
continue
if node1.node.nid == conn:
r = Route(self.codec, node1, node, self.routes, self.nodes)
self.routes.append(r)
+ position += 1
+ self.pdialog.set_fraction(float(position) / total)
break
res = True
for route in self.routes:
if not route.finish(self.routes, self.nodes):
res = False
break
+ position += 1
+ self.pdialog.set_fraction(float(position) / total)
if not res:
return
# final step - optimize drawings
if not size:
break
sx -= size
+ position += 1
+ self.pdialog.set_fraction(float(position) / total)
while 1:
size = self.compressy(sy)
if not size:
self.set_size(sx, sy)
return res
+ def build(self, extra=50):
+ self.pdialog = SimpleProgressDialog("Rendering routes")
+ self.pdialog.show_all()
+ res = self.__build(extra)
+ self.pdialog.destroy()
+ self.pdialog = None
+ return res
+
def expose(self, widget, event):
if not self.flags() & gtk.REALIZED:
return
return size
return None
+ def hda_node_changed(self, obj, widget, node):
+ if widget != self:
+ self.queue_draw()
+
def find_node(self, event):
for node in self.nodes:
what = node.in_area(event.x, event.y)
def show_popup(self, event):
screen_width = gtk.gdk.screen_width()
- screeen_height = gtk.gdk.screen_height()
+ screen_height = gtk.gdk.screen_height()
if self.popup_win:
self.popup_win.destroy()
label.modify_font(get_fixed_font())
label.set_text(self.popup)
self.popup_win.add(label)
+ self.popup_win.move(screen_width + 10, screen_height + 10)
+ self.popup_win.show_all()
popup_width, popup_height = self.popup_win.get_size()
- rootwin = self.get_screen().get_root_window()
- x, y, mods = rootwin.get_pointer()
+ #rootwin = self.get_screen().get_root_window()
+ #x, y, mods = rootwin.get_pointer()
- pos_x = x - popup_width/2
+ pos_x = screen_width - popup_width
if pos_x < 0:
pos_x = 0
- elif pos_x + popup_width > screen_width:
- pos_x = screen_width - popup_width
-
- pos_y = y + 3
- if pos_y + popup_height > screeen_height:
- pos_y = event.y - 3 - popup_height
+ pos_y = screen_height - popup_height
+ if pos_y < 0:
+ pox_y = 0
self.popup_win.move(int(pos_x), int(pos_y))
- self.popup_win.show_all()
+ #self.popup_win.show_all()
def mouse_move(self, widget, event):
oldpopup = self.popup
route.highlight = False
for node in self.nodes:
if node.mouse_move(event.x, event.y, self):
+ self.statusbar.pop(1)
+ self.statusbar.push(1, node.longdesc())
found = redraw = True
break
if not found:
for route in self.routes:
if route.mouse_move(event.x, event.y, self):
+ self.statusbar.pop(1)
+ self.statusbar.push(1, route.statusdesc())
found = redraw = True
break
+ if not found:
+ self.statusbar.pop(1)
if redraw:
self.queue_draw()
if self.popup:
else:
if self.popup_win:
self.popup_win.destroy()
+ self.popup_win = None
+
+ def mouse_leave(self, widget, data=None):
+ for route in self.routes:
+ if route.highlight:
+ redraw = True
+ route.highlight = False
+ if self.popup_win:
+ self.popup_win.destroy()
+ self.popup_win = None
def mark_it(self, widget, node, what, enable):
if what == "start":
self.set_title(self.__class__.__name__ + ' ' + self.codec.name)
self.set_border_width(0)
- table = gtk.Table(2, 2, False)
+ table = gtk.Table(2, 3, False)
self.add(table)
- self.layout = CodecGraphLayout(None, None, codec, self.get_title())
+ statusbar = gtk.Statusbar()
+ self.layout = CodecGraphLayout(None, None, codec, self.get_title(), statusbar)
table.attach(self.layout, 0, 1, 0, 1, gtk.FILL|gtk.EXPAND,
gtk.FILL|gtk.EXPAND, 0, 0)
vScrollbar = gtk.VScrollbar(None)
vScrollbar.set_adjustment(vAdjust)
hAdjust = self.layout.get_hadjustment()
hScrollbar.set_adjustment(hAdjust)
+ table.attach(statusbar, 0, 2, 2, 3, gtk.FILL|gtk.SHRINK,
+ gtk.FILL|gtk.SHRINK, 0, 0)
self.show_all()
GRAPH_WINDOWS[codec] = self
TRACKER.add(self)
PIN_WIDGET_CONTROL_VREF, DIG1_BITS, GPIO_IDS, \
HDA_INPUT, HDA_OUTPUT
+DIFF_FILE = "/tmp/hda-analyze.diff"
+
+CODEC_TREE = {}
+DIFF_TREE = {}
+
def get_fixed_font():
return pango.FontDescription("Misc Fixed,Courier Bold 9")
+class HDASignal(gobject.GObject):
+
+ def __init__(self):
+ self.__gobject_init__()
+
+gobject.signal_new("hda-codec-changed", HDASignal,
+ gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_PYOBJECT,gobject.TYPE_PYOBJECT))
+gobject.signal_new("hda-node-changed", HDASignal,
+ gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_PYOBJECT,gobject.TYPE_PYOBJECT))
+
+HDA_SIGNAL = HDASignal()
+
+def do_diff1(codec, diff1):
+ from difflib import unified_diff
+ diff = unified_diff(diff1.split('\n'), codec.dump().split('\n'), n=8, lineterm='')
+ diff = '\n'.join(list(diff))
+ if len(diff) > 0:
+ diff = 'Diff for codec %i/%i (%s):\n' % (codec.card, codec.device, codec.name) + diff
+ return diff
+
+def do_diff():
+ diff = ''
+ hw = 0
+ for card in CODEC_TREE:
+ for codec in CODEC_TREE[card]:
+ c = CODEC_TREE[card][codec]
+ if c.hwaccess:
+ hw += 1
+ diff += do_diff1(c, DIFF_TREE[card][codec])
+ if len(diff) > 0:
+ open(DIFF_FILE, "w+").write(diff + '\n')
+ print "Diff was stored to: %s" % DIFF_FILE
+ return (diff and hw > 0) and True or False
+
class NodeGui(gtk.ScrolledWindow):
def __init__(self, card=None, codec=None, node=None, doframe=False):
gtk.ScrolledWindow.__init__(self)
self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- self.set_shadow_type(gtk.SHADOW_IN)
+ self.set_shadow_type(gtk.SHADOW_IN)
+ self.read_all = self.__read_all_none
+ self.node = None
+ self.codec = None
if card and not codec and not node:
self.__build_card(card, doframe)
elif codec and not card and not node:
self.__build_codec(codec, doframe)
elif node and not card and not codec:
self.__build_node(node, doframe)
+ self.connect("destroy", self.__destroy)
+ self.codec_changed = HDA_SIGNAL.connect("hda-codec-changed", self.hda_codec_changed)
+ self.node_changed = HDA_SIGNAL.connect("hda-node-changed", self.hda_node_changed)
+ self.read_all()
self.show_all()
+ def __destroy(self, widget):
+ HDA_SIGNAL.handler_disconnect(self.codec_changed)
+ HDA_SIGNAL.handler_disconnect(self.node_changed)
+
+ def __read_all_none(self):
+ pass
+
+ def hda_codec_changed(self, obj, widget, codec):
+ if widget != self:
+ if self.read_all and self.codec == codec:
+ self.read_all()
+
+ def hda_node_changed(self, obj, widget, node):
+ if widget != self:
+ if self.read_all and self.node == node:
+ self.read_all()
+
def __create_text(self, callback):
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
def __node_connection_toggled(self, widget, row, data):
model, node = data
if not model[row][0]:
- node.set_active_connection(int(row))
+ if node.set_active_connection(int(row)):
+ HDA_SIGNAL.emit("hda-node-changed", self, node)
for r in model:
r[0] = False
idx = 0
model.set(iter, 0, node.active_connection == idx,
1, node1.name())
idx += 1
+ self.connection_model = model
treeview = gtk.TreeView(model)
treeview.set_rules_hint(True)
treeview.get_selection().set_mode(gtk.SELECTION_SINGLE)
treeview.set_size_request(300, 30 + len(node.connections) * 25)
renderer = gtk.CellRendererToggle()
renderer.set_radio(True)
- if node.active_connection != None:
+ if not node.active_connection is None:
renderer.connect("toggled", self.__node_connection_toggled, (model, node))
column = gtk.TreeViewColumn("Active", renderer, active=0)
treeview.append_column(column)
renderer = gtk.CellRendererText()
- column = gtk.TreeViewColumn("Destination Node", renderer, text=1, editable=False)
+ column = gtk.TreeViewColumn("Source Node", renderer, text=1, editable=False)
treeview.append_column(column)
sw.add(treeview)
return frame
def __amp_mute_toggled(self, button, data):
caps, vals, idx = data
val = button.get_active()
- vals.set_mute(idx, val)
+ if vals.set_mute(idx, val):
+ HDA_SIGNAL.emit("hda-node-changed", self, vals.node)
button.set_active(vals.vals[idx] & 0x80)
def __amp_value_changed(self, adj, data):
caps, vals, idx = data
val = int(adj.get_value())
- vals.set_value(idx, val)
+ if vals.set_value(idx, val):
+ HDA_SIGNAL.emit("hda-node-changed", self, vals.node)
adj.set_value(vals.vals[idx] & 0x7f)
def __build_amps(self, node):
def build_caps(title, caps, vals):
- if caps and caps.ofs is None:
- caps = caps.dir == HDA_INPUT and \
- node.codec.amp_caps_in or node.codec.amp_caps_out
+ if caps and caps.cloned:
title += ' (Global)'
frame = gtk.Frame(title)
frame.set_border_width(4)
idx = 0
frame1 = None
vbox1 = None
+ self.amp_checkbuttons[caps.dir] = []
+ self.amp_adjs[caps.dir] = []
for val in vals.vals:
if vals.stereo and idx & 1 == 0:
frame1 = gtk.Frame()
hbox.pack_start(label, False, False)
if caps.mute:
checkbutton = gtk.CheckButton('Mute')
- checkbutton.set_active(val & 0x80 and True or False)
checkbutton.connect("toggled", self.__amp_mute_toggled, (caps, vals, idx))
+ self.amp_checkbuttons[caps.dir].append(checkbutton)
hbox.pack_start(checkbutton, False, False)
+ else:
+ self.amp_checkbuttons[caps.dir].append(None)
if caps.stepsize > 0:
adj = gtk.Adjustment((val & 0x7f) % (caps.nsteps+1), 0.0, caps.nsteps+1, 1.0, 1.0, 1.0)
scale = gtk.HScale(adj)
scale.set_digits(0)
scale.set_value_pos(gtk.POS_RIGHT)
adj.connect("value_changed", self.__amp_value_changed, (caps, vals, idx))
+ self.amp_adjs[caps.dir].append(adj)
hbox.pack_start(scale, True, True)
+ else:
+ self.amp_adjs[caps.dir].append(None)
if vbox1:
vbox1.pack_start(hbox, False, False)
else:
frame.add(vbox)
return frame
+ self.amp_checkbuttons = {}
+ self.amp_adjs = {}
hbox = gtk.HBox(False, 0)
c = build_caps('Input Amplifier',
node.in_amp and node.amp_caps_in or None,
def __pincap_eapdbtl_toggled(self, button, data):
node, name = data
- node.eapdbtl_set_value(name, button.get_active())
+ if node.eapdbtl_set_value(name, button.get_active()):
+ HDA_SIGNAL.emit("hda-node-changed", self, node)
button.set_active(name in node.pincap_eapdbtl)
def __pinctls_toggled(self, button, data):
node, name = data
- node.pin_widget_control_set_value(name, button.get_active())
+ if node.pin_widget_control_set_value(name, button.get_active()):
+ HDA_SIGNAL.emit("hda-node-changed", self, node)
button.set_active(name in node.pinctl)
def __pinctls_vref_change(self, combobox, node):
for name in PIN_WIDGET_CONTROL_VREF:
if not name: continue
if idx1 == index:
- node.pin_widget_control_set_value('vref', name)
+ if node.pin_widget_control_set_value('vref', name):
+ HDA_SIGNAL.emit("hda-node-changed", self, node)
break
idx1 += 1
idx = idx1 = 0
frame = gtk.Frame('EAPD')
frame.set_border_width(4)
vbox1 = gtk.VBox(False, 0)
+ self.pincap_eapdbtls_checkbuttons = []
for name in EAPDBTL_BITS:
checkbutton = gtk.CheckButton(name)
- checkbutton.set_active(node.pincap_eapdbtls & (1 << EAPDBTL_BITS[name]))
checkbutton.connect("toggled", self.__pincap_eapdbtl_toggled, (node, name))
+ self.pincap_eapdbtls_checkbuttons.append(checkbutton)
vbox1.pack_start(checkbutton, False, False)
frame.add(vbox1)
vbox.pack_start(frame, False, False)
frame = gtk.Frame('Widget Control')
frame.set_border_width(4)
vbox1 = gtk.VBox(False, 0)
+ self.pin_checkbuttons = []
for name in PIN_WIDGET_CONTROL_BITS:
checkbutton = gtk.CheckButton(name)
- checkbutton.set_active(node.pinctls & (1 << PIN_WIDGET_CONTROL_BITS[name]))
checkbutton.connect("toggled", self.__pinctls_toggled, (node, name))
+ self.pin_checkbuttons.append(checkbutton)
vbox1.pack_start(checkbutton, False, False)
if node.pincap_vref:
combobox = gtk.combo_box_new_text()
- idx = idx1 = active = 0
for name in PIN_WIDGET_CONTROL_VREF:
- if name == node.pinctl_vref: active = idx1
if name:
combobox.append_text(name)
- idx1 += 1
- idx += 1
- combobox.set_active(active)
combobox.connect("changed", self.__pinctls_vref_change, node)
+ self.pincap_vref_combobox = combobox
hbox1 = gtk.HBox(False, 0)
label = gtk.Label('VREF')
hbox1.pack_start(label, False, False)
def __sdi_select_changed(self, adj, node):
val = int(adj.get_value())
- node.sdi_select_set_value(val)
+ if node.sdi_select_set_value(val):
+ HDA_SIGNAL.emit("hda-node-changed", self, node)
adj.set_value(node.sdi_select)
def __dig1_toggled(self, button, data):
node, name = data
val = button.get_active()
- node.dig1_set_value(name, val)
+ if node.dig1_set_value(name, val):
+ HDA_SIGNAL.emit("hda-node-changed", self, node)
button.set_active(name in node.dig1)
def __dig1_category_activate(self, entry, node):
except:
print "Unknown category value '%s'" % val
return
- node.dig1_set_value('category', val)
+ if node.dig1_set_value('category', val):
+ HDA_SIGNAL.emit("hda-node-changed", self, node)
entry.set_text("0x%02x" % node.dig1_category)
def __build_aud(self, node):
hbox1 = gtk.HBox(False, 0)
frame = gtk.Frame('SDI Select')
adj = gtk.Adjustment(node.sdi_select, 0.0, 16.0, 1.0, 1.0, 1.0)
+ self.sdi_select_adj = adj
scale = gtk.HScale(adj)
scale.set_digits(0)
scale.set_value_pos(gtk.POS_LEFT)
hbox1 = gtk.HBox(False, 0)
frame = gtk.Frame('Digital Converter')
vbox1 = gtk.VBox(False, 0)
+ self.digital_checkbuttons = []
for name in DIG1_BITS:
checkbutton = gtk.CheckButton(name)
- checkbutton.set_active(node.digi1 & (1 << DIG1_BITS[name]))
checkbutton.connect("toggled", self.__dig1_toggled, (node, name))
+ self.digital_checkbuttons.append(checkbutton)
vbox1.pack_start(checkbutton, False, False)
frame.add(vbox1)
hbox1.pack_start(frame)
frame.add(self.__new_text_view(text=str))
return frame
+ def __read_all_node(self):
+ node = self.node
+ if node.wtype_id in ['AUD_IN', 'AUD_OUT']:
+ if not node.sdi_select is None:
+ self.sdi_select_adj.set_value(node.sdi_select)
+ if node.digital:
+ idx = 0
+ for name in DIG1_BITS:
+ checkbutton = self.digital_checkbuttons[idx]
+ checkbutton.set_active(node.digi1 & (1 << DIG1_BITS[name]))
+ idx += 1
+ elif node.wtype_id == 'PIN':
+ if 'EAPD' in node.pincap:
+ idx = 0
+ for name in EAPDBTL_BITS:
+ checkbutton = self.pincap_eapdbtls_checkbuttons[idx]
+ checkbutton.set_active(node.pincap_eapdbtls & (1 << EAPDBTL_BITS[name]))
+ idx += 1
+ idx = 0
+ for name in PIN_WIDGET_CONTROL_BITS:
+ checkbutton = self.pin_checkbuttons[idx]
+ checkbutton.set_active(node.pinctls & (1 << PIN_WIDGET_CONTROL_BITS[name]))
+ idx += 1
+ idx = active = 0
+ for name in PIN_WIDGET_CONTROL_VREF:
+ if name == node.pinctl_vref: active = idx
+ if name: idx += 1
+ if node.pincap_vref:
+ self.pincap_vref_combobox.set_active(active)
+ a = []
+ if node.in_amp:
+ a.append((HDA_INPUT, node.amp_caps_in, node.amp_vals_in))
+ if node.out_amp:
+ a.append((HDA_OUTPUT, node.amp_caps_out, node.amp_vals_out))
+ for dir, caps, vals in a:
+ for idx in range(len(vals.vals)):
+ val = vals.vals[idx]
+ checkbutton = self.amp_checkbuttons[dir][idx]
+ if checkbutton:
+ checkbutton.set_active(val & 0x80 and True or False)
+ adj = self.amp_adjs[dir][idx]
+ if adj:
+ adj.set_value((val & 0x7f) % (caps.nsteps+1))
+ idx += 1
+ if hasattr(self, 'connection_model'):
+ for r in self.connection_model:
+ r[0] = False
+ idx = 0
+ for r in self.connection_model:
+ r[0] = node.active_connection == idx
+ idx += 1
+
def __build_node(self, node, doframe=False):
+ self.node = node
self.mytitle = node.name()
if doframe:
mframe = gtk.Frame(self.mytitle)
mframe.add(vbox)
self.add_with_viewport(mframe)
+ self.read_all = self.__read_all_node
+
def __build_codec_info(self, codec):
vbox = gtk.VBox(False, 0)
return hbox
def __gpio_toggled(self, button, (codec, id, idx)):
- codec.gpio.set(id, idx, button.get_active())
+ if codec.gpio.set(id, idx, button.get_active()):
+ HDA_SIGNAL.emit("hda-codec-changed", self, codec)
button.set_active(codec.gpio.test(id, idx))
def __build_codec_gpio(self, codec):
str += 'Wake: %s\n' % (codec.gpio_wake and "True" or "False")
hbox.pack_start(self.__new_text_view(text=str), False, False)
frame.add(hbox)
+ self.gpio_checkbuttons = []
for id in GPIO_IDS:
id1 = id == 'direction' and 'out-dir' or id
frame1 = gtk.Frame(id1)
frame1.set_border_width(4)
vbox1 = gtk.VBox(False, 0)
+ self.gpio_checkbuttons.append([])
for i in range(codec.gpio_max):
- checkbutton = gtk.CheckButton('[%d]' % i)
- checkbutton.set_active(codec.gpio.test(id, i))
+ checkbutton = checkbutton = gtk.CheckButton('[%d]' % i)
checkbutton.connect("toggled", self.__gpio_toggled, (codec, id, i))
+ self.gpio_checkbuttons[-1].append(checkbutton)
vbox1.pack_start(checkbutton, False, False)
frame1.add(vbox1)
hbox.pack_start(frame1, False, False)
return frame
+ def __read_all_codec(self):
+ idx = 0
+ for id in GPIO_IDS:
+ for i in range(self.codec.gpio_max):
+ self.gpio_checkbuttons[idx][i].set_active(self.codec.gpio.test(id, i))
+ idx += 1
+
def __build_codec(self, codec, doframe=False):
+ self.codec = codec
self.mytitle = codec.name
if doframe:
mframe = gtk.Frame(self.mytitle)
vbox.pack_start(self.__build_codec_gpio(codec), False, False)
mframe.add(vbox)
self.add_with_viewport(mframe)
+ self.read_all = self.__read_all_codec
def __build_card_info(self, card):
str = 'Card: %s\n' % card.card
mframe.add(vbox)
self.add_with_viewport(mframe)
+class SimpleProgressDialog(gtk.Dialog):
+
+ def __init__(self, title):
+ gtk.Dialog.__init__(self, title, None, gtk.DIALOG_MODAL, None)
+ self.set_deletable(False)
+
+ box = self.get_child()
+
+ box.pack_start(gtk.Label(), False, False, 0)
+ self.progressbar = gtk.ProgressBar()
+ box.pack_start(self.progressbar, False, False, 0)
+
+ def set_fraction(self, fraction):
+ self.progressbar.set_fraction(fraction)
+ while gtk.events_pending():
+ gtk.main_iteration_do(False)
+
class TrackWindows:
def __init__(self):
if win in self.windows:
self.windows.remove(win)
if not self.windows:
+ self.do_diff(win)
gtk.main_quit()
+ def do_diff(self, widget):
+ if do_diff():
+ dialog = gtk.MessageDialog(widget,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
+ "HDA-Analyzer: Would you like to revert\n"
+ "settings for all HDA codecs?")
+ response = dialog.run()
+ dialog.destroy()
+
+ if response == gtk.RESPONSE_YES:
+ for card in CODEC_TREE:
+ for codec in CODEC_TREE[card]:
+ CODEC_TREE[card][codec].revert()
+ print "Settings for all codecs were reverted..."
+
TRACKER = TrackWindows()