|
a/upmpd/ohplaylist.cxx |
|
b/upmpd/ohplaylist.cxx |
|
... |
|
... |
79 |
dev->addActionMapping(this, "Id",
|
79 |
dev->addActionMapping(this, "Id",
|
80 |
bind(&OHPlaylist::id, this, _1, _2));
|
80 |
bind(&OHPlaylist::id, this, _1, _2));
|
81 |
dev->addActionMapping(this, "Read",
|
81 |
dev->addActionMapping(this, "Read",
|
82 |
bind(&OHPlaylist::ohread, this, _1, _2));
|
82 |
bind(&OHPlaylist::ohread, this, _1, _2));
|
83 |
dev->addActionMapping(this, "ReadList",
|
83 |
dev->addActionMapping(this, "ReadList",
|
84 |
bind(&OHPlaylist::readlist, this, _1, _2));
|
84 |
bind(&OHPlaylist::readList, this, _1, _2));
|
85 |
dev->addActionMapping(this, "Insert",
|
85 |
dev->addActionMapping(this, "Insert",
|
86 |
bind(&OHPlaylist::insert, this, _1, _2));
|
86 |
bind(&OHPlaylist::insert, this, _1, _2));
|
87 |
dev->addActionMapping(this, "DeleteId",
|
87 |
dev->addActionMapping(this, "DeleteId",
|
88 |
bind(&OHPlaylist::deleteId, this, _1, _2));
|
88 |
bind(&OHPlaylist::deleteId, this, _1, _2));
|
89 |
dev->addActionMapping(this, "DeleteAll",
|
89 |
dev->addActionMapping(this, "DeleteAll",
|
|
... |
|
... |
123 |
tstate = "Stopped";
|
123 |
tstate = "Stopped";
|
124 |
}
|
124 |
}
|
125 |
return tstate;
|
125 |
return tstate;
|
126 |
}
|
126 |
}
|
127 |
|
127 |
|
128 |
// The data format for id lists is an array of msb 32b its ints
|
128 |
// The data format for id lists is an array of msb 32 bits ints
|
129 |
// encoded in base64...
|
129 |
// encoded in base64...
|
130 |
static string translateIdArray(const vector<unsigned int>& in)
|
130 |
static string translateIdArray(const vector<unsigned int>& in)
|
131 |
{
|
131 |
{
|
132 |
string out1;
|
132 |
string out1;
|
133 |
for (vector<unsigned int>::const_iterator it = in.begin();
|
133 |
string sdeb;
|
134 |
it != in.end(); it++) {
|
134 |
for (auto val : in) {
|
135 |
out1 += (unsigned char) (((*it) & 0xff000000) >> 24);
|
135 |
out1 += (unsigned char) ((val & 0xff000000) >> 24);
|
136 |
out1 += (unsigned char) ( ((*it) & 0x00ff0000) >> 16);
|
136 |
out1 += (unsigned char) ((val & 0x00ff0000) >> 16);
|
137 |
out1 += (unsigned char) ( ((*it) & 0x0000ff00) >> 8);
|
137 |
out1 += (unsigned char) ((val & 0x0000ff00) >> 8);
|
138 |
out1 += (unsigned char) ( (*it) & 0x000000ff);
|
138 |
out1 += (unsigned char) ((val & 0x000000ff));
|
|
|
139 |
//sdeb += makesint(val) + " ";
|
139 |
}
|
140 |
}
|
|
|
141 |
//LOGDEB("OHPlaylist: current ids: " << sdeb << endl);
|
140 |
return base64_encode(out1);
|
142 |
return base64_encode(out1);
|
141 |
}
|
143 |
}
|
142 |
|
|
|
143 |
string OHPlaylist::makeIdArray()
|
144 |
string OHPlaylist::makeIdArray()
|
144 |
{
|
145 |
{
|
145 |
string out;
|
146 |
string out;
|
146 |
vector<unsigned int> vids;
|
147 |
vector<unsigned int> vids;
|
|
|
148 |
// Retrieve the ids for current queue songs from mpd, and translate format
|
|
|
149 |
bool ok = m_dev->m_mpdcli->getQueueIds(vids);
|
|
|
150 |
if (ok) {
|
|
|
151 |
out = translateIdArray(vids);
|
|
|
152 |
}
|
|
|
153 |
|
|
|
154 |
// Clear metadata cache: entries not in vids are not valid any more
|
|
|
155 |
// We just build a new cache for data about current entries
|
147 |
unordered_map<int, string> nmeta;
|
156 |
unordered_map<int, string> nmeta;
|
148 |
bool ok = m_dev->m_mpdcli->getQueueIds(vids);
|
|
|
149 |
if (ok) {
|
|
|
150 |
out = translateIdArray(vids);
|
|
|
151 |
}
|
|
|
152 |
|
|
|
153 |
// Clear metadata cache: entries not in vids are not interesting
|
|
|
154 |
for (auto& id : vids) {
|
157 |
for (auto& id : vids) {
|
155 |
unordered_map<int, string>::iterator it1 = m_metacache.find(id);
|
158 |
auto inold = m_metacache.find(id);
|
156 |
if (it1 != m_metacache.end())
|
159 |
if (inold != m_metacache.end())
|
157 |
nmeta[id] = it1->second;
|
160 |
nmeta[id].swap(inold->second);
|
158 |
}
|
161 |
}
|
159 |
m_metacache = nmeta;
|
162 |
m_metacache = nmeta;
|
160 |
|
163 |
|
161 |
return out;
|
164 |
return out;
|
162 |
}
|
165 |
}
|
|
... |
|
... |
177 |
|
180 |
|
178 |
return true;
|
181 |
return true;
|
179 |
}
|
182 |
}
|
180 |
|
183 |
|
181 |
bool OHPlaylist::getEventData(bool all, std::vector<std::string>& names,
|
184 |
bool OHPlaylist::getEventData(bool all, std::vector<std::string>& names,
|
182 |
std::vector<std::string>& values)
|
185 |
std::vector<std::string>& values)
|
183 |
{
|
186 |
{
|
184 |
//LOGDEB("OHPlaylist::getEventData" << endl);
|
187 |
//LOGDEB("OHPlaylist::getEventData" << endl);
|
185 |
|
188 |
|
186 |
unordered_map<string, string> state;
|
189 |
unordered_map<string, string> state;
|
|
|
190 |
|
187 |
makestate(state);
|
191 |
makestate(state);
|
188 |
|
192 |
|
189 |
unordered_map<string, string> changed;
|
193 |
unordered_map<string, string> changed;
|
190 |
if (all) {
|
194 |
if (all) {
|
191 |
changed = state;
|
195 |
changed = state;
|
192 |
} else {
|
196 |
} else {
|
193 |
changed = diffmaps(m_state, state);
|
197 |
changed = diffmaps(m_state, state);
|
194 |
}
|
198 |
}
|
195 |
m_state = state;
|
199 |
m_state = state;
|
196 |
|
200 |
|
197 |
for (unordered_map<string, string>::iterator it = changed.begin();
|
201 |
for (auto& entry : changed) {
|
198 |
it != changed.end(); it++) {
|
|
|
199 |
names.push_back(it->first);
|
202 |
names.push_back(entry.first);
|
200 |
values.push_back(it->second);
|
203 |
values.push_back(entry.second);
|
201 |
}
|
204 |
}
|
202 |
|
205 |
|
203 |
return true;
|
206 |
return true;
|
204 |
}
|
207 |
}
|
205 |
|
208 |
|
|
... |
|
... |
387 |
UpSong song;
|
390 |
UpSong song;
|
388 |
if (ok) {
|
391 |
if (ok) {
|
389 |
ok = m_dev->m_mpdcli->statSong(song, id, true);
|
392 |
ok = m_dev->m_mpdcli->statSong(song, id, true);
|
390 |
}
|
393 |
}
|
391 |
if (ok) {
|
394 |
if (ok) {
|
392 |
unordered_map<int, string>::iterator mit = m_metacache.find(id);
|
395 |
auto cached = m_metacache.find(id);
|
393 |
string metadata;
|
396 |
string metadata;
|
394 |
if (mit != m_metacache.end()) {
|
397 |
if (cached != m_metacache.end()) {
|
395 |
metadata = xmlquote(mit->second);
|
398 |
metadata = SoapArgs::xmlQuote(cached->second);
|
396 |
} else {
|
399 |
} else {
|
397 |
metadata = xmlquote(didlmake(song));
|
400 |
metadata = SoapArgs::xmlQuote(didlmake(song));
|
398 |
}
|
401 |
}
|
399 |
data.addarg("Uri", song.uri);
|
402 |
data.addarg("Uri", song.uri);
|
400 |
data.addarg("Metadata", metadata);
|
403 |
data.addarg("Metadata", metadata);
|
401 |
}
|
404 |
}
|
402 |
return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
405 |
return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
|
... |
|
... |
412 |
// <Metadata></Metadata>
|
415 |
// <Metadata></Metadata>
|
413 |
// </Entry>
|
416 |
// </Entry>
|
414 |
// </TrackList>
|
417 |
// </TrackList>
|
415 |
//
|
418 |
//
|
416 |
// Any ids not in the playlist are ignored.
|
419 |
// Any ids not in the playlist are ignored.
|
417 |
int OHPlaylist::readlist(const SoapArgs& sc, SoapData& data)
|
420 |
int OHPlaylist::readList(const SoapArgs& sc, SoapData& data)
|
418 |
{
|
421 |
{
|
419 |
LOGDEB("OHPlaylist::readlist" << endl);
|
422 |
LOGDEB("OHPlaylist::readList" << endl);
|
420 |
string sids;
|
423 |
string sids;
|
421 |
bool ok = sc.getString("IdList", &sids);
|
424 |
bool ok = sc.getString("IdList", &sids);
|
422 |
vector<string> ids;
|
425 |
vector<string> ids;
|
423 |
string out("<TrackList>");
|
426 |
string out("<TrackList>");
|
424 |
if (ok) {
|
427 |
if (ok) {
|
425 |
stringToTokens(sids, ids);
|
428 |
stringToTokens(sids, ids);
|
426 |
for (vector<string>::iterator it = ids.begin(); it != ids.end(); it++) {
|
429 |
for (auto& sid : ids) {
|
427 |
int id = atoi(it->c_str());
|
430 |
int id = atoi(sid.c_str());
|
428 |
UpSong song;
|
431 |
UpSong song;
|
429 |
if (!m_dev->m_mpdcli->statSong(song, id, true))
|
432 |
if (!m_dev->m_mpdcli->statSong(song, id, true))
|
430 |
continue;
|
433 |
continue;
|
431 |
unordered_map<int, string>::iterator mit = m_metacache.find(id);
|
434 |
auto mit = m_metacache.find(id);
|
432 |
string metadata;
|
435 |
string metadata;
|
433 |
if (mit != m_metacache.end()) {
|
436 |
if (mit != m_metacache.end()) {
|
434 |
metadata = xmlquote(mit->second);
|
437 |
metadata = SoapArgs::xmlQuote(mit->second);
|
435 |
} else {
|
438 |
} else {
|
436 |
metadata = xmlquote(didlmake(song));
|
439 |
metadata = SoapArgs::xmlQuote(didlmake(song));
|
437 |
}
|
440 |
}
|
438 |
out += "<Entry><Id>";
|
441 |
out += "<Entry><Id>";
|
439 |
out += it->c_str();
|
442 |
out += sid.c_str();
|
440 |
out += "</Id><Uri>";
|
443 |
out += "</Id><Uri>";
|
441 |
out += song.uri;
|
444 |
out += song.uri;
|
442 |
out += "</Uri><Metadata>";
|
445 |
out += "</Uri><Metadata>";
|
443 |
out += metadata;
|
446 |
out += metadata;
|
444 |
out += "</Metadata></Entry>";
|
447 |
out += "</Metadata></Entry>";
|
|
... |
|
... |
516 |
|
519 |
|
517 |
// Check if id array changed since last call (which returned a gen token)
|
520 |
// Check if id array changed since last call (which returned a gen token)
|
518 |
int OHPlaylist::idArrayChanged(const SoapArgs& sc, SoapData& data)
|
521 |
int OHPlaylist::idArrayChanged(const SoapArgs& sc, SoapData& data)
|
519 |
{
|
522 |
{
|
520 |
LOGDEB("OHPlaylist::idArrayChanged" << endl);
|
523 |
LOGDEB("OHPlaylist::idArrayChanged" << endl);
|
521 |
bool ok = false;
|
524 |
int token;
|
522 |
|
525 |
bool ok = sc.getInt("Token", &token);
|
523 |
data.addarg("Token", "0");
|
|
|
524 |
// Bool indicating if array changed
|
526 |
// Bool indicating if array changed
|
525 |
data.addarg("Value", "0");
|
527 |
data.addarg("Value", "0");
|
526 |
|
528 |
|
527 |
return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
529 |
return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
528 |
}
|
530 |
}
|