|
a/src/ohreceiver.cxx |
|
b/src/ohreceiver.cxx |
|
... |
|
... |
42 |
static const string sTpProduct("urn:av-openhome-org:service:Receiver:1");
|
42 |
static const string sTpProduct("urn:av-openhome-org:service:Receiver:1");
|
43 |
static const string sIdProduct("urn:av-openhome-org:serviceId:Receiver");
|
43 |
static const string sIdProduct("urn:av-openhome-org:serviceId:Receiver");
|
44 |
|
44 |
|
45 |
OHReceiver::OHReceiver(UpMpd *dev, const OHReceiverParams& parms)
|
45 |
OHReceiver::OHReceiver(UpMpd *dev, const OHReceiverParams& parms)
|
46 |
: UpnpService(sTpProduct, sIdProduct, dev), m_dev(dev),
|
46 |
: UpnpService(sTpProduct, sIdProduct, dev), m_dev(dev),
|
47 |
m_pl(parms.pl), m_pr(parms.pr), m_httpport(parms.httpport),
|
47 |
m_httpport(parms.httpport), m_pm(parms.pm)
|
48 |
m_pm(parms.pm)
|
|
|
49 |
{
|
48 |
{
|
50 |
dev->addActionMapping(this, "Play",
|
49 |
dev->addActionMapping(this, "Play",
|
51 |
bind(&OHReceiver::play, this, _1, _2));
|
50 |
bind(&OHReceiver::play, this, _1, _2));
|
52 |
dev->addActionMapping(this, "Stop",
|
51 |
dev->addActionMapping(this, "Stop",
|
53 |
bind(&OHReceiver::stop, this, _1, _2));
|
52 |
bind(&OHReceiver::stop, this, _1, _2));
|
|
... |
|
... |
133 |
{
|
132 |
{
|
134 |
if (ok && m_dev)
|
133 |
if (ok && m_dev)
|
135 |
m_dev->loopWakeup();
|
134 |
m_dev->loopWakeup();
|
136 |
}
|
135 |
}
|
137 |
|
136 |
|
138 |
int OHReceiver::play(const SoapIncoming& sc, SoapOutgoing& data)
|
137 |
bool OHReceiver::iPlay()
|
139 |
{
|
138 |
{
|
140 |
LOGDEB("OHReceiver::play" << endl);
|
|
|
141 |
bool ok = false;
|
139 |
bool ok = false;
|
142 |
|
140 |
|
143 |
if (!m_pl) {
|
141 |
if (!m_dev->m_ohpl) {
|
144 |
LOGERR("OHReceiver::play: no playlist service" << endl);
|
142 |
LOGERR("OHReceiver::play: no playlist service" << endl);
|
145 |
return UPNP_E_INTERNAL_ERROR;
|
143 |
return false;
|
146 |
}
|
144 |
}
|
147 |
if (m_uri.empty()) {
|
145 |
if (m_uri.empty()) {
|
148 |
LOGERR("OHReceiver::play: no uri" << endl);
|
146 |
LOGERR("OHReceiver::play: no uri" << endl);
|
149 |
return UPNP_E_INTERNAL_ERROR;
|
147 |
return false;
|
150 |
}
|
148 |
}
|
151 |
if (m_metadata.empty()) {
|
149 |
if (m_metadata.empty()) {
|
152 |
LOGERR("OHReceiver::play: no metadata" << endl);
|
150 |
LOGERR("OHReceiver::play: no metadata" << endl);
|
153 |
return UPNP_E_INTERNAL_ERROR;
|
151 |
return false;
|
154 |
}
|
152 |
}
|
155 |
|
153 |
|
156 |
m_dev->m_mpdcli->stop();
|
154 |
m_dev->m_mpdcli->stop();
|
157 |
|
155 |
|
158 |
int id = -1;
|
156 |
int id = -1;
|
|
... |
|
... |
190 |
// Wait for sc2mpd to signal ready, then play.
|
188 |
// Wait for sc2mpd to signal ready, then play.
|
191 |
// sc2mpd writes a single line to stdout "CONNECTED" when
|
189 |
// sc2mpd writes a single line to stdout "CONNECTED" when
|
192 |
// it gets there, which should be more or less instantaneous
|
190 |
// it gets there, which should be more or less instantaneous
|
193 |
int timeo = 15;
|
191 |
int timeo = 15;
|
194 |
if (m_cmd->getline(line, timeo) < 0) {
|
192 |
if (m_cmd->getline(line, timeo) < 0) {
|
195 |
LOGERR("OHReceiver: mpd mode: sc2mpd still not ready to play after " << timeo << " seconds\n");
|
193 |
LOGERR("OHReceiver: mpd mode: sc2mpd still not ready to play after "
|
|
|
194 |
<< timeo << " seconds\n");
|
196 |
goto out;
|
195 |
goto out;
|
197 |
}
|
196 |
}
|
198 |
LOGDEB("OHReceiver: sc2mpd sent: " << line);
|
197 |
LOGDEB("OHReceiver: sc2mpd sent: " << line);
|
199 |
// And insert the appropriate uri in the mpd playlist
|
198 |
// And insert the appropriate uri in the mpd playlist
|
200 |
if (!m_pl->urlMap(urlmap)) {
|
199 |
if (!m_dev->m_ohpl->urlMap(urlmap)) {
|
201 |
LOGERR("OHReceiver::play: urlMap() failed" <<endl);
|
200 |
LOGERR("OHReceiver::play: urlMap() failed" <<endl);
|
202 |
goto out;
|
201 |
goto out;
|
203 |
}
|
202 |
}
|
204 |
for (auto it = urlmap.begin(); it != urlmap.end(); it++) {
|
203 |
for (auto it = urlmap.begin(); it != urlmap.end(); it++) {
|
205 |
if (it->second == m_httpuri) {
|
204 |
if (it->second == m_httpuri) {
|
206 |
id = it->first;
|
205 |
id = it->first;
|
207 |
}
|
206 |
}
|
208 |
}
|
207 |
}
|
209 |
if (id == -1) {
|
208 |
if (id == -1) {
|
210 |
ok = m_pl->insertUri(0, m_httpuri, SoapHelp::xmlUnquote(m_metadata),
|
209 |
ok = m_dev->m_ohpl->insertUri(0, m_httpuri,
|
211 |
&id);
|
210 |
SoapHelp::xmlUnquote(m_metadata),&id);
|
212 |
if (!ok) {
|
211 |
if (!ok) {
|
213 |
LOGERR("OHReceiver::play: insertUri() failed\n");
|
212 |
LOGERR("OHReceiver::play: insertUri() failed\n");
|
214 |
goto out;
|
213 |
goto out;
|
215 |
}
|
214 |
}
|
216 |
}
|
215 |
}
|
|
... |
|
... |
225 |
out:
|
224 |
out:
|
226 |
if (!ok) {
|
225 |
if (!ok) {
|
227 |
iStop();
|
226 |
iStop();
|
228 |
}
|
227 |
}
|
229 |
maybeWakeUp(ok);
|
228 |
maybeWakeUp(ok);
|
|
|
229 |
return ok;
|
|
|
230 |
}
|
|
|
231 |
|
|
|
232 |
int OHReceiver::play(const SoapIncoming& sc, SoapOutgoing& data)
|
|
|
233 |
{
|
230 |
LOGDEB("OHReceiver::play: returning\n");
|
234 |
LOGDEB("OHReceiver::play" << endl);
|
|
|
235 |
bool ok = iPlay();
|
|
|
236 |
if (ok && m_dev->m_ohpr)
|
|
|
237 |
m_dev->m_ohpr->iSetSourceIndexByName("Receiver");
|
231 |
return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
238 |
return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
232 |
}
|
239 |
}
|
233 |
|
240 |
|
234 |
bool OHReceiver::iStop()
|
241 |
bool OHReceiver::iStop()
|
235 |
{
|
242 |
{
|
|
... |
|
... |
240 |
}
|
247 |
}
|
241 |
m_dev->m_mpdcli->stop();
|
248 |
m_dev->m_mpdcli->stop();
|
242 |
|
249 |
|
243 |
unordered_map<int, string> urlmap;
|
250 |
unordered_map<int, string> urlmap;
|
244 |
// Remove our bogus URi from the playlist
|
251 |
// Remove our bogus URi from the playlist
|
245 |
if (!m_pl->urlMap(urlmap)) {
|
252 |
if (!m_dev->m_ohpl->urlMap(urlmap)) {
|
246 |
LOGERR("OHReceiver::stop: urlMap() failed" <<endl);
|
253 |
LOGERR("OHReceiver::stop: urlMap() failed" <<endl);
|
247 |
return false;
|
|
|
248 |
}
|
254 |
}
|
249 |
for (auto it = urlmap.begin(); it != urlmap.end(); it++) {
|
255 |
for (auto it = urlmap.begin(); it != urlmap.end(); it++) {
|
250 |
if (it->second == m_httpuri) {
|
256 |
if (it->second == m_httpuri) {
|
251 |
m_dev->m_mpdcli->deleteId(it->first);
|
257 |
m_dev->m_mpdcli->deleteId(it->first);
|
252 |
}
|
258 |
}
|
|
... |
|
... |
255 |
// index (it does call stop when it deconnects).
|
261 |
// index (it does call stop when it deconnects).
|
256 |
// I guess that there is no reason to reset the source, and
|
262 |
// I guess that there is no reason to reset the source, and
|
257 |
// another CP could just set it to what it wants, but Bubble at
|
263 |
// another CP could just set it to what it wants, but Bubble at
|
258 |
// least won't do a thing with the renderer as long as the source
|
264 |
// least won't do a thing with the renderer as long as the source
|
259 |
// is set to receiver.
|
265 |
// is set to receiver.
|
260 |
if (m_pr)
|
266 |
if (m_dev->m_ohpr)
|
261 |
m_pr->iSetSourceIndex(0);
|
267 |
m_dev->m_ohpr->iSetSourceIndexByName("Playlist");
|
262 |
|
268 |
|
|
|
269 |
maybeWakeUp(true);
|
263 |
return true;
|
270 |
return true;
|
264 |
}
|
271 |
}
|
265 |
|
272 |
|
266 |
int OHReceiver::stop(const SoapIncoming& sc, SoapOutgoing& data)
|
273 |
int OHReceiver::stop(const SoapIncoming& sc, SoapOutgoing& data)
|
267 |
{
|
274 |
{
|
268 |
LOGDEB("OHReceiver::stop" << endl);
|
275 |
LOGDEB("OHReceiver::stop" << endl);
|
269 |
bool ok = iStop();
|
|
|
270 |
maybeWakeUp(ok);
|
|
|
271 |
return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
276 |
return iStop() ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
272 |
}
|
277 |
}
|
273 |
|
278 |
|
274 |
int OHReceiver::setSender(const SoapIncoming& sc, SoapOutgoing& data)
|
279 |
bool OHReceiver::iSetSender(const string& uri, const string& metadata)
|
275 |
{
|
280 |
{
|
276 |
LOGDEB("OHReceiver::setSender" << endl);
|
|
|
277 |
string uri, metadata;
|
|
|
278 |
bool ok = sc.get("Uri", &uri) && sc.get("Metadata", &metadata);
|
|
|
279 |
|
|
|
280 |
// Only do something if data changes, and then first stop any
|
281 |
// Only do something if data changes, and then first stop any
|
281 |
// current playing. We probably should not receive this if we're
|
282 |
// current playing. We probably should not receive this if we're
|
282 |
// not in the stopped state, but just in case...
|
283 |
// not in the stopped state, but just in case...
|
283 |
if (ok && (m_uri.compare(uri) || m_metadata.compare(metadata))) {
|
284 |
if (m_uri.compare(uri) || m_metadata.compare(metadata)) {
|
284 |
if (m_cmd)
|
285 |
if (m_cmd)
|
285 |
iStop();
|
286 |
iStop();
|
286 |
m_uri = uri;
|
287 |
m_uri = uri;
|
287 |
m_metadata = metadata;
|
288 |
m_metadata = metadata;
|
288 |
LOGDEB("OHReceiver::setSender: uri [" << m_uri << "] meta [" <<
|
289 |
LOGDEB("OHReceiver::setSender: uri [" << m_uri << "] meta [" <<
|
289 |
m_metadata << "]" << endl);
|
290 |
m_metadata << "]" << endl);
|
|
|
291 |
}
|
|
|
292 |
return true;
|
|
|
293 |
}
|
|
|
294 |
|
|
|
295 |
int OHReceiver::setSender(const SoapIncoming& sc, SoapOutgoing& data)
|
|
|
296 |
{
|
|
|
297 |
LOGDEB("OHReceiver::setSender" << endl);
|
|
|
298 |
string uri, metadata;
|
|
|
299 |
bool ok = sc.get("Uri", &uri) && sc.get("Metadata", &metadata);
|
|
|
300 |
if (ok) {
|
|
|
301 |
ok = iSetSender(uri, metadata);
|
290 |
}
|
302 |
}
|
291 |
|
303 |
|
292 |
maybeWakeUp(ok);
|
304 |
maybeWakeUp(ok);
|
293 |
return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
305 |
return ok ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
294 |
}
|
306 |
}
|