aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--README.md1
-rwxr-xr-xmpris_to_text.py102
3 files changed, 50 insertions, 54 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..600d2d3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
.vscode \ No newline at end of file
diff --git a/README.md b/README.md
index 90251b7..7611ab9 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,6 @@ A Python script that fetches media data from MPRIS-compliant media players and s
7## Required packages 7## Required packages
8 8
9- [blessed](https://github.com/jquast/blessed): Terminal UI 9- [blessed](https://github.com/jquast/blessed): Terminal UI
10- [dbussy](https://github.com/ldo/dbussy): DBus client
11 10
12## Parameters 11## Parameters
13 12
diff --git a/mpris_to_text.py b/mpris_to_text.py
index 1284300..16ee1e0 100755
--- a/mpris_to_text.py
+++ b/mpris_to_text.py
@@ -1,31 +1,34 @@
1#!/usr/bin/python 1#!/usr/bin/python
2 2
3import sys 3import sys
4import asyncio
5import re 4import re
6import threading 5import threading
7import argparse 6import argparse
8import signal 7import signal
9 8
9import dbus
10import dbus.mainloop.glib
11from gi.repository import GLib
12
10from blessed import Terminal 13from blessed import Terminal
11 14
12import ravel 15
16dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
13 17
14 18
15loop = asyncio.get_event_loop()
16name_regex = re.compile("^org\.mpris\.MediaPlayer2\.") 19name_regex = re.compile("^org\.mpris\.MediaPlayer2\.")
17bus = None 20bus = dbus.SessionBus()
18term = Terminal() 21term = Terminal()
19 22
20refresh_cond = threading.Condition() 23refresh_cond = threading.Condition()
21refresh_flag = True 24refresh_flag = True
22exit_flag = False 25exit_flag = False
23exit_task = asyncio.Future()
24 26
25players = [] 27players = []
26player_id_to_index = {} 28player_id_to_index = {}
27active_player = "" 29active_player = ""
28current_output = "" 30current_output = ""
31playing_song_changed_signal_receiver = None
29 32
30filename = "" 33filename = ""
31meta_format = "" 34meta_format = ""
@@ -35,14 +38,14 @@ meta_format_album = ""
35 38
36 39
37def track_string(metadata): 40def track_string(metadata):
38 artist = metadata["xesam:artist"][1][0] if "xesam:artist" in metadata else "" 41 artist = metadata["xesam:artist"][0] if "xesam:artist" in metadata else ""
39 title = metadata["xesam:title"][1] if "xesam:title" in metadata else "" 42 title = metadata["xesam:title"] if "xesam:title" in metadata else ""
40 album = metadata["xesam:album"][1] if "xesam:album" in metadata else "" 43 album = metadata["xesam:album"] if "xesam:album" in metadata else ""
41 44
42 return meta_format.format( 45 return meta_format.format(
43 artist = meta_format_artist.format(artist) if artist != "" else "", 46 artist = meta_format_artist.format(artist) if artist != "" else "",
44 title = meta_format_title.format(title) if title != "" else "", 47 title = meta_format_title.format(title) if title != "" else "",
45 album = meta_format_album.format(album) if title != "" else "" 48 album = meta_format_album.format(album) if album != "" else ""
46 ) 49 )
47 50
48 51
@@ -56,25 +59,21 @@ def write_track(track):
56 f.close() 59 f.close()
57 60
58 61
59@ravel.signal(name = "PropertiesChanged", in_signature = "sa{sv}as", args_keyword = "args") 62def playing_song_changed(player, changed_properties, invalidated_properties):
60def playing_song_changed(args):
61 global refresh_cond 63 global refresh_cond
62 global refresh_flag 64 global refresh_flag
63 65
64 [ player, changed_properties, invalidated_properties ] = args
65 if "Metadata" in changed_properties: 66 if "Metadata" in changed_properties:
66 write_track(track_string(changed_properties["Metadata"][1])) 67 write_track(track_string(changed_properties["Metadata"]))
67 with refresh_cond: 68 with refresh_cond:
68 refresh_flag = True 69 refresh_flag = True
69 refresh_cond.notify() 70 refresh_cond.notify()
70 71
71 72
72@ravel.signal(name = "NameOwnerChanged", in_signature = "sss", args_keyword = "args") 73def dbus_name_owner_changed(name, old_owner, new_owner):
73def dbus_name_owner_changed(args):
74 global refresh_cond 74 global refresh_cond
75 global refresh_flag 75 global refresh_flag
76 76
77 [ name, old_owner, new_owner ] = args
78 if name_regex.match(name): 77 if name_regex.match(name):
79 get_players() 78 get_players()
80 with refresh_cond: 79 with refresh_cond:
@@ -84,7 +83,10 @@ def dbus_name_owner_changed(args):
84 83
85def set_active_player(player_id): 84def set_active_player(player_id):
86 global bus 85 global bus
86 global players
87 global player_id_to_index
87 global active_player 88 global active_player
89 global playing_song_changed_signal_receiver
88 90
89 if player_id in player_id_to_index: 91 if player_id in player_id_to_index:
90 active_player = player_id 92 active_player = player_id
@@ -93,26 +95,22 @@ def set_active_player(player_id):
93 else: 95 else:
94 active_player = "" 96 active_player = ""
95 97
96 for (name, player_id) in players: 98 if playing_song_changed_signal_receiver is not None:
97 bus.unlisten_propchanged( 99 playing_song_changed_signal_receiver.remove()
98 path = "/org/mpris/MediaPlayer2",
99 interface = name,
100 func = playing_song_changed,
101 fallback = True
102 )
103 100
104 if active_player != "": 101 if active_player != "":
105 bus.listen_propchanged( 102 playing_song_changed_signal_receiver = bus.add_signal_receiver(
106 path = "/org/mpris/MediaPlayer2", 103 handler_function = playing_song_changed,
107 interface = active_player, 104 bus_name = active_player,
108 func = playing_song_changed, 105 dbus_interface = "org.freedesktop.DBus.Properties",
109 fallback = True 106 signal_name = "PropertiesChanged",
107 path = "/org/mpris/MediaPlayer2"
110 ) 108 )
111 109
112 player_path = bus[active_player]["/org/mpris/MediaPlayer2"] 110 player_path = bus.get_object(active_player, "/org/mpris/MediaPlayer2")
113 player_props = player_path.get_interface("org.freedesktop.DBus.Properties") 111 player_props = dbus.Interface(player_path, "org.freedesktop.DBus.Properties")
114 112
115 write_track(track_string(player_props.Get("org.mpris.MediaPlayer2.Player", "Metadata")[0][1])) 113 write_track(track_string(player_props.Get("org.mpris.MediaPlayer2.Player", "Metadata")))
116 else: 114 else:
117 write_track("") 115 write_track("")
118 116
@@ -120,23 +118,25 @@ def set_active_player(player_id):
120def get_players(): 118def get_players():
121 global players 119 global players
122 global player_id_to_index 120 global player_id_to_index
121 global active_player
123 122
124 players = [] 123 players = []
125 player_id_to_index = {} 124 player_id_to_index = {}
126 bus_proxy = bus["org.freedesktop.DBus"]["/org/freedesktop/DBus"].get_interface("org.freedesktop.DBus") 125 bus_path = bus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus")
126 bus_proxy = dbus.Interface(bus_path, "org.freedesktop.DBus")
127 names = bus_proxy.ListNames() 127 names = bus_proxy.ListNames()
128 128
129 for name in names[0]: 129 for name in names:
130 if name_regex.match(name): 130 if name_regex.match(name):
131 split_name = name.split(".") 131 split_name = name.split(".")
132 id_start_index = len(split_name[0]) + len(split_name[1]) + len(split_name[2]) + 3 132 id_start_index = len(split_name[0]) + len(split_name[1]) + len(split_name[2]) + 3
133 133
134 player_path = bus[name]["/org/mpris/MediaPlayer2"] 134 player_path = bus.get_object(name, "/org/mpris/MediaPlayer2")
135 player_proxy = player_path.get_interface("org.mpris.MediaPlayer2") 135 player_props = dbus.Interface(player_path, "org.freedesktop.DBus.Properties")
136 player_id = name[id_start_index:] 136 player_id = name[id_start_index:]
137 try: 137 try:
138 player_id = player_proxy.Identity 138 player_id = player_props.Get("org.mpris.MediaPlayer2.Player", "Identity")
139 except AttributeError: 139 except dbus.exceptions.DBusException:
140 pass 140 pass
141 141
142 players.append((name, player_id)) 142 players.append((name, player_id))
@@ -194,17 +194,11 @@ def on_resize(*args):
194 194
195def init_dbus(): 195def init_dbus():
196 global bus 196 global bus
197 global loop
198 197
199 bus = ravel.session_bus() 198 bus_path = bus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus")
200 bus.attach_asyncio(loop) 199 bus_proxy = dbus.Interface(bus_path, "org.freedesktop.DBus")
201 bus.listen_signal( 200
202 path = "/org/freedesktop/DBus", 201 bus_proxy.connect_to_signal("NameOwnerChanged", dbus_name_owner_changed)
203 interface = "org.freedesktop.DBus",
204 name = "NameOwnerChanged",
205 func = dbus_name_owner_changed,
206 fallback = True
207 )
208 202
209 get_players() 203 get_players()
210 204
@@ -215,6 +209,7 @@ def init_blessed():
215 global refresh_cond 209 global refresh_cond
216 global refresh_flag 210 global refresh_flag
217 global exit_flag 211 global exit_flag
212 global loop
218 213
219 with term.cbreak(): 214 with term.cbreak():
220 val = None 215 val = None
@@ -235,7 +230,7 @@ def init_blessed():
235 exit_flag = True 230 exit_flag = True
236 refresh_cond.notify() 231 refresh_cond.notify()
237 232
238 exit_task.set_result(True) 233 loop.quit()
239 234
240 235
241def read_args(): 236def read_args():
@@ -298,4 +293,5 @@ blessed_thread.start()
298menu_thread = threading.Thread(target=draw_menu) 293menu_thread = threading.Thread(target=draw_menu)
299menu_thread.start() 294menu_thread.start()
300 295
301loop.run_until_complete(exit_task) 296loop = GLib.MainLoop()
297loop.run()