[chirp_devel] [PATCH] Add import support for Kenwood *.hmk files
Dan Smith
Tue Apr 3 17:53:28 PDT 2012
> diff -r 91be43cc7ac4 -r 1bb3df3d624f chirp/directory.py
> --- a/chirp/directory.py Tue Apr 03 11:19:10 2012 -0700
> +++ b/chirp/directory.py Tue Apr 03 16:21:35 2012 -0600
> @@ -91,6 +91,9 @@
> if image_file.lower().endswith(".csv"):
> return get_radio("Generic_CSV")(image_file)
>
> + if image_file.lower().endswith(".hmk"):
> + return get_radio("Kenwood_HMK")(image_file)
> +
> if icf.is_9x_icf(image_file):
> return get_radio("Icom_IC91_92AD_ICF")(image_file)
This follows the existing pattern, but I think the existing pattern is
ugly. I can say that, since it's mine.
I suggested on IRC that you use match_model(), and then realized when I
saw the above that match_model() isn't used for CSV (or chirp) files,
and can't be for extension-based matching. What was I thinking.
I'll send a patch to the list in a minute that will enable doing so, and
convert the three cases there to use match_model() instead. Let me know
what you think about doing it that way instead.
> +class HMKRadio(chirp_common.CloneModeRadio):
I was thinking you would inherit from CSVRadio and hopefully eliminate
the need to duplicate all that work. Was there some reason this didn't
work out?
> + def _blank(self):
> + self.errors = []
> + self.memories = []
> + for i in range(0, 1000):
> + m = chirp_common.Memory()
> + m.number = i
> + m.empty = True
> + self.memories.append(m)
I don't think you need _blank() if you're not going to support editing,
right? If you inherit it from CSVRadio, it's one thing, but I think
it'll confuse a future developer if it's here for no reason.
> + def __init__(self, pipe):
> + chirp_common.CloneModeRadio.__init__(self, None)
> +
> + self._filename = pipe
> + if self._filename and os.path.exists(self._filename):
> + self.load()
> + else:
> + self._blank()
It's an error if we're instantiated without a filename.
> + def get_features(self):
> + rf = chirp_common.RadioFeatures()
> + rf.has_bank = False
> + rf.has_dtcs_polarity = False
> + rf.memory_bounds = (0, len(self.memories))
> + rf.has_infinite_number = True
> +
> + rf.valid_modes = list(chirp_common.MODES)
> + rf.valid_tmodes = list(chirp_common.TONE_MODES)
> + rf.valid_duplexes = ["", "-", "+", "split"]
> + rf.valid_tuning_steps = list(chirp_common.TUNING_STEPS)
> + rf.valid_bands = [(1, 10000000000)]
> + rf.valid_skips = ["", "S"]
> + rf.valid_characters = chirp_common.CHARSET_ASCII
> + rf.valid_name_length = 999
> +
> + return rf
If you inherit from CSVRadio, then these are fine, but I think they are
probably unnecessary if you're import-only, right?
> + def _parse_quoted_line(self, line):
> + line = line.replace("\n", "")
> + line = line.replace("\r", "")
> + line = line.replace('"', "")
> +
> + return line.split(",")
This is dead code from the CSV driver. Lets remove it from there and not
replicate it here :)
> + def _parse_csv_data_line(self, headers, line):
> + mem = chirp_common.Memory()
> + odd_split = False
> +
> + for header, (typ, attr) in self.ATTR_MAP.items():
> + try:
> + val = self._get_datum_by_header(headers, line, header)
> + if not val and typ == int:
> + val = None
> + elif attr == "duplex":
> + val = typ(self.DUPLEX_MAP[val])
> + if val == "split":
> + odd_split = True
Hmm, what do the Tx Freq. and Offset columns look like in the two cases?
Seems like we should be able to do better than this.
> + elif attr == "skip":
> + val = typ(self.SKIP_MAP[val])
> + elif attr == "tmode":
> + val = typ(self.TMODE_MAP[val])
Instead of special-casing these, why not use a function like the
frequency parsing case? Something like this:
ATTR_MAP = {
...
"T/CT/DCS" : (lambda v: self.TMODE_MAP[v], "tmode"),
"L.Out" : (lambda v: self.SKIP_MAP[v], "skip"),
...
}
That way you can just cover all the cases with this:
> + else:
> + val = typ(val)
...like the CSV driver does. Plus, if we can figure out something sneaky
for the Offset and Tx Freq. cases, then you could still inherit from
CSVRadio with a different ATTR_MAP :)
> +
> + def load(self, filename=None):
> + if filename is None and self._filename is None:
> + raise errors.RadioError("Need a location to load from")
> +
> + if filename:
> + self._filename = filename
> +
> + self._blank()
I think you can remove this.
> +
> + f = file(self._filename, "r")
> + for i in range(0, 10):
> + f.readline().strip()
Is it always ten lines? Maybe it would be better to probe smartly to
chew up everything until the header row?
> + #f.seek(0, 0)
Did you intend to leave this in or take it out?
--
Dan Smith
www.danplanet.com
KK7DS
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: OpenPGP digital signature
Url : http://intrepid.danplanet.com/pipermail/chirp_devel/attachments/20120403/ef1c342b/attachment-0001.bin
More information about the chirp_devel
mailing list