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

⌈⌋ ⎇ branch:  streamtuner2


Changes To write a plugin

Changes to "write a plugin" between 2015-05-11 21:17:18 and 2015-05-20 07:37:08

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







Writing a new plugin is often trivial.
Just create a new `channels/name.py` following this structure:
Just create a new `channels/myplugin.py` following this structure:

    # title: MyPlugin
    # description: my radio list
    # url: http://www.mymusicstation.com/
    # version: 0.1
    # type: channel
    # category: radio
27
28
29
30
31
32
33


34
35
36
37
38
39
40
41
42
43
44
45
46




47
48
49
50
51
52
53
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59







+
+













+
+
+
+







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

The class name must match the script basename.

### Plugin meta block

The description block on top is used for the [plugin management](wiki/plugin+meta+data) (and documentative purposes). This is meant to cleanly separate in-application values (like .module or .has_search, .catmap) from attributes that just serve initialization.

All fields show up in `self.meta`, for instance the `meta["title"]` or `meta["url"]` are occasionally used. The `config[]` entry is a list/dict combination, and its defaults automatically thrown into `conf.*` variables. Therefore plugins can use their settings right away (e.g. `conf.myplugin_bitrate=128`)

### update_categories()

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.

### update_streams()

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.

   * `ahttp.get()` for fetching resources
   * `pq()` to use PyQuery
   * or import `json` etc.

Most plugins will return a list of dicts like:

    [
      {title: Radio123, url: http://pls, genre: Pop, playing: Song123},
      {title: Next.Radio, url: http://pls, genre: Pop, playing: Next Song},
      ...
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94

95
96
97

98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84


85
86
87
88
89
90
91
92
93
94

95
96
97
98

99
100
101

102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118
119

120







+










-
-










-
+



-
+


-
+








-
+








-
+
      * <kbd>title</kbd> - station title
      * <kbd>url</kbd> - streaming url (to pls or m3u resource)
      * <kbd>playing</kbd> - currently playing song, if any
      * <kbd>homepage</kbd> - station homepage
      * <kbd>bitrate</kbd> - (int) audio bitrate (like 128)
      * <kbd>listeners</kbd> - (int) number of listeners
      * <kbd>format</kbd> - to set a custom audio format (audio/ogg)
      * <kbd>listformat</kbd> - url playlist type (pls)

   * Internal fields are: 

      * <kbd>favicon</kbd> - path to localized favicon, either from <kbd>homepage</kbd> or <kbd>img</kbd> url
      * <kbd>state</kbd> - a gtk icon
      * <kbd>deleted</kbd> - strikethrough for deleted entries
      * <kbd>favourite</kbd> - add a star for bookmarked stations
      * <kbd>search_col</kbd> - search color
      * <kbd>search_set</kbd> - 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.

You can add any additional fields of your choosing.

### streams = {}

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

### conf. options

You can access your <kbd>config:</kbd> options per the global `conf.*` dict. Take care to prefer unambigious names like `conf.myplugin_pagesize` etc.
You can access your <kbd>config:</kbd> options through the global `conf.*` dict. Take care to prefer unambigious names like `conf.myplugin_pagesize` etc.

### Attributes

There are a couple of other attributes.
There are a couple of possible class/object flags.

 - **has_search** `= False`  
   This flag documents if live server searches are available. If it's supported, then the `update_streams()` method may be called with `cat=None` and `search="Find me maybe"` instead; and it's then responsible to do some searching.
   This flag documents if live server searches are available. If it's supported, then the `update_streams()` method may be called with `cat=None` and `search="Find me maybe"` instead; and is then responsible to do some searching.

 - **audioformat** `= "audio/mpeg"`  
   Sets the default audio stream type for this channel. (Note that each individual stream entry may carry its own `format` attribute, just in case.)

 - **listformat** `= "pls"`  
   Declares the channel service playlist type. Can be either "pls" or "m3u" or "xspf" if the server is super modern. Most directories provide `http://myradiolist.com/listen-12345.pls` URLs, so should use `"pls"` here.  It's also possible to use "href" here, if you can't be sure of audio or playlist format types. And "srv" if the provider has a clean list of direct MP3/Ogg streaming URLs only.

 - **titles =** `dict(listeners=False)`  
   This defines which station column titles to show. There are title=, genre= which you commonly have. And there is playing= or bitrate= and homepage= which you can omit by setting it to `=False`. Alternatively just rename them with `playing="Artist/Album name`.
   This defines which station column titles to show. There are title=, genre= which you commonly have. And there is playing= or bitrate= and homepage= which you can omit by setting it to `=False`. Alternatively just rename them with `playing="Artist/Album name"`.

 - **datamap** = `[...]`  
   If you want some complexity, such as elaborate column title renaming, extra pixmaps/favicons, or using custom row fields/attributes - then this can all be accomplished with a Gtk TreeView *datamap*. No, you don't want to do that.

 - Other internal fields are listed in `channels/__init__.py`

### Installation

To have a new plugin picked up, you need to copy/symlink the file into `/usr/share/streamtuner2/channels/`. It's imported from the `channels` module group automatically. Which allows relocatability, and later even local plugins. (Which is commonly unneeded featuritis though. So not yet implemented.)
To have a new plugin picked up, you need to copy/symlink the file into `/usr/share/streamtuner2/channels/`. It's imported from the `channels` module group automatically. Which allows relocatability, or loading it from ~/.config/streamtuner/plugins/ even.