Switch to unified view

a/src/upmpdutils.cxx b/src/upmpdutils.cxx
...
...
132
        ss << "<" #TAG ">" << SoapHelp::xmlQuote(FLD) << "</" #TAG ">"; \
132
        ss << "<" #TAG ">" << SoapHelp::xmlQuote(FLD) << "</" #TAG ">"; \
133
    } else {                                                            \
133
    } else {                                                            \
134
        ss << "<" #TAG ">" << SoapHelp::xmlQuote(DEF) << "</" #TAG ">"; \
134
        ss << "<" #TAG ">" << SoapHelp::xmlQuote(DEF) << "</" #TAG ">"; \
135
    }
135
    }
136
136
137
string UpSong::didl()
137
string UpSong::didl() const
138
{
138
{
139
    ostringstream ss;
139
    ostringstream ss;
140
    string typetag;
140
    string typetag;
141
    if (iscontainer) {
141
    if (iscontainer) {
142
    typetag = "container";
142
    typetag = "container";
143
    } else {
143
    } else {
144
    typetag = "item";
144
    typetag = "item";
145
    }
145
    }
146
    ss << "<" << typetag << " id=\"" << id << "\" parentID=\"" <<
146
    ss << "<" << typetag;
147
    if (!id.empty()) {
148
        ss << " id=\"" << id;
149
    }
150
    if (!parentid.empty()) {
151
        ss << "\" parentID=\"" << parentid;
152
    }
147
  parentid << "\" restricted=\"1\" searchable=\"" <<
153
    ss << "\" restricted=\"1\" searchable=\"" <<
148
    (searchable ? string("1") : string("0")) << "\">" <<
154
    (searchable ? string("1") : string("0")) << "\">" <<
149
    "<dc:title>" << SoapHelp::xmlQuote(title) << "</dc:title>";
155
    "<dc:title>" << SoapHelp::xmlQuote(title) << "</dc:title>";
156
157
    if (id.empty()) {
158
        ss << "<orig>mpd</orig>";
159
    }
150
160
151
    if (iscontainer) {
161
    if (iscontainer) {
152
        UPNPXMLD(upnpClass, upnp:class, "object.container");
162
        UPNPXMLD(upnpClass, upnp:class, "object.container");
153
        // tracknum is reused for annotations for containers
163
        // tracknum is reused for annotations for containers
154
        ss << (tracknum.empty() ? string() :
164
        ss << (tracknum.empty() ? string() :
...
...
159
        UPNPXMLD(upnpClass, upnp:class, "object.item.audioItem.musicTrack");
169
        UPNPXMLD(upnpClass, upnp:class, "object.item.audioItem.musicTrack");
160
    UPNPXML(genre, upnp:genre);
170
    UPNPXML(genre, upnp:genre);
161
    UPNPXML(album, upnp:album);
171
    UPNPXML(album, upnp:album);
162
    UPNPXML(tracknum, upnp:originalTrackNumber);
172
    UPNPXML(tracknum, upnp:originalTrackNumber);
163
173
164
    ss << "<res " <<
174
    ss << "<res";
175
        if (duration_secs) {
165
            "duration=\"" << upnpduration(duration_secs * 1000)  << "\" " <<
176
            ss << " duration=\"" << upnpduration(duration_secs * 1000)  << "\"";
177
        }
178
        if (size) {
166
            "size=\"" << lltodecstr(size)                        << "\" " <<
179
            ss << " size=\"" << lltodecstr(size)                        << "\"";
180
        }
181
        if (bitrate) {
167
            "bitrate=\"" << SoapHelp::i2s(bitrate)               << "\" " <<
182
            ss << " bitrate=\"" << SoapHelp::i2s(bitrate)               << "\"";
183
        }
184
        if (samplefreq) {
168
        "sampleFrequency=\"" << SoapHelp::i2s(samplefreq)    << "\" " <<
185
        ss << " sampleFrequency=\"" << SoapHelp::i2s(samplefreq)    << "\"";
186
        }
187
        if (channels) {
169
            "nrAudioChannels=\"" << SoapHelp::i2s(channels)      << "\" " <<
188
            ss << " nrAudioChannels=\"" << SoapHelp::i2s(channels)      << "\"";
189
        }
190
        if (!mime.empty()) {
170
        "protocolInfo=\"http-get:*:" << mime << ":* "        << "\" >"<<
191
        ss << " protocolInfo=\"http-get:*:" << mime << ":* "        << "\"";
171
            SoapHelp::xmlQuote(uri) <<
192
        }
172
            "</res>";
193
        ss << ">" << SoapHelp::xmlQuote(uri) << "</res>";
173
    }
194
    }
174
    UPNPXML(artist, dc:creator);
195
    UPNPXML(artist, dc:creator);
175
    UPNPXML(artist, upnp:artist);
196
    UPNPXML(artist, upnp:artist);
176
    UPNPXML(date, dc:date);
197
    UPNPXML(date, dc:date);
177
    UPNPXML(artUri, upnp:albumArtURI);
198
    UPNPXML(artUri, upnp:albumArtURI);
...
...
204
225
205
// Bogus didl fragment maker. We probably don't need a full-blown XML
226
// Bogus didl fragment maker. We probably don't need a full-blown XML
206
// helper here
227
// helper here
207
string didlmake(const UpSong& song)
228
string didlmake(const UpSong& song)
208
{
229
{
209
    ostringstream ss;
230
    return wrapDIDL(song.didl());
210
    ss << "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
211
       "<DIDL-Lite xmlns:dc=\"http://purl.org/dc/elements/1.1/\" "
212
       "xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\" "
213
       "xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\" "
214
       "xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\">"
215
       << "<item restricted=\"1\">";
216
    ss << "<orig>mpd</orig>";
217
    {
218
        const string& val = song.title;
219
        ss << "<dc:title>" << SoapHelp::xmlQuote(val) << "</dc:title>";
220
    }
221
222
    // TBD Playlists etc?
223
    ss << "<upnp:class>object.item.audioItem.musicTrack</upnp:class>";
224
225
    {
226
        const string& val = song.artist;
227
        if (!val.empty()) {
228
            string a = SoapHelp::xmlQuote(val);
229
            ss << "<dc:creator>" << a << "</dc:creator>" <<
230
               "<upnp:artist>" << a << "</upnp:artist>";
231
        }
232
    }
233
234
    {
235
        const string& val = song.album;
236
        if (!val.empty()) {
237
            ss << "<upnp:album>" << SoapHelp::xmlQuote(val) << "</upnp:album>";
238
        }
239
    }
240
241
    {
242
        const string& val = song.genre;
243
        if (!val.empty()) {
244
            ss << "<upnp:genre>" << SoapHelp::xmlQuote(val) << "</upnp:genre>";
245
        }
246
    }
247
248
    {
249
        string val = song.tracknum;
250
        // MPD may return something like xx/yy
251
        string::size_type spos = val.find("/");
252
        if (spos != string::npos) {
253
            val = val.substr(0, spos);
254
        }
255
        if (!val.empty()) {
256
            ss << "<upnp:originalTrackNumber>" << val <<
257
               "</upnp:originalTrackNumber>";
258
        }
259
    }
260
261
    {
262
        const string& val = song.artUri;
263
        if (!val.empty()) {
264
            ss << "<upnp:albumArtURI>" << SoapHelp::xmlQuote(val) <<
265
               "</upnp:albumArtURI>";
266
        }
267
    }
268
269
    // TBD: the res element normally has size, sampleFrequency,
270
    // nrAudioChannels and protocolInfo attributes, which are bogus
271
    // for the moment. partly because MPD does not supply them.  And
272
    // mostly everything is bogus if next is set...
273
274
    ss << "<res " << "duration=\"" << upnpduration(song.duration_secs * 1000)
275
       << "\" "
276
       // Bitrate keeps changing for VBRs and forces events. Keeping
277
       // it out for now.
278
       //       << "bitrate=\"" << mpds.kbrate << "\" "
279
       << "sampleFrequency=\"44100\" nrAudioChannels=\"2\" "
280
       << "protocolInfo=\"http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000\""
281
       << ">"
282
       << SoapHelp::xmlQuote(song.uri)
283
       << "</res>"
284
       << "</item></DIDL-Lite>";
285
    return ss.str();
286
}
231
}
287
232
288
bool dirObjToUpSong(const UPnPDirObject& dobj, UpSong *ups)
233
bool dirObjToUpSong(const UPnPDirObject& dobj, UpSong *ups)
289
{
234
{
290
    ups->artist = dobj.getprop("upnp:artist");
235
    ups->artist = dobj.getprop("upnp:artist");