Changeset View
Changeset View
Standalone View
Standalone View
plugins/mprisremote/mprisremoteplugin.cpp
Show All 29 Lines | |||||
30 | #include <core/device.h> | 30 | #include <core/device.h> | ||
31 | 31 | | |||
32 | K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_mprisremote.json", registerPlugin< MprisRemotePlugin >(); ) | 32 | K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_mprisremote.json", registerPlugin< MprisRemotePlugin >(); ) | ||
33 | 33 | | |||
34 | Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_MPRISREMOTE, "kdeconnect.plugin.mprisremote") | 34 | Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_MPRISREMOTE, "kdeconnect.plugin.mprisremote") | ||
35 | 35 | | |||
36 | MprisRemotePlugin::MprisRemotePlugin(QObject* parent, const QVariantList& args) | 36 | MprisRemotePlugin::MprisRemotePlugin(QObject* parent, const QVariantList& args) | ||
37 | : KdeConnectPlugin(parent, args) | 37 | : KdeConnectPlugin(parent, args) | ||
38 | , m_player() | 38 | , m_currentPlayer() | ||
39 | , m_playing(false) | 39 | , m_players() | ||
40 | , m_nowPlaying() | | |||
41 | , m_volume(50) | | |||
42 | , m_length(0) | | |||
43 | , m_lastPosition(0) | | |||
44 | , m_lastPositionTime() | | |||
45 | , m_playerList() | | |||
46 | { | 40 | { | ||
47 | } | 41 | } | ||
48 | 42 | | |||
49 | MprisRemotePlugin::~MprisRemotePlugin() | 43 | MprisRemotePlugin::~MprisRemotePlugin() | ||
50 | { | 44 | { | ||
51 | } | 45 | } | ||
52 | 46 | | |||
53 | bool MprisRemotePlugin::receivePacket(const NetworkPacket& np) | 47 | bool MprisRemotePlugin::receivePacket(const NetworkPacket& np) | ||
54 | { | 48 | { | ||
55 | if (np.type() != PACKET_TYPE_MPRIS) | 49 | if (np.type() != PACKET_TYPE_MPRIS) | ||
56 | return false; | 50 | return false; | ||
57 | 51 | | |||
58 | if (np.has(QStringLiteral("nowPlaying")) || np.has(QStringLiteral("volume")) || np.has(QStringLiteral("isPlaying")) || np.has(QStringLiteral("length")) || np.has(QStringLiteral("pos"))) { | 52 | if (np.has(QStringLiteral("player"))) { | ||
59 | if (np.get<QString>(QStringLiteral("player")) == m_player) { | 53 | m_players[m_currentPlayer]->parseNetworkPacket(np); | ||
60 | m_nowPlaying = np.get<QString>(QStringLiteral("nowPlaying"), m_nowPlaying); | | |||
61 | m_volume = np.get<int>(QStringLiteral("volume"), m_volume); | | |||
62 | m_length = np.get<int>(QStringLiteral("length"), m_length); | | |||
63 | if(np.has(QStringLiteral("pos"))){ | | |||
64 | m_lastPosition = np.get<int>(QStringLiteral("pos"), m_lastPosition); | | |||
65 | m_lastPositionTime = QDateTime::currentMSecsSinceEpoch(); | | |||
66 | } | 54 | } | ||
67 | m_playing = np.get<bool>(QStringLiteral("isPlaying"), m_playing); | 55 | | ||
56 | if (np.has(QStringLiteral("playerList"))) { | ||||
57 | QStringList players = np.get<QStringList>(QStringLiteral("playerList")); | ||||
58 | qDeleteAll(m_players); | ||||
59 | m_players.clear(); | ||||
60 | for (const QString& player : players) { | ||||
61 | m_players[player] = new MprisRemotePlayer(); | ||||
68 | } | 62 | } | ||
63 | | ||||
64 | if (m_players.empty()) { | ||||
65 | m_currentPlayer = QString(); | ||||
66 | } else if (!m_players.contains(m_currentPlayer)) { | ||||
67 | m_currentPlayer = m_players.keys().first(); | ||||
69 | } | 68 | } | ||
70 | 69 | | |||
71 | if (np.has(QStringLiteral("playerList"))) { | | |||
72 | m_playerList = np.get<QStringList>(QStringLiteral("playerList"), QStringList()); | | |||
73 | } | 70 | } | ||
74 | Q_EMIT propertiesChanged(); | 71 | Q_EMIT propertiesChanged(); | ||
75 | 72 | | |||
76 | return true; | 73 | return true; | ||
77 | } | 74 | } | ||
78 | 75 | | |||
79 | long MprisRemotePlugin::position() const | 76 | long MprisRemotePlugin::position() const | ||
80 | { | 77 | { | ||
81 | if(m_playing) { | 78 | if (m_currentPlayer.isEmpty()) | ||
82 | return m_lastPosition + (QDateTime::currentMSecsSinceEpoch() - m_lastPositionTime); | 79 | return 0; | ||
83 | } else { | 80 | | ||
84 | return m_lastPosition; | 81 | return m_players[m_currentPlayer]->position(); | ||
85 | } | | |||
86 | } | 82 | } | ||
87 | 83 | | |||
88 | QString MprisRemotePlugin::dbusPath() const | 84 | QString MprisRemotePlugin::dbusPath() const | ||
89 | { | 85 | { | ||
90 | return "/modules/kdeconnect/devices/" + device()->id() + "/mprisremote"; | 86 | return "/modules/kdeconnect/devices/" + device()->id() + "/mprisremote"; | ||
91 | } | 87 | } | ||
92 | 88 | | |||
93 | void MprisRemotePlugin::requestPlayerStatus() | 89 | void MprisRemotePlugin::requestPlayerStatus() | ||
94 | { | 90 | { | ||
95 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | 91 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | ||
96 | {"player", m_player}, | 92 | {"player", m_currentPlayer}, | ||
97 | {"requestNowPlaying", true}, | 93 | {"requestNowPlaying", true}, | ||
98 | {"requestVolume", true}} | 94 | {"requestVolume", true}} | ||
99 | ); | 95 | ); | ||
100 | sendPacket(np); | 96 | sendPacket(np); | ||
101 | } | 97 | } | ||
102 | 98 | | |||
103 | void MprisRemotePlugin::requestPlayerList() | 99 | void MprisRemotePlugin::requestPlayerList() | ||
104 | { | 100 | { | ||
105 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, {{"requestPlayerList", true}}); | 101 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, {{"requestPlayerList", true}}); | ||
106 | sendPacket(np); | 102 | sendPacket(np); | ||
107 | } | 103 | } | ||
108 | 104 | | |||
109 | void MprisRemotePlugin::sendAction(const QString& action) | 105 | void MprisRemotePlugin::sendAction(const QString& action) | ||
110 | { | 106 | { | ||
111 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | 107 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | ||
112 | {"player", m_player}, | 108 | {"player", m_currentPlayer}, | ||
113 | {"action", action} | 109 | {"action", action} | ||
114 | }); | 110 | }); | ||
115 | sendPacket(np); | 111 | sendPacket(np); | ||
116 | } | 112 | } | ||
117 | 113 | | |||
118 | void MprisRemotePlugin::seek(int offset) const | 114 | void MprisRemotePlugin::seek(int offset) const | ||
119 | { | 115 | { | ||
120 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | 116 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | ||
121 | {"player", m_player}, | 117 | {"player", m_currentPlayer}, | ||
122 | {"Seek", offset}}); | 118 | {"Seek", offset}}); | ||
123 | sendPacket(np); | 119 | sendPacket(np); | ||
124 | } | 120 | } | ||
125 | 121 | | |||
126 | void MprisRemotePlugin::setVolume(int volume) | 122 | void MprisRemotePlugin::setVolume(int volume) | ||
127 | { | 123 | { | ||
128 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | 124 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | ||
129 | {"player", m_player}, | 125 | {"player", m_currentPlayer}, | ||
130 | {"setVolume",volume} | 126 | {"setVolume",volume} | ||
131 | }); | 127 | }); | ||
132 | sendPacket(np); | 128 | sendPacket(np); | ||
133 | } | 129 | } | ||
134 | 130 | | |||
135 | void MprisRemotePlugin::setPosition(int position) | 131 | void MprisRemotePlugin::setPosition(int position) | ||
136 | { | 132 | { | ||
137 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | 133 | NetworkPacket np(PACKET_TYPE_MPRIS_REQUEST, { | ||
138 | {"player", m_player}, | 134 | {"player", m_currentPlayer}, | ||
139 | {"SetPosition", position} | 135 | {"SetPosition", position} | ||
140 | }); | 136 | }); | ||
141 | sendPacket(np); | 137 | sendPacket(np); | ||
142 | 138 | | |||
143 | m_lastPosition = position; | 139 | m_players[m_currentPlayer]->setPosition(position); | ||
144 | m_lastPositionTime = QDateTime::currentMSecsSinceEpoch(); | | |||
145 | } | 140 | } | ||
146 | 141 | | |||
147 | void MprisRemotePlugin::setPlayer(const QString& player) | 142 | void MprisRemotePlugin::setPlayer(const QString& player) | ||
148 | { | 143 | { | ||
149 | if (m_player != player) { | 144 | if (m_currentPlayer != player) { | ||
150 | m_player = player; | 145 | m_currentPlayer = player; | ||
151 | requestPlayerStatus(); | 146 | requestPlayerStatus(); | ||
147 | Q_EMIT propertiesChanged(); | ||||
148 | } | ||||
149 | } | ||||
150 | | ||||
151 | bool MprisRemotePlugin::isPlaying() const | ||||
152 | { | ||||
153 | if (m_currentPlayer.isEmpty()) | ||||
154 | return false; | ||||
155 | | ||||
156 | return m_players[m_currentPlayer]->playing(); | ||||
157 | } | ||||
158 | | ||||
159 | int MprisRemotePlugin::length() const | ||||
160 | { | ||||
161 | if (m_currentPlayer.isEmpty()) | ||||
162 | return 0; | ||||
163 | | ||||
164 | return m_players[m_currentPlayer]->length(); | ||||
165 | } | ||||
166 | | ||||
167 | int MprisRemotePlugin::volume() const | ||||
168 | { | ||||
169 | if (m_currentPlayer.isEmpty()) | ||||
170 | return 0; | ||||
171 | | ||||
172 | return m_players[m_currentPlayer]->volume(); | ||||
152 | } | 173 | } | ||
174 | | ||||
175 | QString MprisRemotePlugin::player() const | ||||
176 | { | ||||
177 | if (m_currentPlayer.isEmpty()) | ||||
178 | return QString(); | ||||
179 | | ||||
180 | return m_currentPlayer; | ||||
181 | } | ||||
182 | | ||||
183 | QStringList MprisRemotePlugin::playerList() const | ||||
184 | { | ||||
185 | return m_players.keys(); | ||||
186 | } | ||||
187 | | ||||
188 | QString MprisRemotePlugin::nowPlaying() const | ||||
189 | { | ||||
190 | if (m_currentPlayer.isEmpty()) | ||||
191 | return QString(); | ||||
192 | | ||||
193 | return m_players[m_currentPlayer]->nowPlaying(); | ||||
194 | } | ||||
195 | | ||||
196 | QString MprisRemotePlugin::title() const | ||||
197 | { | ||||
198 | if (m_currentPlayer.isEmpty()) | ||||
199 | return QString(); | ||||
200 | | ||||
201 | return m_players[m_currentPlayer]->title(); | ||||
202 | } | ||||
203 | | ||||
204 | QString MprisRemotePlugin::album() const | ||||
205 | { | ||||
206 | if (m_currentPlayer.isEmpty()) | ||||
apol: While this will work, if the map ever gets out of sync we could get a crash.
Maybe it's just… | |||||
207 | return QString(); | ||||
208 | | ||||
209 | return m_players[m_currentPlayer]->album(); | ||||
210 | } | ||||
211 | QString MprisRemotePlugin::artist() const | ||||
212 | { | ||||
213 | if (m_currentPlayer.isEmpty()) | ||||
214 | return QString(); | ||||
215 | | ||||
216 | return m_players[m_currentPlayer]->artist(); | ||||
153 | } | 217 | } | ||
154 | 218 | | |||
155 | #include "mprisremoteplugin.moc" | 219 | #include "mprisremoteplugin.moc" |
While this will work, if the map ever gets out of sync we could get a crash.
Maybe it's just safer to do something like: