Internet radio browser GUI for music/video streams from various directory services.

⌈⌋ ⎇ branch:  streamtuner2


Check-in [ea30a91e8d]

Overview
Comment:Allow plugin # config: bags only with <> or {} as delimiters, to support markup description/label.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ea30a91e8db71f023a570dbd9172a927f610b501
User & Date: mario on 2016-10-22 18:58:26
Other Links: manifest | tags
Context
2016-10-22
18:58
Shorten "house-mixes" title. check-in: dd4aa1e8ec user: mario tags: trunk
18:58
Allow plugin # config: bags only with <> or {} as delimiters, to support markup description/label. check-in: ea30a91e8d user: mario tags: trunk
2016-10-18
22:11
Move action/playback handlers to contrib/cmdline/ check-in: 05817e12db user: mario tags: trunk
Changes

Modified channels/configwin.py from [7969234304] to [75725508ad].

190
191
192
193
194
195
196
197

198
199
200
201

202
203
204
205
206
207
208
209
210
211
190
191
192
193
194
195
196

197
198
199
200

201
202
203
204
205
206
207
208
209
210
211







-
+



-
+










        doc = meta.get("doc", "").strip()
        if ver < 3:
            doc = re.sub("(?<=\S) *\n(?! *\n)", " ", doc)
        return doc

    # Put config widgets into channels/features configwin notebooks
    def add_channels(self, id=None, w=None, label=None, color=None, image=None, align=20):
        self.plugin_options.pack_start(uikit.wrap(self.widgets, id, w, label, color, image, align))
        self.plugin_options.pack_start(uikit.wrap(self.widgets, id, w, label, color, image, align, label_markup=1))

    # Separate tab for non-channel plugins
    def add_features(self, id=None, w=None, label=None, color=None, image=None, align=20):
        self.feature_options.pack_start(uikit.wrap(self.widgets, id, w, label, color, image, align))
        self.feature_options.pack_start(uikit.wrap(self.widgets, id, w, label, color, image, align, label_markup=1))


    # save config
    def save(self, widget):
        self.save_config(conf.__dict__, "config_")
        self.save_config(conf.plugins, "config_plugins_")
        [callback() for callback in self.hooks["config_save"]]
        conf.save(nice=1)
        self.hide()

Modified pluginconf.py from [9a5f974003] to [3b562696a0].

268
269
270
271
272
273
274

275
276
277
278
279
280
281
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282







+







#   { name=option2, type=boolean, $value=1, etc. }
#
# Stubs out name, value, type, description if absent.
#
def plugin_meta_config(str):
    config = []
    for entry in rx.config.findall(str):
        entry = entry[0] or entry[1]
        opt = {
            "type": None,
            "name": None,
            "description": "",
            "value": None
        }
        for field in rx.options.findall(entry):
293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308







-
+







class rx:
    comment = re.compile(r"""(^ {0,4}#.*\n)+""", re.M)
    hash = re.compile(r"""(^ {0,4}# *)""", re.M)
    keyval = re.compile(r"""
        ^([\w-]+):(.*$(?:\n(?![\w-]+:).+$)*)      # plain key:value lines
    """, re.M | re.X)
    config = re.compile(r"""
        [\{\<] (.+?) [\}\>]                    # JSOL/YAML scheme {...} dicts
        \{ (.+?) \} | \< (.+?) \>              # JSOL/YAML scheme {...} dicts
    """, re.X)
    options = re.compile(r"""
        ["':$]?   (\w*)  ["']?                 # key or ":key" or '$key'
        \s* [:=] \s*                           # "=" or ":"
     (?:  "  ([^"]*)  "
       |  '  ([^']*)  '                        #  "quoted" or 'singl' values
       |     ([^,]*)                           #  or unquoted literals