aboutsummaryrefslogtreecommitdiffstats
path: root/music_update.py
diff options
context:
space:
mode:
Diffstat (limited to 'music_update.py')
-rwxr-xr-xmusic_update.py302
1 files changed, 0 insertions, 302 deletions
diff --git a/music_update.py b/music_update.py
deleted file mode 100755
index d9f14c3..0000000
--- a/music_update.py
+++ /dev/null
@@ -1,302 +0,0 @@
1#!/usr/bin/python
2
3import sys
4import asyncio
5import re
6import threading
7import argparse
8import signal
9
10from blessed import Terminal
11
12import dbussy as dbus
13import ravel
14
15
16loop = asyncio.get_event_loop()
17name_regex = re.compile("^org\.mpris\.MediaPlayer2\.")
18
19bus = None
20term = Terminal()
21refresh_cond = threading.Condition()
22refresh_flag = True
23exit_flag = False
24exit_task = asyncio.Future()
25
26players = []
27player_id_to_index = {}
28active_player = ""
29current_output = ""
30
31filename = ""
32meta_format = ""
33meta_format_artist = ""
34meta_format_title = ""
35meta_format_album = ""
36
37
38def track_string(metadata):
39 artist = metadata["xesam:artist"][1][0] if "xesam:artist" in metadata else ""
40 title = metadata["xesam:title"][1] if "xesam:title" in metadata else ""
41 album = metadata["xesam:album"][1] if "xesam:album" in metadata else ""
42
43 return meta_format.format(
44 artist = meta_format_artist.format(artist) if artist != "" else "",
45 title = meta_format_title.format(title) if title != "" else "",
46 album = meta_format_album.format(album) if title != "" else ""
47 )
48
49
50def write_track(track):
51 global filename
52 global current_output
53
54 current_output = track
55 f = open(filename, "w")
56 f.write(track)
57 f.close()
58
59
60@ravel.signal(name = "PropertiesChanged", in_signature = "sa{sv}as", args_keyword = "args")
61def playing_song_changed(args):
62 global refresh_cond
63 global refresh_flag
64
65 [ player, changed_properties, invalidated_properties ] = args
66 if "Metadata" in changed_properties:
67 write_track(track_string(changed_properties["Metadata"][1]))
68 with refresh_cond:
69 refresh_flag = True
70 refresh_cond.notify()
71
72
73@ravel.signal(name = "NameOwnerChanged", in_signature = "sss", args_keyword = "args")
74def dbus_name_owner_changed(args):
75 global refresh_cond
76 global refresh_flag
77
78 [ name, old_owner, new_owner ] = args
79 if name_regex.match(name):
80 get_players()
81 with refresh_cond:
82 refresh_flag = True
83 refresh_cond.notify()
84
85
86def set_active_player(player_id):
87 global bus
88 global active_player
89
90 if player_id in player_id_to_index:
91 active_player = player_id
92 elif len(player_id_to_index) != 0:
93 active_player = next(iter(player_id_to_index))
94 else:
95 active_player = ""
96
97 for (name, player_id) in players:
98 bus.unlisten_propchanged(
99 path = "/org/mpris/MediaPlayer2",
100 interface = name,
101 func = playing_song_changed,
102 fallback = True
103 )
104
105 if active_player != "":
106 bus.listen_propchanged(
107 path = "/org/mpris/MediaPlayer2",
108 interface = active_player,
109 func = playing_song_changed,
110 fallback = True
111 )
112
113 player_path = bus[active_player]["/org/mpris/MediaPlayer2"]
114 player_props = player_path.get_interface("org.freedesktop.DBus.Properties")
115
116 write_track(track_string(player_props.Get("org.mpris.MediaPlayer2.Player", "Metadata")[0][1]))
117 else:
118 write_track("")
119
120
121def get_players():
122 global players
123 global player_id_to_index
124
125 players = []
126 player_id_to_index = {}
127 bus_proxy = bus["org.freedesktop.DBus"]["/org/freedesktop/DBus"].get_interface("org.freedesktop.DBus")
128 names = bus_proxy.ListNames()
129
130 for name in names[0]:
131 if name_regex.match(name):
132 split_name = name.split(".")
133 id_start_index = len(split_name[0]) + len(split_name[1]) + len(split_name[2]) + 3
134
135 player_path = bus[name]["/org/mpris/MediaPlayer2"]
136 player_proxy = player_path.get_interface("org.mpris.MediaPlayer2")
137 player_id = name[id_start_index:]
138 try:
139 player_id = player_proxy.Identity
140 except AttributeError:
141 pass
142
143 players.append((name, player_id))
144 player_id_to_index[name] = len(players) - 1
145
146 set_active_player(active_player)
147
148
149def draw_menu():
150 global term
151 global players
152 global refresh_cond
153 global refresh_flag
154 global exit_flag
155 global current_output
156 global filename
157
158 while not exit_flag:
159 with refresh_cond:
160 while not refresh_flag and not exit_flag:
161 refresh_cond.wait()
162
163 refresh_flag = False
164
165 with term.fullscreen():
166 print(term.move(0, 0) + term.bold_bright_white_on_bright_black(("{0:<{width}}").format("MPRIS To Text", width=term.width)) + "\n")
167 print(term.move_x(2) + term.bold("Player: ") + term.move_up())
168
169 for i in range(len(players)):
170 player = players[i]
171 output = "%d: %s" % (i, player[1])
172
173 if players[player_id_to_index[active_player]][0] == player[0]:
174 print(term.move_x(10) + term.standout(output))
175 else:
176 print(term.move_x(10) + output)
177
178 print(term.move_x(2) + term.bold("File: ") + filename)
179 print(term.move_x(2) + term.bold("Output: ") + "\n".join(term.wrap(current_output, width=term.width - 10, subsequent_indent=" " * 10)))
180
181 print(term.move_x(0) + "\nEnter number to select player or q to exit." + term.move_up())
182
183 with term.fullscreen():
184 print(term.move(0, 0) + "Exiting...")
185
186
187def on_resize(*args):
188 global refresh_cond
189 global refresh_flag
190
191 with refresh_cond:
192 refresh_flag = True
193 refresh_cond.notify()
194
195
196def init_dbus():
197 global bus
198 global loop
199
200 bus = ravel.session_bus()
201 bus.attach_asyncio(loop)
202 bus.listen_signal(
203 path = "/org/freedesktop/DBus",
204 interface = "org.freedesktop.DBus",
205 name = "NameOwnerChanged",
206 func = dbus_name_owner_changed,
207 fallback = True
208 )
209
210 get_players()
211
212
213def init_blessed():
214 global bus
215 global term
216 global refresh_cond
217 global refresh_flag
218 global exit_flag
219
220 with term.cbreak():
221 val = None
222
223 while val not in (u'q', u'Q',):
224 val = term.inkey(timeout=5)
225
226 if not val or val.is_sequence or not val.isnumeric():
227 continue
228
229 if int(val) < len(players):
230 set_active_player(players[int(val)][0])
231 with refresh_cond:
232 refresh_flag = True
233 refresh_cond.notify()
234
235 with refresh_cond:
236 exit_flag = True
237 refresh_cond.notify()
238
239 exit_task.set_result(True)
240
241
242def read_args():
243 global filename
244 global meta_format
245 global meta_format_artist
246 global meta_format_title
247 global meta_format_album
248
249 parser = argparse.ArgumentParser(description="Write metadata from MPRIS-compliant media players into a text file.")
250 parser.add_argument("--file",
251 type = str,
252 dest = "filename",
253 default = "/tmp/mpris_info.txt",
254 help = "Full path to file (default: \"/tmp/mpris_info.txt\")"
255 )
256 parser.add_argument("--format-order",
257 type = str,
258 dest = "format",
259 default = "{artist}{title}{album} ",
260 help = "Format string (default: \"{artist}{title}{album} \")"
261 )
262 parser.add_argument("--format-artist",
263 type = str,
264 dest = "format_artist",
265 default = "{} ",
266 help = "Format string for the artist part (default: \"{} \")"
267 )
268 parser.add_argument("--format-title",
269 type = str,
270 dest = "format_title",
271 default = "\"{}\"",
272 help = "Format string for the title part (default: \"\"{}\"\")"
273 )
274 parser.add_argument("--format-album",
275 type = str,
276 dest = "format_album",
277 default = " from \"{}\"",
278 help = "Format string for the album part (default: \" from \"{}\"\")"
279 )
280
281 args = parser.parse_args()
282 filename = args.filename
283 meta_format = args.format
284 meta_format_artist = args.format_artist
285 meta_format_title = args.format_title
286 meta_format_album = args.format_album
287
288
289
290read_args()
291
292signal.signal(signal.SIGWINCH, on_resize)
293
294init_dbus()
295
296blessed_thread = threading.Thread(target=init_blessed)
297blessed_thread.start()
298
299menu_thread = threading.Thread(target=draw_menu)
300menu_thread.start()
301
302loop.run_until_complete(exit_task)