summaryrefslogtreecommitdiffstats
path: root/modules/mpd.py
blob: e94872c7384e469832d0501efb49da1f79ad45de (plain)
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
from mpd import (MPDClient, CommandError)
from socket import error as SocketError
import time
import re

"""
Mpd - module to show information from mpd to your's bar! Settings listed above.
DEPENDENCIES: python-mpd2 (NOT python2-mpd2):
    # pip install python-mpd2

@author shadowprince
@version 1.0
@license Eclipse Public License
"""

# mpd settings
HOST = "localhost"
PORT = "6600"
PASSWORD = None

# time to update
CACHED_TIME = 1

# position
POSITION = 1

# if text length will be greater - it'll shrink it
MAX_WIDTH = 120

# hide any indicator, if
HIDE_WHEN_PAUSED = False
HIDE_WHEN_STOPPED = True

# state characters (or strings). Actual of them replaces {state} placeholder in STRFORMAT
STATE_CHARACTERS = {
    "pause": "[pause]",
    "play": "[play]",
    "stop": "[stop]",
}

""" format of result string
can contain: 
    {state} - current state from STATE_CHARACTERS
    Track information:
    {track}, {artist}, {title}, {time}, {album}, {pos}
    In additional, information about next track also comes in, in analogue with current, but with next_ prefix,
    like {next_title}
"""
STRFORMAT = "{state} {pos}. {artist} - {title} [{time}] | {next_title}"

class Py3status:
    def __init__(self, *args, **kwargs):
        self.text = ""
        super(Py3status).__init__(*args, **kwargs)

    def currentTrack(self, i3status_output_json, i3status_config):
        try: 
            c = MPDClient()
            c.connect(host=HOST, port=PORT)
            if PASSWORD:
                c.password(PASSWORD)

            status = c.status()
            song = int(status.get("song", 0))
            next_song = int(status.get("nextsong", 0))

            if (status["state"] == "pause" and HIDE_WHEN_PAUSED) or (status["state"] == "stop" and HIDE_WHEN_STOPPED):
                text = ""
            else:
                try:
                    song = c.playlistinfo()[song]
                    song["time"] = "{0:.2f}".format(int(song.get("time", 1)) / 60)
                except IndexError:
                    song = {}

                try:
                    next_song = c.playlistinfo()[next_song]
                except IndexError:
                    next_song = {}

                format_args = song
                format_args["state"] = STATE_CHARACTERS.get(status.get("state", None))
                for k, v in next_song.items():
                    format_args["next_{}".format(k)] = v

                text = STRFORMAT
                for k, v in format_args.items():
                    text = text.replace("{" + k + "}", v)

                for sub in re.findall(r"{\S+?}", text):
                    text = text.replace(sub, "")
        except SocketError:
            text = "Failed to connect to mpd!"
        except CommandError:
            text = "Failed to authenticate to mpd!"
            c.disconnect()

        if len(text) > MAX_WIDTH:
            text = text[-MAX_WIDTH-3:] + "..."

        if self.text != text:
            transformed = True
            self.text = text
        else:
            transformed = False

        return (POSITION, {
                    'transformed': transformed,
                    'full_text': self.text,
                    'name': 'scratchpad-count', 
                    'cached_until': time.time() + CACHED_TIME,
                    })