-
Notifications
You must be signed in to change notification settings - Fork 1
/
linux_server.py
183 lines (142 loc) · 5.97 KB
/
linux_server.py
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#! /usr/bin/python3
from flask import Flask, json, Response
from dbus.mainloop.glib import DBusGMainLoop
from mpris2 import get_players_uri, Player
import platform
import sys
import config
uri = None # pylint: disable=invalid-name
player = None # pylint: disable=invalid-name
api_info = {}
playing_state = {}
DBusGMainLoop(set_as_default=True)
api = Flask(__name__)
def api_info_update():
temp_api_info = {}
temp_api_info["platform"] = platform.system()
temp_api_info["version"] = config.VERSION
temp_api_info["python_version"] = platform.python_version()
global api_info # pylint: disable=invalid-name
api_info = temp_api_info
return api_info
def init_player():
try:
# Get MPRIS client
for client in get_players_uri():
# If the config specifies to ignore Chrome MPRIS
if config.IGNORE_CHROME_MPRIS:
# If the first MPRIS client is a Chrome instance
if client.startswith('org.mpris.MediaPlayer2.chrome'):
continue
# Set the MPRIS uri to the active element
global uri # pylint: disable=invalid-name
uri = client
break
# Initialize player with URI
global player # pylint: disable=invalid-name
player = Player(dbus_interface_info={'dbus_uri': uri}) # pylint: disable=unexpected-keyword-arg
# Everything worked, the player has been successfully initialized
return True
except:
e = sys.exc_info()[0]
# Something went wrong, the player has not been initialized
# Returns information about the error
return e
# Route for API info endpoint
@api.route('/api_info', methods=['GET'])
def get_api_info():
# Return a stringified JSON object from the output of the function
return Response(json.dumps(api_info_update()), mimetype='application/json')
# Route for Ping endpoint
@api.route('/ping', methods=['GET'])
def get_ping():
return "Pong"
# Route for playing endpoint
@api.route('/playing_state', methods=['GET'])
def get_playing_state():
if not init_player(): # If the player cannot be initialized
return Response(json.dumps(playing_state), mimetype='application/json', status=504)
# Add URI and platform to playing_state
playing_state["uri"] = uri
playing_state["platform"] = "Linux"
# Try to add all fields to the playing_state object of the Metadata of the player
endpoints_meta = ["TITLE", "ARTIST", "ALBUM", "ART_URI", "LENGTH"]
ends_var_meta = ["title", "artist", "album", "artwork", "length"]
for endpoint in endpoints_meta:
end_var = ends_var_meta[endpoints_meta.index(endpoint)]
try:
if endpoint == "ARTIST":
playing_state[end_var] = str(player.Metadata[getattr(player.Metadata, endpoint)][0])
continue
playing_state[end_var] = str(player.Metadata[getattr(player.Metadata, endpoint)])
# Workaround to get working Spotify covers URL
if endpoint == "ART_URI" and "open.spotify.com" in str(playing_state[end_var]):
playing_state[end_var] = playing_state[end_var].replace('open.spotify.com', 'i.scdn.co')
except:
pass
# Try to add all fields to the playing_state object of the player
endpoints_player = ["Position", "PlaybackStatus", "Volume"]
ends_var_player = ["position", "status", "volume"]
for endpoint in endpoints_player:
end_var = ends_var_player[endpoints_player.index(endpoint)]
try:
if str(player.Position) == "0":
continue
playing_state[end_var] = str(getattr(player, endpoint))
except:
pass
# Add all player abilities to the playing_state object
playing_state["config"] = [{}]
configs_player = ["CanPause", "CanPlay", "CanSeek"]
conf_var_player = ["canPause", "canPlay", "canSeek"]
for config_item in configs_player:
conf_var = conf_var_player[configs_player.index(config_item)]
try:
playing_state["config"][0][conf_var] = bool(getattr(player, config_item))
except:
pass
# Return a stringified JSON object
return Response(json.dumps(playing_state), mimetype='application/json')
@api.route('/control/next', methods=['POST'])
def next_song():
init_player()
try:
player.Next()
return Response(json.dumps({"success": True}), mimetype='application/json', status=201)
except:
return Response(json.dumps({"success": False}), mimetype='application/json', status=502)
@api.route('/control/previous', methods=['POST'])
def previous_song():
init_player()
try:
player.Previous()
return Response(json.dumps({"success": True}), mimetype='application/json', status=201)
except:
return Response(json.dumps({"success": False}), mimetype='application/json', status=502)
@api.route('/control/play', methods=['POST'])
def resume_song():
init_player()
try:
player.Play()
return Response(json.dumps({"success": True}), mimetype='application/json', status=201)
except:
return Response(json.dumps({"success": False}), mimetype='application/json', status=502)
@api.route('/control/pause', methods=['POST'])
def pause_song():
init_player()
try:
player.Pause()
return Response(json.dumps({"success": True}), mimetype='application/json', status=201)
except:
return Response(json.dumps({"success": False}), mimetype='application/json', status=502)
@api.route('/control/playpause', methods=['POST'])
def playpause_song():
init_player()
try:
player.PlayPause()
return Response(json.dumps({"success": True}), mimetype='application/json', status=201)
except:
return Response(json.dumps({"success": False}), mimetype='application/json', status=502)
# Initialize API on host 0.0.0.0 and port 5175
# If you want to debug using Flask, edit the config file
api.run(host=config.HOST, port=config.PORT, debug=config.DEBUG)