Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package chirp for openSUSE:Factory checked in at 2026-09-10 11:48:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/chirp (Old) and /work/SRC/openSUSE:Factory/.chirp.new.1265 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "chirp" Thu Sep 10 11:48:52 2026 rev:78 rq:1376752 version:20260904 Changes: -------- --- /work/SRC/openSUSE:Factory/chirp/chirp.changes 2026-08-21 22:17:46.880926295 +0200 +++ /work/SRC/openSUSE:Factory/.chirp.new.1265/chirp.changes 2026-09-10 11:51:54.641897587 +0200 @@ -1,0 +2,8 @@ +Wed Sep 09 19:37:20 UTC 2026 - Andreas Stieger <[email protected]> + +- Update to version 20260904: + * Fix RB28/RB628 tone and DTCS index mapping + * Retevis RB28/RB628: Fix Busy Channel Lockout display + * various bug fixes + +------------------------------------------------------------------- Old: ---- chirp-20260821.obscpio New: ---- chirp-20260904.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ chirp.spec ++++++ --- /var/tmp/diff_new_pack.PB4ahm/_old 2026-09-10 11:51:56.358969599 +0200 +++ /var/tmp/diff_new_pack.PB4ahm/_new 2026-09-10 11:51:56.363969809 +0200 @@ -20,7 +20,7 @@ %define pythons python3 Name: chirp -Version: 20260821 +Version: 20260904 Release: 0 Summary: Tool for programming amateur radio sets License: GPL-3.0-only ++++++ _service ++++++ --- /var/tmp/diff_new_pack.PB4ahm/_old 2026-09-10 11:51:56.433972745 +0200 +++ /var/tmp/diff_new_pack.PB4ahm/_new 2026-09-10 11:51:56.442973122 +0200 @@ -4,8 +4,8 @@ <param name="scm">git</param> <param name="changesgenerate">enable</param> <param name="filename">chirp</param> - <param name="versionformat">20260821</param> - <param name="revision">fa27a491d275f88b452d0488a51b4c85d4f7062a</param> + <param name="versionformat">20260904</param> + <param name="revision">3af0eda7d60f6a79120097c4f3caccb6bb2d74dd</param> </service> <service mode="manual" name="set_version"/> <service name="tar" mode="buildtime"/> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.PB4ahm/_old 2026-09-10 11:51:56.505975765 +0200 +++ /var/tmp/diff_new_pack.PB4ahm/_new 2026-09-10 11:51:56.513976100 +0200 @@ -1,7 +1,7 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/kk7ds/chirp.git</param> - <param name="changesrevision">fa27a491d275f88b452d0488a51b4c85d4f7062a</param> + <param name="changesrevision">3af0eda7d60f6a79120097c4f3caccb6bb2d74dd</param> </service> </servicedata> (No newline at EOF) ++++++ chirp-20260821.obscpio -> chirp-20260904.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20260821/chirp/drivers/ft4.py new/chirp-20260904/chirp/drivers/ft4.py --- old/chirp-20260821/chirp/drivers/ft4.py 2026-08-19 02:25:46.000000000 +0200 +++ new/chirp-20260904/chirp/drivers/ft4.py 2026-08-30 20:43:53.000000000 +0200 @@ -280,14 +280,9 @@ if not response: if cmd == PROGRAM_CMD: raise errors.RadioNoResponse() - raise errors.RadioError("No response from radio") - if len(response) != response_len: - raise errors.RadioError("Incomplete response from radio") else: response = b"" ack = pipe.read(1) - if not ack: - raise errors.RadioError("No response from radio") if ack != b'\x06': if retry < 5: LOG.debug("retry: " + str(retry)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20260821/chirp/drivers/kenwood_live.py new/chirp-20260904/chirp/drivers/kenwood_live.py --- old/chirp-20260821/chirp/drivers/kenwood_live.py 2026-08-19 02:25:46.000000000 +0200 +++ new/chirp-20260904/chirp/drivers/kenwood_live.py 2026-08-30 20:43:53.000000000 +0200 @@ -410,6 +410,8 @@ rf.valid_tuning_steps = STEPS rf.has_sub_devices = True rf.memory_bounds = (1, self._upper) + rf.valid_bands = [(144000000, 148000000), + (420000000, 450000000)] return rf def _make_mem_spec(self, mem): @@ -502,7 +504,7 @@ MODEL = "TM-G707" def get_features(self): - rf = TMV7Radio.get_features(self) + rf = super().get_features() rf.has_sub_devices = False rf.memory_bounds = (1, 180) rf.valid_bands = [(118000000, 174000000), @@ -520,7 +522,7 @@ MODEL = "TH-G71" def get_features(self): - rf = TMV7Radio.get_features(self) + rf = super().get_features() rf.has_tuning_step = True rf.valid_tuning_steps = list(THG71_STEPS) rf.valid_name_length = 6 @@ -1051,9 +1053,59 @@ """Kenwood TH-K2""" MODEL = "TH-K2" HARDWARE_FLOW = False + _probe_memory = 99 _kenwood_valid_tones = list(KENWOOD_TONES) + def __init__(self, *a, **k): + self._has_name = True + super().__init__(*a, **k) + if self.pipe: + self._probe_layout() + + def _probe_layout(self): + """Determine if the radio is in 100+alpha or 200 channel mode""" + rf = self.get_features() + wasempty = None + try: + LOG.debug('Getting memory %i', self._probe_memory) + m = self.get_memory(self._probe_memory) + wasempty = m.empty + if wasempty: + m.freq = rf.valid_bands[0][0] + m.empty = False + LOG.debug('Memory %i was empty using %s to probe', + self._probe_memory, m) + else: + LOG.debug('Memory %i was set: %s', self._probe_memory, m) + # This either sets the probe memory over itself, or creates one + # at the lower limit frequency. Note that in order for this to + # work, we need _has_name=True here so that we can detect if we + # failed to set the memory (because 199 is out of range) or the + # memory name (because 199 is in range, but names are not + # supported). + self.set_memory(m) + LOG.error('Unexpectedly successful at setting probe memory %s', m) + except errors.InvalidDataError as e: + LOG.debug('Probe response was %s', e) + if 'name' in str(e): + # Radio is configured for max channels, refused the name + self._has_name = False + LOG.info('Radio determined to be in max-channel mode') + else: + # Radio is configured for alpha channels, as it refused the + # whole thing + self._has_name = True + LOG.info('Radio determined to be in channel+alpha mode') + finally: + if wasempty: + LOG.debug('Erasing probe memory %s', m) + # This needs to do the raw command because of the memory + # caching in set_memory() + self.command(self.pipe, *self._cmd_set_memory( + self._probe_memory, "")) + LOG.debug('Done probing layout') + def get_features(self): rf = chirp_common.RadioFeatures() rf.can_odd_split = False @@ -1068,7 +1120,7 @@ rf.valid_bands = [(136000000, 173990000)] rf.valid_skips = ["", "S"] rf.valid_tuning_steps = [5.0] - rf.memory_bounds = (0, 49) + rf.memory_bounds = (0, 49 if self._has_name else 99) return rf def _cmd_get_memory(self, number): @@ -1139,6 +1191,7 @@ class TM271Radio(THK2Radio): """Kenwood TM-271""" MODEL = "TM-271" + _probe_memory = 199 def get_features(self): rf = chirp_common.RadioFeatures() @@ -1146,6 +1199,7 @@ rf.has_dtcs_polarity = False rf.has_bank = False rf.has_tuning_step = False + rf.has_name = self._has_name rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS"] rf.valid_modes = THK2_MODES rf.valid_duplexes = THK2_DUPLEX @@ -1154,7 +1208,7 @@ rf.valid_bands = [(137000000, 173990000)] rf.valid_skips = ["", "S"] rf.valid_tuning_steps = list(TM271_STEPS) - rf.memory_bounds = (0, 99) + rf.memory_bounds = (0, 99 if self._has_name else 199) return rf def _cmd_get_memory(self, number): @@ -1178,25 +1232,13 @@ @directory.register -class TM471Radio(THK2Radio): +class TM471Radio(TM271Radio): """Kenwood TM-471""" MODEL = "TM-471" def get_features(self): - rf = chirp_common.RadioFeatures() - rf.can_odd_split = False - rf.has_dtcs_polarity = False - rf.has_bank = False - rf.has_tuning_step = False - rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS"] - rf.valid_modes = THK2_MODES - rf.valid_duplexes = THK2_DUPLEX - rf.valid_characters = THK2_CHARS - rf.valid_name_length = 6 + rf = super().get_features() rf.valid_bands = [(444000000, 479990000)] - rf.valid_skips = ["", "S"] - rf.valid_tuning_steps = [5.0] - rf.memory_bounds = (0, 99) return rf def _cmd_get_memory(self, number): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20260821/chirp/drivers/retevis_rb28.py new/chirp-20260904/chirp/drivers/retevis_rb28.py --- old/chirp-20260821/chirp/drivers/retevis_rb28.py 2026-08-19 02:25:46.000000000 +0200 +++ new/chirp-20260904/chirp/drivers/retevis_rb28.py 2026-08-30 20:43:53.000000000 +0200 @@ -140,17 +140,23 @@ VOXD_LIST = ["0.5", "1.0", "1.5", "2.0", "2.5", "3.0"] VOXL_LIST = ["OFF"] + ["%s" % x for x in range(1, 10)] -PMR_TONES = tuple( - set(chirp_common.TONES) - set([69.3, 159.8, 165.5, 171.3, 177.3, - 183.5, 189.9, 196.6, 199.5, 206.5, - 229.1, 254.1])) - -PMR_DTCS_CODES = tuple( - set(chirp_common.DTCS_CODES) - set([36, 53, 122, 145, 212, - 225, 246, 252, 255, 266, - 274, 325, 332, 356, 446, - 452, 454, 455, 462, 523, - 526])) +# Sort to preserve chirp_common ordering because these tuples are used for +# positional tone/DTCS index mapping when decoding the radio image. +PMR_TONES = tuple(sorted( + set(chirp_common.TONES) - set([ + 69.3, 159.8, 165.5, 171.3, 177.3, + 183.5, 189.9, 196.6, 199.5, 206.5, + 229.1, 254.1 + ]) +)) + +PMR_DTCS_CODES = tuple(sorted( + set(chirp_common.DTCS_CODES) - set([ + 36, 53, 122, 145, 212, 225, 246, 252, 255, + 266, 274, 325, 332, 356, 446, 452, 454, 455, + 462, 523, 526 + ]) +)) def _enter_programming_mode(radio): @@ -464,8 +470,9 @@ mem.extra.append(rset) _obj = self._memobj.bclo - key = "chnl_%i" % (mem.number) - rs = RadioSettingValueBoolean(getattr(_obj, "chnl_%i" % (mem.number))) + key = "bclo" + rs = RadioSettingValueBoolean( + getattr(_obj, "chnl_%i" % mem.number)) rset = RadioSetting(key, "Busy Channel Lockout", rs) mem.extra.append(rset) @@ -575,8 +582,9 @@ _mem.highpower = mem.power == self.POWER_LEVELS[0] for setting in mem.extra: - if setting.get_name().startswith("chnl_"): - setattr(self._memobj.bclo, setting.get_name(), setting.value) + if setting.get_name() == "bclo": + setattr(self._memobj.bclo, + "chnl_%i" % mem.number, setting.value) else: setattr(_mem, setting.get_name(), setting.value) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20260821/chirp/wxui/bugreport.py new/chirp-20260904/chirp/wxui/bugreport.py --- old/chirp-20260821/chirp/wxui/bugreport.py 2026-08-19 02:25:46.000000000 +0200 +++ new/chirp-20260904/chirp/wxui/bugreport.py 2026-08-30 20:43:53.000000000 +0200 @@ -41,6 +41,7 @@ CONF = config.get() BASE = (CONF.get('baseurl', 'chirpmyradio') or 'https://data.chirpmyradio.com/redmine') +USER_BASE = 'https://chirpmyradio.com' LOG = logging.getLogger(__name__) ReportThreadEvent, EVT_REPORT_THREAD = wx.lib.newevent.NewCommandEvent() @@ -252,8 +253,8 @@ def _build(self, vbox): vbox.Add( wx.adv.HyperlinkCtrl( - self, label=BASE + '/account/register', - url=BASE + '/account/register'), + self, label=USER_BASE + '/account/register', + url=USER_BASE + '/account/register'), 0, border=20, flag=wx.ALIGN_CENTER) panel = wx.Panel(self) @@ -418,9 +419,10 @@ wx.adv.HyperlinkCtrl( panel, label=_('searched for duplicate issues'), - url=BASE + ('/projects/chirp/search?utf8=%E2%9C%93&' - 'q=&scope=&all_words=&all_words=1&titles_only=&' - 'issues=1&attachments=0&options=0&commit=Search')), + url=USER_BASE + ( + '/projects/chirp/search?utf8=%E2%9C%93&' + 'q=&scope=&all_words=&all_words=1&titles_only=&' + 'issues=1&attachments=0&options=0&commit=Search')), 0) hbox.AddStretchSpacer(1) @@ -591,7 +593,7 @@ style=wx.TE_CENTER) vbox.Add(self.result, 0, border=20, flag=wx.EXPAND | wx.ALL) - self.issuelink = wx.adv.HyperlinkCtrl(self, url=BASE) + self.issuelink = wx.adv.HyperlinkCtrl(self, url=USER_BASE) self.issuelink.Hide() vbox.Add(self.issuelink, 0, border=20, flag=wx.EXPAND | wx.ALL) @@ -731,7 +733,7 @@ self.result.SetLabel( _('Successfully sent bug report:')) self.FindWindowById(wx.ID_BACKWARD).Enable(False) - link = BASE + '/issues/%s' % self.context.bugnum + link = USER_BASE + '/issues/%s' % self.context.bugnum self.issuelink.SetLabel(link) self.issuelink.SetURL(link) self.issuelink.Show() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20260821/chirp/wxui/common.py new/chirp-20260904/chirp/wxui/common.py --- old/chirp-20260821/chirp/wxui/common.py 2026-08-19 02:25:46.000000000 +0200 +++ new/chirp-20260904/chirp/wxui/common.py 2026-08-30 20:43:53.000000000 +0200 @@ -40,6 +40,26 @@ LOG = logging.getLogger(__name__) CONF = config.get() + +def pg_action_edit(): + # wxPython >= 4.3 replaced the PG_ACTION_* integer constants with + # the PGKeyboardAction enum. Look this up lazily (i.e. not at + # module import time) since by the time a settings grid is + # actually built, something will have already imported + # wx.propgrid for real; doing it ourselves at import time with an + # explicit `import wx.propgrid` breaks tests that stub out `wx` + # wholesale with a Mock. + if hasattr(wx.propgrid, 'PG_ACTION_EDIT'): + return wx.propgrid.PG_ACTION_EDIT + return wx.propgrid.PGKeyboardAction.Edit + + +def pg_action_next_property(): + if hasattr(wx.propgrid, 'PG_ACTION_NEXT_PROPERTY'): + return wx.propgrid.PG_ACTION_NEXT_PROPERTY + return wx.propgrid.PGKeyboardAction.NextProperty + + CHIRP_DATA_MEMORY = wx.DataFormat('x-chirp/memory-channel') EditorChanged, EVT_EDITOR_CHANGED = wx.lib.newevent.NewCommandEvent() StatusMessage, EVT_STATUS_MESSAGE = wx.lib.newevent.NewCommandEvent() @@ -403,8 +423,8 @@ self.pg.DedicateKey(wx.WXK_RETURN) self.pg.DedicateKey(wx.WXK_UP) self.pg.DedicateKey(wx.WXK_DOWN) - self.pg.AddActionTrigger(wx.propgrid.PG_ACTION_EDIT, wx.WXK_RETURN) - self.pg.AddActionTrigger(wx.propgrid.PG_ACTION_NEXT_PROPERTY, + self.pg.AddActionTrigger(pg_action_edit(), wx.WXK_RETURN) + self.pg.AddActionTrigger(pg_action_next_property(), wx.WXK_RETURN) sizer = wx.BoxSizer(wx.VERTICAL) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20260821/chirp/wxui/memedit.py new/chirp-20260904/chirp/wxui/memedit.py --- old/chirp-20260821/chirp/wxui/memedit.py 2026-08-19 02:25:46.000000000 +0200 +++ new/chirp-20260904/chirp/wxui/memedit.py 2026-08-30 20:43:53.000000000 +0200 @@ -2918,8 +2918,8 @@ self._pg.DedicateKey(wx.WXK_RETURN) self._pg.DedicateKey(wx.WXK_UP) self._pg.DedicateKey(wx.WXK_DOWN) - self._pg.AddActionTrigger(wx.propgrid.PG_ACTION_EDIT, wx.WXK_RETURN) - self._pg.AddActionTrigger(wx.propgrid.PG_ACTION_NEXT_PROPERTY, + self._pg.AddActionTrigger(common.pg_action_edit(), wx.WXK_RETURN) + self._pg.AddActionTrigger(common.pg_action_next_property(), wx.WXK_RETURN) self._tabs.InsertPage(0, self._pg, _('Values')) ++++++ chirp.obsinfo ++++++ --- /var/tmp/diff_new_pack.PB4ahm/_old 2026-09-10 11:51:58.194046561 +0200 +++ /var/tmp/diff_new_pack.PB4ahm/_new 2026-09-10 11:51:58.198046728 +0200 @@ -1,5 +1,5 @@ name: chirp -version: 20260821 -mtime: 1787099146 -commit: fa27a491d275f88b452d0488a51b4c85d4f7062a +version: 20260904 +mtime: 1788115433 +commit: 3af0eda7d60f6a79120097c4f3caccb6bb2d74dd
