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

⌈⌋ branch:  streamtuner2

Update of "write a plugin"


Artifact ID: 0a769b31cf8219d526933e9c1538e6f32bc9cbf2
Page Name:write a plugin
Date: 2015-03-25 16:34:16
Original User: mario
Parent: 4b5e202b6032406965c42c5a0c0ab49f931f7ab8 (diff)
Next 483fa47010d213a0330479013ae65fa336c959c4

Wrting a new plugin is often trivial. Just create a new channels/ following this structure:

# title: MyPlugin
# description: my radio list
# version: 0.1
# type: channel
# category: radio

from channels import *

class myplugin (ChannelPlugin):
    title = "MyNewChannel"
    module = "myplugin"
    homepage = ""
    has_search = False
    titles = dict(listeners=False)
    categories = []
    catmap = {}
    config = []

    def update_categories(self):
        self.categories = ["Pop", "Rock", "etc"]

    def update_streams(self, cat, search=None):
        entries = []
        # ...
        # get it from somewhere
        # ...        
        return entries

The description block on top is used for the plugin management, and decorative purposes. Some fields like title and and module are repeated in the class declaration though.

Each plugin needs a update_categories() method. This can be a stub, if the channel plugin has a static list of genres. If so, just set the categories = [] declaration right away. The method is only used if the default categories list is empty, needs to be renewed from the service (e.g. whenever the menu entry Channel>Update_categories is used). There's also a catmap={} dict in case category/genre titles have to be associated with service ids.

More importantly you need the update_streams() method to fetch station lists. It receives a cat parameter, for instance "Pop". Then do whatever API query or website scraping (regex/pyquery) is necessary to populate a list.

Most plugins will return a list of dicts like:

 {title: Radio123, url: http://pls, genre: Pop, playing: Song123}

The title is required, and the streaming URL of course. Other fields are mostly optional.

  • Standard fields are:

    • genre - the category name
    • title - station title
    • url - streaming url (to pls or m3u resource)
    • playing - currently playing song, if any
    • homepage - station homepage
    • bitrate - (int) audio bitrate (like 128)
    • listeners - (int) number of listeners
    • favicon - url to favicon, if any
    • format - to set a custom audio format (audio/ogg)
  • Internal fields are:

    • state - a gtk icon
    • deleted - strikethrough for deleted entries
    • favourite - add a star for bookmarked stations
    • search_col - search color
    • search_set - search state
  • With a datamap=[] declaration custom field names could be displayed.

  • Often you just want to rename the column titles however - per title=dict(listeners="Whatever") in the class declaration.

Received station lists get stored internally in a streams={"Pop":[...]} dict, and cached in the ~/.config/streamtuner2/cache/ directory of course.

There's also a config=[] list, in case your plugin needs to keep some settings. (For example an API key.)

The has_search class flag permits live server searches. If one is issued, the update_streams() method will be called with cat=None and search="Find me maybe" set instead.

  • Other class options include listformat="audio/x-scpls" for declaring the station URL mime type (here pls for example).
  • And audioformat="audio/mpeg" for the audio mime type.
  • While current="" and default="Pop" can specify which category is visible per default, or currently active. (Both will be retired in later versions. More a clutch for current Gtk handling.)
  • Other internal fields are listed in channels/

To have a new plugin picked up, you need to copy/symlink the file into /usr/share/streamtuner2/channels/. It's imported from a local ./channels/ dir though, but the plugin finder currently just looks for the global directory.