|
a/upmpd/upmpd.cxx |
|
b/upmpd/upmpd.cxx |
|
... |
|
... |
118 |
|
118 |
|
119 |
static const string serviceIdRender("urn:upnp-org:serviceId:RenderingControl");
|
119 |
static const string serviceIdRender("urn:upnp-org:serviceId:RenderingControl");
|
120 |
static const string serviceIdTransport("urn:upnp-org:serviceId:AVTransport");
|
120 |
static const string serviceIdTransport("urn:upnp-org:serviceId:AVTransport");
|
121 |
static const string serviceIdCM("urn:upnp-org:serviceId:ConnectionManager");
|
121 |
static const string serviceIdCM("urn:upnp-org:serviceId:ConnectionManager");
|
122 |
|
122 |
|
|
|
123 |
// Note: if we ever need this to work without cxx11, there is this:
|
|
|
124 |
// http://www.tutok.sk/fastgl/callback.html
|
123 |
UpMpd::UpMpd(const string& deviceid,
|
125 |
UpMpd::UpMpd(const string& deviceid,
|
124 |
const unordered_map<string, string>& xmlfiles,
|
126 |
const unordered_map<string, string>& xmlfiles,
|
125 |
MPDCli *mpdcli, Options opts)
|
127 |
MPDCli *mpdcli, Options opts)
|
126 |
: UpnpDevice(deviceid, xmlfiles), m_mpdcli(mpdcli), m_desiredvolume(-1),
|
128 |
: UpnpDevice(deviceid, xmlfiles), m_mpdcli(mpdcli), m_desiredvolume(-1),
|
127 |
m_options(opts)
|
129 |
m_options(opts)
|
128 |
{
|
130 |
{
|
129 |
addServiceType(serviceIdRender,
|
131 |
addServiceType(serviceIdRender,
|
130 |
"urn:schemas-upnp-org:service:RenderingControl:1");
|
132 |
"urn:schemas-upnp-org:service:RenderingControl:1");
|
131 |
{ auto bound = bind(&UpMpd::setMute, this, _1, _2);
|
133 |
addActionMapping("SetMute", bind(&UpMpd::setMute, this, _1, _2));
|
132 |
addActionMapping("SetMute", bound);
|
134 |
addActionMapping("GetMute", bind(&UpMpd::getMute, this, _1, _2));
|
133 |
}
|
135 |
addActionMapping("SetVolume", bind(&UpMpd::setVolume, this, _1, _2, false));
|
134 |
{ auto bound = bind(&UpMpd::getMute, this, _1, _2);
|
136 |
addActionMapping("GetVolume", bind(&UpMpd::getVolume, this, _1, _2, false));
|
135 |
addActionMapping("GetMute", bound);
|
137 |
addActionMapping("ListPresets", bind(&UpMpd::listPresets, this, _1, _2));
|
136 |
}
|
138 |
addActionMapping("SelectPreset", bind(&UpMpd::selectPreset, this, _1, _2));
|
137 |
{ auto bound = bind(&UpMpd::setVolume, this, _1, _2, false);
|
139 |
#if 0
|
138 |
addActionMapping("SetVolume", bound);
|
|
|
139 |
}
|
|
|
140 |
// { auto bound = bind(&UpMpd::setVolume, this, _1, _2, true);
|
|
|
141 |
// addActionMapping("SetVolumeDB", bound);
|
|
|
142 |
// }
|
|
|
143 |
{ auto bound = bind(&UpMpd::getVolume, this, _1, _2, false);
|
|
|
144 |
addActionMapping("GetVolume", bound);
|
|
|
145 |
}
|
|
|
146 |
// { auto bound = bind(&UpMpd::getVolume, this, _1, _2, true);
|
|
|
147 |
// addActionMapping("GetVolumeDB", bound);
|
140 |
addActionMapping("GetVolumeDB",
|
148 |
// }
|
141 |
bind(&UpMpd::getVolume, this, _1, _2, true));
|
149 |
{ auto bound = bind(&UpMpd::listPresets, this, _1, _2);
|
142 |
addActionMapping("SetVolumeDB",
|
150 |
addActionMapping("ListPresets", bound);
|
143 |
bind(&UpMpd::setVolume, this, _1, _2, true));
|
151 |
}
|
|
|
152 |
{ auto bound = bind(&UpMpd::selectPreset, this, _1, _2);
|
|
|
153 |
addActionMapping("SelectPreset", bound);
|
|
|
154 |
}
|
|
|
155 |
// { auto bound = bind(&UpMpd::getVolumeDBRange, this, _1, _2);
|
|
|
156 |
// addActionMapping("GetVolumeDBRange", bound);
|
144 |
addActionMapping("GetVolumeDBRange",
|
157 |
// }
|
145 |
bind(&UpMpd::getVolumeDBRange, this, _1, _2));
|
|
|
146 |
#endif
|
158 |
|
147 |
|
159 |
addServiceType(serviceIdTransport,
|
148 |
addServiceType(serviceIdTransport,
|
160 |
"urn:schemas-upnp-org:service:AVTransport:1");
|
149 |
"urn:schemas-upnp-org:service:AVTransport:1");
|
161 |
|
|
|
162 |
{ auto bound = bind(&UpMpd::setAVTransportURI, this, _1, _2, false);
|
|
|
163 |
addActionMapping("SetAVTransportURI", bound);
|
150 |
addActionMapping("SetAVTransportURI",
|
164 |
}
|
|
|
165 |
{ auto bound = bind(&UpMpd::setAVTransportURI, this, _1, _2, true);
|
151 |
bind(&UpMpd::setAVTransportURI, this, _1, _2, false));
|
166 |
addActionMapping("SetNextAVTransportURI", bound);
|
152 |
addActionMapping("SetNextAVTransportURI",
|
167 |
}
|
153 |
bind(&UpMpd::setAVTransportURI, this, _1, _2, true));
|
168 |
{ auto bound = bind(&UpMpd::getPositionInfo, this, _1, _2);
|
|
|
169 |
addActionMapping("GetPositionInfo", bound);
|
154 |
addActionMapping("GetPositionInfo",
|
170 |
}
|
155 |
bind(&UpMpd::getPositionInfo, this, _1, _2));
|
171 |
{ auto bound = bind(&UpMpd::getTransportInfo, this, _1, _2);
|
|
|
172 |
addActionMapping("GetTransportInfo", bound);
|
156 |
addActionMapping("GetTransportInfo",
|
173 |
}
|
157 |
bind(&UpMpd::getTransportInfo, this, _1, _2));
|
174 |
{ auto bound = bind(&UpMpd::getMediaInfo, this, _1, _2);
|
|
|
175 |
addActionMapping("GetMediaInfo", bound);
|
158 |
addActionMapping("GetMediaInfo",
|
176 |
}
|
159 |
bind(&UpMpd::getMediaInfo, this, _1, _2));
|
177 |
{ auto bound = bind(&UpMpd::getDeviceCapabilities, this, _1, _2);
|
|
|
178 |
addActionMapping("GetDeviceCapabilities", bound);
|
160 |
addActionMapping("GetDeviceCapabilities",
|
179 |
}
|
161 |
bind(&UpMpd::getDeviceCapabilities, this, _1, _2));
|
180 |
{ auto bound = bind(&UpMpd::setPlayMode, this, _1, _2);
|
162 |
addActionMapping("SetPlayMode", bind(&UpMpd::setPlayMode, this, _1, _2));
|
181 |
addActionMapping("SetPlayMode", bound);
|
|
|
182 |
}
|
|
|
183 |
{ auto bound = bind(&UpMpd::getTransportSettings, this, _1, _2);
|
|
|
184 |
addActionMapping("GetTransportSettings", bound);
|
163 |
addActionMapping("GetTransportSettings",
|
185 |
}
|
164 |
bind(&UpMpd::getTransportSettings, this, _1, _2));
|
186 |
{ auto bound = bind(&UpMpd::getCurrentTransportActions, this, _1, _2);
|
|
|
187 |
addActionMapping("GetCurrentTransportActions", bound);
|
165 |
addActionMapping("GetCurrentTransportActions",
|
188 |
}
|
166 |
bind(&UpMpd::getCurrentTransportActions, this, _1, _2));
|
189 |
{ auto bound = bind(&UpMpd::playcontrol, this, _1, _2, 0);
|
167 |
addActionMapping("Stop", bind(&UpMpd::playcontrol, this, _1, _2, 0));
|
190 |
addActionMapping("Stop", bound);
|
|
|
191 |
}
|
|
|
192 |
{ auto bound = bind(&UpMpd::playcontrol, this, _1, _2, 1);
|
168 |
addActionMapping("Play", bind(&UpMpd::playcontrol, this, _1, _2, 1));
|
193 |
addActionMapping("Play", bound);
|
169 |
addActionMapping("Pause", bind(&UpMpd::playcontrol, this, _1, _2, 2));
|
194 |
}
|
170 |
addActionMapping("Seek", bind(&UpMpd::seek, this, _1, _2));
|
195 |
{ auto bound = bind(&UpMpd::playcontrol, this, _1, _2, 2);
|
|
|
196 |
addActionMapping("Pause", bound);
|
|
|
197 |
}
|
|
|
198 |
{ auto bound = bind(&UpMpd::seek, this, _1, _2);
|
|
|
199 |
addActionMapping("Seek", bound);
|
|
|
200 |
}
|
|
|
201 |
{ auto bound = bind(&UpMpd::seqcontrol, this, _1, _2, 0);
|
171 |
addActionMapping("Next", bind(&UpMpd::seqcontrol, this, _1, _2, 0));
|
202 |
addActionMapping("Next", bound);
|
|
|
203 |
}
|
|
|
204 |
{ auto bound = bind(&UpMpd::seqcontrol, this, _1, _2, 1);
|
172 |
addActionMapping("Previous", bind(&UpMpd::seqcontrol, this, _1, _2, 1));
|
205 |
addActionMapping("Previous", bound);
|
|
|
206 |
}
|
|
|
207 |
|
173 |
|
208 |
addServiceType(serviceIdCM,
|
174 |
addServiceType(serviceIdCM,
|
209 |
"urn:schemas-upnp-org:service:ConnectionManager:1");
|
175 |
"urn:schemas-upnp-org:service:ConnectionManager:1");
|
210 |
{ auto bound = bind(&UpMpd::getCurrentConnectionIDs, this, _1, _2);
|
|
|
211 |
addActionMapping("GetCurrentConnectionIDs", bound);
|
176 |
addActionMapping("GetCurrentConnectionIDs",
|
212 |
}
|
|
|
213 |
{ auto bound = bind(&UpMpd::getCurrentConnectionInfo, this, _1, _2);
|
177 |
bind(&UpMpd::getCurrentConnectionIDs, this, _1, _2));
|
214 |
addActionMapping("GetCurrentConnectionInfo", bound);
|
178 |
addActionMapping("GetCurrentConnectionInfo",
|
215 |
}
|
179 |
bind(&UpMpd::getCurrentConnectionInfo, this, _1, _2));
|
216 |
{ auto bound = bind(&UpMpd::getProtocolInfo, this, _1, _2);
|
|
|
217 |
addActionMapping("GetProtocolInfo", bound);
|
180 |
addActionMapping("GetProtocolInfo",
|
218 |
}
|
181 |
bind(&UpMpd::getProtocolInfo, this, _1, _2));
|
219 |
}
|
182 |
}
|
220 |
|
183 |
|
221 |
// This is called by the polling loop at regular intervals, or when
|
184 |
// This is called by the polling loop at regular intervals, or when
|
222 |
// triggered, to retrieve changed state variables for each of the
|
185 |
// triggered, to retrieve changed state variables for each of the
|
223 |
// services (the list of services was defined in the base class by the
|
186 |
// services (the list of services was defined in the base class by the
|
|
... |
|
... |
1027 |
if (it == sc.args.end() || it->second.empty()) {
|
990 |
if (it == sc.args.end() || it->second.empty()) {
|
1028 |
return UPNP_E_INVALID_PARAM;
|
991 |
return UPNP_E_INVALID_PARAM;
|
1029 |
}
|
992 |
}
|
1030 |
string target(it->second);
|
993 |
string target(it->second);
|
1031 |
|
994 |
|
1032 |
// LOGDEB("UpMpd::seek: unit " << unit << " target " << target);
|
|
|
1033 |
|
|
|
1034 |
const MpdStatus &mpds = m_mpdcli->getStatus();
|
995 |
const MpdStatus &mpds = m_mpdcli->getStatus();
|
|
|
996 |
|
|
|
997 |
//LOGDEB("UpMpd::seek: unit " << unit << " target " << target <<
|
|
|
998 |
// " current posisition " << mpds.songelapsedms / 1000 <<
|
|
|
999 |
// " seconds" << endl);
|
|
|
1000 |
|
1035 |
int abs_seconds;
|
1001 |
int abs_seconds;
|
|
|
1002 |
// Note that ABS_TIME and REL_TIME don't mean what you'd think
|
|
|
1003 |
// they mean. REL_TIME means relative to the current track,
|
|
|
1004 |
// ABS_TIME to the whole media (ie for a multitrack tape). So
|
|
|
1005 |
// we only support REL_TIME, as absolute position in the current song
|
1036 |
if (!unit.compare("ABS_TIME")) {
|
1006 |
if (!unit.compare("REL_TIME")) {
|
1037 |
abs_seconds = upnpdurationtos(target);
|
1007 |
abs_seconds = upnpdurationtos(target);
|
1038 |
} else if (!unit.compare("REL_TIME")) {
|
|
|
1039 |
abs_seconds = mpds.songelapsedms / 1000;
|
|
|
1040 |
abs_seconds += upnpdurationtos(target);
|
|
|
1041 |
// } else if (!unit.compare("TRACK_NR")) {
|
|
|
1042 |
} else {
|
1008 |
} else {
|
1043 |
return UPNP_E_INVALID_PARAM;
|
1009 |
return UPNP_E_INVALID_PARAM;
|
1044 |
}
|
1010 |
}
|
|
|
1011 |
LOGDEB("UpMpd::seek: seeking to " << abs_seconds << " seconds (" <<
|
|
|
1012 |
upnpduration(abs_seconds * 1000) << ")" << endl);
|
1045 |
|
1013 |
|
1046 |
loopWakeup();
|
1014 |
loopWakeup();
|
1047 |
return m_mpdcli->seek(abs_seconds) ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
1015 |
return m_mpdcli->seek(abs_seconds) ? UPNP_E_SUCCESS : UPNP_E_INTERNAL_ERROR;
|
1048 |
}
|
1016 |
}
|
1049 |
|
1017 |
|