[chirp_devel] [PATCH] [RFC] Add bitwise browser when developer options are enabled
# HG changeset patch # User Dan Smith dsmith@danplanet.com # Date 1362327994 28800 # Node ID d7da2968488769d7e32321b0e03d7201662dc079 # Parent 49de55116a55bc5b35a5391aa14b3e68d182e4c7 [RFC] Add bitwise browser when developer options are enabled
This is something I've been wanting to do for a while. It provides a graphical way to explore the memory object of a clone-mode radio. It is roughly equivalent to doing "show raw memory" on a channel, but lets you do the same for other areas, such as the settings, limits, etc.
I want to do more things like let you diff other areas, and perhaps display the contents in a more formal way so that they can be tweaked arbitrarily, but that will come later. I'm submitting this here for comments and folks to try it out. Note that it requires dev tools to be enabled before opening an image.
Thoughts? Comments?
diff -r 49de55116a55 -r d7da29684887 chirp/bitwise.py --- a/chirp/bitwise.py Thu Feb 28 18:13:55 2013 -0800 +++ b/chirp/bitwise.py Sun Mar 03 08:26:34 2013 -0800 @@ -188,7 +188,7 @@
def __str__(self): if isinstance(self.__items[0], charDataElement): - return "".join([x.get_value() for x in self.__items]) + return repr("".join([x.get_value() for x in self.__items]))[1:-1] else: return str(self.__items)
@@ -612,6 +612,13 @@ raise ValueError("Struct size mismatch during set_raw()") self._data[self._offset] = buffer
+ def __iter__(self): + for item in self._generators.values(): + yield item + + def items(self): + return self._generators.items() + class Processor:
_types = { diff -r 49de55116a55 -r d7da29684887 chirpui/editorset.py --- a/chirpui/editorset.py Thu Feb 28 18:13:55 2013 -0800 +++ b/chirpui/editorset.py Sun Mar 03 08:26:34 2013 -0800 @@ -19,7 +19,7 @@
from chirp import chirp_common, directory, generic_csv, generic_xml from chirpui import memedit, dstaredit, bankedit, common, importdialog -from chirpui import inputdialog, reporting, settingsedit +from chirpui import inputdialog, reporting, settingsedit, radiobrowser, config
class EditorSet(gtk.VBox): __gsignals__ = { @@ -65,6 +65,7 @@ "bank_names" : None, "bank_members" : None, "settings" : None, + "browser" : None, }
if isinstance(self.radio, chirp_common.IcomDstarSupport): @@ -88,6 +89,11 @@ if rf.has_settings: self.editors["settings"] = settingsedit.SettingsEditor(self.rthread)
+ conf = config.get() + if (hasattr(self.rthread.radio, '_memobj') and + conf.get_bool("developer", "state")): + self.editors["browser"] = radiobrowser.RadioBrowser(self.rthread) + lab = gtk.Label(_("Memories")) self.tabs.append_page(self.editors["memedit"].root, lab) self.editors["memedit"].root.show() @@ -115,6 +121,10 @@ self.tabs.append_page(self.editors["settings"].root, lab) self.editors["settings"].root.show()
+ if self.editors["browser"]: + lab = gtk.Label(_("Browser")) + self.tabs.append_page(self.editors["browser"].root, lab) + self.pack_start(self.tabs) self.tabs.show()
diff -r 49de55116a55 -r d7da29684887 chirpui/radiobrowser.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chirpui/radiobrowser.py Sun Mar 03 08:26:34 2013 -0800 @@ -0,0 +1,154 @@ +import gtk +import gobject +import pango +import re +import os + +from chirp import bitwise +from chirpui import common + +def do_insert_line_with_tags(b, line): + def i(text, *tags): + b.insert_with_tags_by_name(b.get_end_iter(), text, *tags) + + def ident(name): + if "unknown" in name: + i(name, 'grey', 'bold') + else: + i(name, 'bold') + + def nonzero(value): + i(value, 'red', 'bold') + + def foo(value): + i(value, 'blue', 'bold') + + m = re.match("^( *)([A-z0-9_]+: )(0x[A-F0-9]+) ((.*))$", line) + if m: + i(m.group(1)) + ident(m.group(2)) + if m.group(3) == '0x00': + i(m.group(3)) + else: + nonzero(m.group(3)) + i(' (') + for char in m.group(4): + if char == '1': + nonzero(char) + else: + i(char) + i(')') + return + + m = re.match("^( *)([A-z0-9_]+: )(.*)$", line) + if m: + i(m.group(1)) + ident(m.group(2)) + i(m.group(3)) + return + + m = re.match("^(.*} )([A-z0-9_]+)( ()([0-9]+)( bytes at )(0x[A-F0-9]+)", + line) + if m: + i(m.group(1)) + ident(m.group(2)) + i(m.group(3)) + foo(m.group(4)) + i(m.group(5)) + foo(m.group(6)) + i(")") + return + + i(line) + +def do_insert_with_tags(buf, text): + buf.set_text('') + lines = text.split(os.linesep) + for line in lines: + do_insert_line_with_tags(buf, line) + buf.insert_with_tags_by_name(buf.get_end_iter(), os.linesep) + +class RadioBrowser(common.Editor): + def _build_ui(self): + self._display = gtk.TextView() + + fontdesc = pango.FontDescription("Courier 10") + self._display.modify_font(fontdesc) + self._display.set_editable(False) + tt = self._display.get_buffer().get_tag_table() + for color in ["red", "green", "blue", "grey"]: + tag = gtk.TextTag(color) + tag.set_property("foreground", color) + tt.add(tag) + tag = gtk.TextTag("bold") + tag.set_property("weight", pango.WEIGHT_BOLD) + tt.add(tag) + + self._store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) + self._tree = gtk.TreeView(self._store) + + rend = gtk.CellRendererText() + tvc = gtk.TreeViewColumn('Element', rend, text=0) + self._tree.append_column(tvc) + self._tree.connect('button_press_event', self._tree_click) + self._tree.set_size_request(200, -1) + + self.root = gtk.HBox(False, 3) + sw = gtk.ScrolledWindow() + sw.add(self._tree) + sw.show() + self.root.pack_start(sw, 0, 0, 0) + sw = gtk.ScrolledWindow() + sw.add(self._display) + sw.show() + self.root.pack_start(sw, 1, 1, 1) + self._tree.show() + self._display.show() + self.root.show() + + def _fill(self, name, obj, parent=None): + iter = self._store.append(parent, (name, obj)) + + if isinstance(obj, bitwise.structDataElement): + for name, item in obj.items(): + if isinstance(item, bitwise.structDataElement): + self._fill(name, item, iter) + elif isinstance(item, bitwise.arrayDataElement): + self._fill("%s[%i]" % (name, len(item)), item, iter) + elif isinstance(obj, bitwise.arrayDataElement): + i = 0 + for item in obj: + self._fill("%s[%i]" % (name, i), item, iter) + i += 1 + + def _tree_click(self, view, event): + if event.button != 1: + return + + pathinfo = view.get_path_at_pos(int(event.x), int(event.y)) + path = pathinfo[0] + iter = self._store.get_iter(path) + name, obj = self._store.get(iter, 0, 1) + + do_insert_with_tags(self._display.get_buffer(), repr(obj)) + + def __init__(self, rthread): + super(RadioBrowser, self).__init__() + self._radio = rthread.radio + self._build_ui() + self._fill('root', self._radio._memobj) + +if __name__ == "__main__": + from chirp import * + from chirp import directory + import sys + + r = directory.get_radio_by_image(sys.argv[1]) + class Foo: + radio = r + w = gtk.Window() + b = RadioBrowser(Foo) + w.set_default_size(1024, 768) + w.add(b.root) + w.show() + gtk.main()
Grately appreciated: I'm working on the 857 settings, i'll test this patch for sure ;) I'll le you know my thoughts.
73 de IZ3GME Marco
On 03/03/2013 17:26, Dan Smith wrote:
# HG changeset patch # User Dan Smith dsmith@danplanet.com # Date 1362327994 28800 # Node ID d7da2968488769d7e32321b0e03d7201662dc079 # Parent 49de55116a55bc5b35a5391aa14b3e68d182e4c7 [RFC] Add bitwise browser when developer options are enabled
This is something I've been wanting to do for a while. It provides a graphical way to explore the memory object of a clone-mode radio. It is roughly equivalent to doing "show raw memory" on a channel, but lets you do the same for other areas, such as the settings, limits, etc.
I want to do more things like let you diff other areas, and perhaps display the contents in a more formal way so that they can be tweaked arbitrarily, but that will come later. I'm submitting this here for comments and folks to try it out. Note that it requires dev tools to be enabled before opening an image.
Thoughts? Comments?
diff -r 49de55116a55 -r d7da29684887 chirp/bitwise.py --- a/chirp/bitwise.py Thu Feb 28 18:13:55 2013 -0800 +++ b/chirp/bitwise.py Sun Mar 03 08:26:34 2013 -0800 @@ -188,7 +188,7 @@
def __str__(self): if isinstance(self.__items[0], charDataElement):
return "".join([x.get_value() for x in self.__items])
return repr("".join([x.get_value() for x in self.__items]))[1:-1] else: return str(self.__items)
@@ -612,6 +612,13 @@ raise ValueError("Struct size mismatch during set_raw()") self._data[self._offset] = buffer
def __iter__(self):
for item in self._generators.values():
yield item
def items(self):
return self._generators.items()
class Processor:
_types = {
diff -r 49de55116a55 -r d7da29684887 chirpui/editorset.py --- a/chirpui/editorset.py Thu Feb 28 18:13:55 2013 -0800 +++ b/chirpui/editorset.py Sun Mar 03 08:26:34 2013 -0800 @@ -19,7 +19,7 @@
from chirp import chirp_common, directory, generic_csv, generic_xml from chirpui import memedit, dstaredit, bankedit, common, importdialog -from chirpui import inputdialog, reporting, settingsedit +from chirpui import inputdialog, reporting, settingsedit, radiobrowser, config
class EditorSet(gtk.VBox): __gsignals__ = { @@ -65,6 +65,7 @@ "bank_names" : None, "bank_members" : None, "settings" : None,
"browser" : None, } if isinstance(self.radio, chirp_common.IcomDstarSupport):
@@ -88,6 +89,11 @@ if rf.has_settings: self.editors["settings"] = settingsedit.SettingsEditor(self.rthread)
conf = config.get()
if (hasattr(self.rthread.radio, '_memobj') and
conf.get_bool("developer", "state")):
self.editors["browser"] = radiobrowser.RadioBrowser(self.rthread)
lab = gtk.Label(_("Memories")) self.tabs.append_page(self.editors["memedit"].root, lab) self.editors["memedit"].root.show()
@@ -115,6 +121,10 @@ self.tabs.append_page(self.editors["settings"].root, lab) self.editors["settings"].root.show()
if self.editors["browser"]:
lab = gtk.Label(_("Browser"))
self.tabs.append_page(self.editors["browser"].root, lab)
self.pack_start(self.tabs) self.tabs.show()
diff -r 49de55116a55 -r d7da29684887 chirpui/radiobrowser.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chirpui/radiobrowser.py Sun Mar 03 08:26:34 2013 -0800 @@ -0,0 +1,154 @@ +import gtk +import gobject +import pango +import re +import os
+from chirp import bitwise +from chirpui import common
+def do_insert_line_with_tags(b, line):
- def i(text, *tags):
b.insert_with_tags_by_name(b.get_end_iter(), text, *tags)
- def ident(name):
if "unknown" in name:
i(name, 'grey', 'bold')
else:
i(name, 'bold')
- def nonzero(value):
i(value, 'red', 'bold')
- def foo(value):
i(value, 'blue', 'bold')
- m = re.match("^( *)([A-z0-9_]+: )(0x[A-F0-9]+) ((.*))$", line)
- if m:
i(m.group(1))
ident(m.group(2))
if m.group(3) == '0x00':
i(m.group(3))
else:
nonzero(m.group(3))
i(' (')
for char in m.group(4):
if char == '1':
nonzero(char)
else:
i(char)
i(')')
return
- m = re.match("^( *)([A-z0-9_]+: )(.*)$", line)
- if m:
i(m.group(1))
ident(m.group(2))
i(m.group(3))
return
- m = re.match("^(.*} )([A-z0-9_]+)( ()([0-9]+)( bytes at )(0x[A-F0-9]+)",
line)
- if m:
i(m.group(1))
ident(m.group(2))
i(m.group(3))
foo(m.group(4))
i(m.group(5))
foo(m.group(6))
i(")")
return
- i(line)
+def do_insert_with_tags(buf, text):
- buf.set_text('')
- lines = text.split(os.linesep)
- for line in lines:
do_insert_line_with_tags(buf, line)
buf.insert_with_tags_by_name(buf.get_end_iter(), os.linesep)
+class RadioBrowser(common.Editor):
- def _build_ui(self):
self._display = gtk.TextView()
fontdesc = pango.FontDescription("Courier 10")
self._display.modify_font(fontdesc)
self._display.set_editable(False)
tt = self._display.get_buffer().get_tag_table()
for color in ["red", "green", "blue", "grey"]:
tag = gtk.TextTag(color)
tag.set_property("foreground", color)
tt.add(tag)
tag = gtk.TextTag("bold")
tag.set_property("weight", pango.WEIGHT_BOLD)
tt.add(tag)
self._store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
self._tree = gtk.TreeView(self._store)
rend = gtk.CellRendererText()
tvc = gtk.TreeViewColumn('Element', rend, text=0)
self._tree.append_column(tvc)
self._tree.connect('button_press_event', self._tree_click)
self._tree.set_size_request(200, -1)
self.root = gtk.HBox(False, 3)
sw = gtk.ScrolledWindow()
sw.add(self._tree)
sw.show()
self.root.pack_start(sw, 0, 0, 0)
sw = gtk.ScrolledWindow()
sw.add(self._display)
sw.show()
self.root.pack_start(sw, 1, 1, 1)
self._tree.show()
self._display.show()
self.root.show()
- def _fill(self, name, obj, parent=None):
iter = self._store.append(parent, (name, obj))
if isinstance(obj, bitwise.structDataElement):
for name, item in obj.items():
if isinstance(item, bitwise.structDataElement):
self._fill(name, item, iter)
elif isinstance(item, bitwise.arrayDataElement):
self._fill("%s[%i]" % (name, len(item)), item, iter)
elif isinstance(obj, bitwise.arrayDataElement):
i = 0
for item in obj:
self._fill("%s[%i]" % (name, i), item, iter)
i += 1
- def _tree_click(self, view, event):
if event.button != 1:
return
pathinfo = view.get_path_at_pos(int(event.x), int(event.y))
path = pathinfo[0]
iter = self._store.get_iter(path)
name, obj = self._store.get(iter, 0, 1)
do_insert_with_tags(self._display.get_buffer(), repr(obj))
- def __init__(self, rthread):
super(RadioBrowser, self).__init__()
self._radio = rthread.radio
self._build_ui()
self._fill('root', self._radio._memobj)
+if __name__ == "__main__":
- from chirp import *
- from chirp import directory
- import sys
- r = directory.get_radio_by_image(sys.argv[1])
- class Foo:
radio = r
- w = gtk.Window()
- b = RadioBrowser(Foo)
- w.set_default_size(1024, 768)
- w.add(b.root)
- w.show()
- gtk.main()
chirp_devel mailing list chirp_devel@intrepid.danplanet.com http://intrepid.danplanet.com/mailman/listinfo/chirp_devel Developer docs: http://chirp.danplanet.com/projects/chirp/wiki/Developers
On 2013-03-03 09:58, Dan Smith wrote:
Greatly appreciated: I'm working on the 857 settings, i'll test this patch for sure ;) I'll let you know my thoughts.
Cool, thanks :)
I have a rather complete map of the FT-897D memory (which I understand is pretty much identical to the FT-857), and the FT-817ND as well. The only problem is, it is in code written in Java, so I don't have clear bit-fields like I do in my C++ code for D-Star radios. The Java code uses a table format describing the fields and the bit positions therein, using Java "enum"s, so the code isn't very clear to someone who is not familiar with that Java feature.
If someone wants that (GPL v2) code, I have no problem providing it, with the understanding that I don't presently have the time to explain the code (flying weather is picking up). It doesn't look too difficult to figure out.
-- Dean
ps: I used GPL v2 (without the "any later version" clause) in my code, because I don't particularly care for the idea that Richard Stallman could decide on a new GPL license, and have *users* arbitrarily adopt that, with unknown consequences to me. I don't particularly mind v3 (I prefer v2; I think it's a better license for my purposes), but I'm not comfortable with leaving the door open to any future revisions that he or anyone else at the FSF would create. I don't believe that reverse engineering my code is a violation of the GPL v2 (at any rate I'll allow it in this circumstance), but I'd like to restrict its distribution to GPL v2 only.
Hi Dean!! Here I am! For what I've seen 857 and 897 share the very same memory mapping.
Please send your code code to me: I already have written quite complete mapping but, still, having something to compare can be of help and save time.
Many thanks 73 de IZ3GME Marco
On 03/03/2013 19:34, Dean Gibson AE7Q wrote:
On 2013-03-03 09:58, Dan Smith wrote:
Greatly appreciated: I'm working on the 857 settings, i'll test this patch for sure ;) I'll let you know my thoughts.
Cool, thanks :)
I have a rather complete map of the FT-897D memory (which I understand is pretty much identical to the FT-857), and the FT-817ND as well. The only problem is, it is in code written in Java, so I don't have clear bit-fields like I do in my C++ code for D-Star radios. The Java code uses a table format describing the fields and the bit positions therein, using Java "enum"s, so the code isn't very clear to someone who is not familiar with that Java feature.
If someone wants that (GPL v2) code, I have no problem providing it, with the understanding that I don't presently have the time to explain the code (flying weather is picking up). It doesn't look too difficult to figure out.
-- Dean
ps: I used GPL v2 (without the "any later version" clause) in my code, because I don't particularly care for the idea that Richard Stallman could decide on a new GPL license, and have *users* arbitrarily adopt that, with unknown consequences to me. I don't particularly mind v3 (I prefer v2; I think it's a better license for my purposes), but I'm not comfortable with leaving the door open to any future revisions that he or anyone else at the FSF would create. I don't believe that reverse engineering my code is a violation of the GPL v2 (at any rate I'll allow it in this circumstance), but I'd like to restrict its distribution to GPL v2 only.
chirp_devel mailing list chirp_devel@intrepid.danplanet.com http://intrepid.danplanet.com/mailman/listinfo/chirp_devel Developer docs: http://chirp.danplanet.com/projects/chirp/wiki/Developers
I also found an FT-897 layout in C++. All is attached ...
On 2013-03-03 11:39, Marco IZ3GME wrote:
Hi Dean!! Here I am! For what I've seen 857 and 897 share the very same memory mapping.
Please send your code code to me: I already have written quite complete mapping but, still, having something to compare can be of help and save time.
Many thanks 73 de IZ3GME Marco
On 03/03/2013 19:34, Dean Gibson AE7Q wrote:
On 2013-03-03 09:58, Dan Smith wrote:
Greatly appreciated: I'm working on the 857 settings, i'll test this patch for sure ;) I'll let you know my thoughts.
Cool, thanks :)
I have a rather complete map of the FT-897D memory (which I understand is pretty much identical to the FT-857), and the FT-817ND as well. The only problem is, it is in code written in Java, so I don't have clear bit-fields like I do in my C++ code for D-Star radios. The Java code uses a table format describing the fields and the bit positions therein, using Java "enum"s, so the code isn't very clear to someone who is not familiar with that Java feature.
If someone wants that (GPL v2) code, I have no problem providing it, with the understanding that I don't presently have the time to explain the code (flying weather is picking up). It doesn't look too difficult to figure out.
-- Dean
ps: I used GPL v2 (without the "any later version" clause) in my code, because I don't particularly care for the idea that Richard Stallman could decide on a new GPL license, and have *users* arbitrarily adopt that, with unknown consequences to me. I don't particularly mind v3 (I prefer v2; I think it's a better license for my purposes), but I'm not comfortable with leaving the door open to any future revisions that he or anyone else at the FSF would create. I don't believe that reverse engineering my code is a violation of the GPL v2 (at any rate I'll allow it in this circumstance), but I'd like to restrict its distribution to GPL v2 only.
Many thanks Dean! I see is pretty easy to read, I find very helpfull to compare your code and mine side by side.
73 de IZ3GME Marco
On 04/03/2013 03:10, Dean Gibson AE7Q wrote:
I also found an FT-897 layout in C++. All is attached ...
On 2013-03-03 11:39, Marco IZ3GME wrote:
Hi Dean!! Here I am! For what I've seen 857 and 897 share the very same memory mapping.
Please send your code code to me: I already have written quite complete mapping but, still, having something to compare can be of help and save time.
Many thanks 73 de IZ3GME Marco
On 03/03/2013 19:34, Dean Gibson AE7Q wrote:
On 2013-03-03 09:58, Dan Smith wrote:
Greatly appreciated: I'm working on the 857 settings, i'll test this patch for sure ;) I'll let you know my thoughts.
Cool, thanks :)
I have a rather complete map of the FT-897D memory (which I understand is pretty much identical to the FT-857), and the FT-817ND as well. The only problem is, it is in code written in Java, so I don't have clear bit-fields like I do in my C++ code for D-Star radios. The Java code uses a table format describing the fields and the bit positions therein, using Java "enum"s, so the code isn't very clear to someone who is not familiar with that Java feature.
If someone wants that (GPL v2) code, I have no problem providing it, with the understanding that I don't presently have the time to explain the code (flying weather is picking up). It doesn't look too difficult to figure out.
-- Dean
ps: I used GPL v2 (without the "any later version" clause) in my code, because I don't particularly care for the idea that Richard Stallman could decide on a new GPL license, and have *users* arbitrarily adopt that, with unknown consequences to me. I don't particularly mind v3 (I prefer v2; I think it's a better license for my purposes), but I'm not comfortable with leaving the door open to any future revisions that he or anyone else at the FSF would create. I don't believe that reverse engineering my code is a violation of the GPL v2 (at any rate I'll allow it in this circumstance), but I'd like to restrict its distribution to GPL v2 only.
chirp_devel mailing list chirp_devel@intrepid.danplanet.com http://intrepid.danplanet.com/mailman/listinfo/chirp_devel Developer docs: http://chirp.danplanet.com/projects/chirp/wiki/Developers
participants (3)
-
Dan Smith
-
Dean Gibson AE7Q
-
Marco IZ3GME