File: specbuttons.py

package info (click to toggle)
streamtuner2 2.2.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 2,432 kB
  • sloc: python: 8,976; makefile: 91; php: 51; sh: 7; perl: 3
file content (135 lines) | stat: -rw-r--r-- 4,779 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
60
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# encoding: utf-8
# title: Spec buttons for apps
# description: Adds configurable mini toolbar buttons
# version: 0.8.2
# depends: streamtuner2 >= 2.2.0
# type: feature
# category: ui
# config:
#    { name: specbutton_rows, value: 2, max: 4, type: int, description: "Number of rows to arrange buttons in." }
#    { name: specbuttons, type: dict, columns: "Icon,Command", description: "Icons can be `<a href='http://www.pygtk.org/pygtk2reference/gtk-stock-items.html'>gtk-xyz</a>` internal names. Else use `/usr/share/icon/*.png` file names. Icon file basenames will be expanded into full paths." }
# documentation:
#    http://fossil.include-once.org/streamtuner2/info/43b36ed35b1488d5
#
# Adds the mini/extra buttons in the toolbar, which allow to control your
# audio player or run other system commands.
#
#  [Icon]  [Cmd]
#
#  volume  pavucontrol
#
#  up      amixer sset Master 5%+
#
#  kill    pkill vlc
#
# Icons can be gtk-xyz icon names or /usr/share/icon/* PNG files.
# Each command may use streamtuner2 placeholders like %g or %url and $title.


import os.path
import subprocess
import math
import re
from config import conf, log, plugin_meta
import action
from uikit import gtk


# Extra/mini buttons in toolbar
class specbuttons(object):
    meta = plugin_meta()
    module = 'specbuttons'

    # Hook toolbar label
    def __init__(self, parent):
        if not parent:
            return
        self.parent = parent
        conf.add_plugin_defaults(self.meta, self.module)
        self.specbuttons = parent.get_widget("specbuttons")
        parent.hooks["init"].append(self.update_buttons)
        parent.hooks["config_save"].append(self.update_paths)
        parent.specbuttons.show()

    # Extra buttons
    def update_buttons(self, parent):
    
        # define table width (2 rows default)
        y = conf.specbuttons_rows if "specbuttons_rows" in conf else 2
        y = max(min(int(conf.specbutton_rows), 4), 1) # 1 <= y <= 4
        self.specbuttons.resize(y, int(math.ceil(len(conf.specbuttons) / y)))
        # clean up
        for widget in self.specbuttons.get_children():
            widget.destroy()
        
        # add icon buttons
        #for xy, (btn, cmd) in enumerate(conf.specbuttons.items()):
        for xy, (btn) in enumerate( sorted ( conf.specbuttons )):
            cmd = conf.specbuttons [btn]
            #log.IN(btn, cmd)
            w_btn = gtk.Button()
            w_btn.set_image(self.icon(btn))
            w_btn.connect("clicked", lambda x0, cmd=cmd, *x: self.action(cmd))
            self.specbuttons.attach(
                child = w_btn,
                left_attach   = int(xy / y),
                right_attach  = int(xy / y) + 1,
                top_attach    = xy % y,
                bottom_attach = (xy % y) + 1,
                xoptions = gtk.EXPAND,
                yoptions = gtk.EXPAND,
                xpadding = 1,
                ypadding = 1
            )
        self.specbuttons.show_all()

    # Instantiate Image from gtk-* string or path
    def icon(self, btn):
        wi = gtk.Image()
        if (btn.find("gtk-") == 0):
            wi.set_from_stock(btn, gtk.ICON_SIZE_SMALL_TOOLBAR)
        else:
            if not os.path.exists(btn):
                btn = self.locate(btn)
                log.DATA(btn)
            if btn:
                wi.set_from_file(btn)
            else:
                wi.set_from_stock("gtk-image-missing", gtk.ICON_SIZE_SMALL_TOOLBAR)
        return wi

    # Look for image basename (e.g. "play") in /usr/share/icons/*.* and /pixmaps/*
    def locate(self, btn, f=None):
        try:
            f = subprocess.Popen(["locate", "/usr/share/[pi]*s/*%s*.*" % btn], stdout=subprocess.PIPE)
        except:
            return None
        path, err = f.communicate()
        if not err:
            return path.split("\n")[0]

    # Update paths when saving config dialog
    def update_paths(self):
        r = {}
        for btn, cmd in conf.specbuttons.items():
            # replace "gtk." to "gtk-"
            if re.match("^gtk\.\w+", btn, re.I):
                btn = re.sub("[._]+", "-", btn).lower()
            # not /path or gtk-
            elif not re.match("^(/|\./|gtk-|\w:[\\\\/])", btn):
                path = self.locate(btn)
                if path:
                    btn = path
                else:
                    log.WARN("Extra button icon '%s' could not be found" % btn)
            r[btn] = cmd
        conf.specbuttons = r
        self.update_buttons(self.parent)

    # Button callback, allow for %url/%title placeholders
    def action(self, cmd):
        if re.search("[%$]", cmd):
            row = self.parent.channel().row()
            cmd = action.run_fmt_url(cmd, row=row, add_default=False, cmd=cmd)
        action.run(cmd)