Switch to unified view

a/libupnpp/control/avtransport.cxx b/libupnpp/control/avtransport.cxx
...
...
24
#include <upnp/upnp.h>
24
#include <upnp/upnp.h>
25
25
26
#include "libupnpp/soaphelp.hxx"
26
#include "libupnpp/soaphelp.hxx"
27
#include "libupnpp/upnpp_p.hxx"
27
#include "libupnpp/upnpp_p.hxx"
28
#include "libupnpp/log.hxx"
28
#include "libupnpp/log.hxx"
29
#include "libupnpp/upnpavutils.hxx"
29
#include "libupnpp/control/avtransport.hxx"
30
#include "libupnpp/control/avtransport.hxx"
30
#include "libupnpp/control/avlastchg.hxx"
31
#include "libupnpp/control/avlastchg.hxx"
32
#include "libupnpp/control/cdircontent.hxx"
31
33
32
namespace UPnPClient {
34
namespace UPnPClient {
33
35
34
const string AVTransport::SType("urn:schemas-upnp-org:service:AVTransport:1");
36
const string AVTransport::SType("urn:schemas-upnp-org:service:AVTransport:1");
35
37
...
...
39
{
41
{
40
    const string::size_type sz(SType.size()-2);
42
    const string::size_type sz(SType.size()-2);
41
    return !SType.compare(0, sz, st, 0, sz);
43
    return !SType.compare(0, sz, st, 0, sz);
42
}
44
}
43
45
46
static AVTransport::TransportState stringToTpState(const string& s)
47
{
48
    if (!stringuppercmp("STOPPED", s)) {
49
        return AVTransport::Stopped;
50
    } else if (!stringuppercmp("PLAYING", s)) {
51
        return AVTransport::Playing;
52
    } else if (!stringuppercmp("TRANSITIONING", s)) {
53
        return AVTransport::Transitioning;
54
    } else if (!stringuppercmp("PAUSED_PLAYBACK", s)) {
55
        return AVTransport::PausedPlayback;
56
    } else if (!stringuppercmp("PAUSED_RECORDING", s)) {
57
        return AVTransport::PausedRecording;
58
    } else if (!stringuppercmp("RECORDING", s)) {
59
        return AVTransport::Recording;
60
    } else if (!stringuppercmp("NO MEDIA PRESENT", s)) {
61
        return AVTransport::NoMediaPresent;
62
    } else {
63
        LOGERR("AVTransport event: bad value for TransportState: " 
64
               << s << endl);
65
        return AVTransport::Unknown;
66
    }
67
}
68
69
static AVTransport::TransportStatus stringToTpStatus(const string& s)
70
{
71
    if (!stringuppercmp("OK", s)) {
72
        return AVTransport::TPS_Ok;
73
    } else if (!stringuppercmp("ERROR_OCCURRED", s)) {
74
        return  AVTransport::TPS_Error;
75
    } else {
76
        LOGERR("AVTransport event: bad value for TransportStatus: " 
77
               << s << endl);
78
        return  AVTransport::TPS_Unknown;
79
    }
80
}
81
82
static AVTransport::PlayMode stringToPlayMode(const string& s)
83
{
84
    if (!stringuppercmp("NORMAL", s)) {
85
        return AVTransport::PM_Normal;
86
    } else if (!stringuppercmp("SHUFFLE", s)) {
87
        return AVTransport::PM_Shuffle;
88
    } else if (!stringuppercmp("REPEAT_ONE", s)) {
89
        return AVTransport::PM_RepeatOne;
90
    } else if (!stringuppercmp("REPEAT_ALL", s)) {
91
        return AVTransport::PM_RepeatAll;
92
    } else if (!stringuppercmp("RANDOM", s)) {
93
        return AVTransport::PM_Random;
94
    } else if (!stringuppercmp("DIRECT_1", s)) {
95
        return AVTransport::PM_Direct1;
96
    } else {
97
        LOGERR("AVTransport event: bad value for PlayMode: " 
98
               << s << endl);
99
        return AVTransport::PM_Unknown;
100
    }
101
}
102
44
void AVTransport::evtCallback(
103
void AVTransport::evtCallback(
45
    const std::unordered_map<std::string, std::string>& props)
104
    const std::unordered_map<std::string, std::string>& props)
46
{
105
{
47
    //LOGDEB("AVTransport::evtCallback:" << endl);
106
    LOGDEB1("AVTransport::evtCallback:" << endl);
48
    for (auto& entry: props) {
107
    for (auto& entry: props) {
49
        if (entry.first.compare("LastChange")) {
108
        if (entry.first.compare("LastChange")) {
50
            LOGINF("AVTransport:event: var not lastchange: "
109
            LOGINF("AVTransport:event: var not lastchange: "
51
                   << entry.first << " -> " << entry.second << endl;);
110
                   << entry.first << " -> " << entry.second << endl;);
52
            continue;
111
            continue;
53
        }
112
        }
113
        LOGDEB1("AVTransport:event: "
114
                << entry.first << " -> " << entry.second << endl;);
54
115
55
        std::unordered_map<std::string, std::string> props1;
116
        std::unordered_map<std::string, std::string> props1;
56
        if (!decodeAVLastChange(entry.second, props1)) {
117
        if (!decodeAVLastChange(entry.second, props1)) {
57
            LOGERR("AVTransport::evtCallback: bad LastChange value: "
118
            LOGERR("AVTransport::evtCallback: bad LastChange value: "
58
                   << entry.second << endl);
119
                   << entry.second << endl);
59
            return;
120
            return;
60
        }
121
        }
61
        for (auto& entry1: props1) {
122
        for (auto& entry1: props1) {
62
            //LOGDEB("    " << entry1.first << " -> " << 
123
            if (!m_reporter) {
124
                LOGDEB1("AVTransport::evtCallback: " << entry1.first << " -> " 
63
            //       entry1.second << endl);
125
                       << entry1.second << endl);
126
                continue;
127
            }
128
64
            if (!entry1.first.compare("TransportState")) {
129
            if (!entry1.first.compare("TransportState")) {
65
            } else if (!entry1.first.compare("CurrentTransportActions")) {
130
                m_reporter->changed(entry1.first.c_str(), 
131
                                    stringToTpState(entry1.second));
132
66
            } else if (!entry1.first.compare("TransportStatus")) {
133
            } else if (!entry1.first.compare("TransportStatus")) {
67
            } else if (!entry1.first.compare("TransportPlaySpeed")) {
134
                m_reporter->changed(entry1.first.c_str(), 
68
            } else if (!entry1.first.compare("CurrentTrack")) {
135
                                    stringToTpStatus(entry1.second));
69
            } else if (!entry1.first.compare("CurrentTrackURI")) {
136
70
            } else if (!entry1.first.compare("CurrentTrackMetaData")) {
71
            } else if (!entry1.first.compare("NumberOfTracks")) {
72
            } else if (!entry1.first.compare("CurrentMediaDuration")) {
73
            } else if (!entry1.first.compare("CurrentTrackDuration")) {
74
            } else if (!entry1.first.compare("AVTransportURI")) {
75
            } else if (!entry1.first.compare("AVTransportURIMetaData")) {
76
            } else if (!entry1.first.compare("RelativeTimePosition")) {
77
            } else if (!entry1.first.compare("AbsoluteTimePosition")) {
78
            } else if (!entry1.first.compare("NextAVTransportURI")) {
79
            } else if (!entry1.first.compare("NextAVTransportURIMetaData")){
80
            } else if (!entry1.first.compare("PlaybackStorageMedium")) {
81
            } else if (!entry1.first.compare("PossiblePlaybackStorageMedium")) {
82
            } else if (!entry1.first.compare("RecordStorageMedium")) {
83
            } else if (!entry1.first.compare("RelativeCounterPosition")) {
84
            } else if (!entry1.first.compare("AbsoluteCounterPosition")) {
85
            } else if (!entry1.first.compare("CurrentPlayMode")) {
137
            } else if (!entry1.first.compare("CurrentPlayMode")) {
138
                m_reporter->changed(entry1.first.c_str(), 
139
                                    stringToPlayMode(entry1.second));
140
141
            } else if (!entry1.first.compare("CurrentTransportActions") ||
142
                       !entry1.first.compare("CurrentTrackURI") ||
143
                       !entry1.first.compare("AVTransportURI") ||
144
                       !entry1.first.compare("NextAVTransportURI")) {
145
                m_reporter->changed(entry1.first.c_str(), 
146
                                    entry1.second.c_str());
147
148
            } else if (!entry1.first.compare("TransportPlaySpeed") ||
149
                       !entry1.first.compare("CurrentTrack") ||
150
                       !entry1.first.compare("NumberOfTracks") ||
151
                       !entry1.first.compare("RelativeCounterPosition") ||
152
                       !entry1.first.compare("AbsoluteCounterPosition") ||
153
                       !entry1.first.compare("InstanceID")) {
154
                m_reporter->changed(entry1.first.c_str(),
155
                                    atoi(entry1.second.c_str()));
156
157
            } else if (!entry1.first.compare("CurrentMediaDuration") ||
158
                       !entry1.first.compare("CurrentTrackDuration") ||
159
                       !entry1.first.compare("RelativeTimePosition") ||
160
                       !entry1.first.compare("AbsoluteTimePosition")) {
161
                m_reporter->changed(entry1.first.c_str(),
162
                                    upnpdurationtos(entry1.second));
163
164
            } else if (!entry1.first.compare("AVTransportURIMetaData") ||
165
                       !entry1.first.compare("NextAVTransportURIMetaData") ||
166
                       !entry1.first.compare("CurrentTrackMetaData")) {
167
                UPnPDirContent meta;
168
                if (!meta.parse(entry1.second)) {
169
                    LOGERR("AVTransport event: bad metadata: [" <<
170
                           entry1.second << "]" << endl);
171
                } else {
172
                    LOGDEB1("AVTransport event: metadata: " << 
173
                           meta.m_items.size() << " items " << endl);
174
                }
175
                
176
                m_reporter->changed(entry1.first.c_str(), meta);
177
86
            } else if (!entry1.first.compare("PossibleRecordStorageMedium")) {
178
            } else if (!entry1.first.compare("PlaybackStorageMedium") ||
179
                       !entry1.first.compare("PossiblePlaybackStorageMedium") ||
180
                       !entry1.first.compare("RecordStorageMedium") ||
181
                       !entry1.first.compare("PossibleRecordStorageMedium") ||
87
            } else if (!entry1.first.compare("RecordMediumWriteStatus")) {
182
                       !entry1.first.compare("RecordMediumWriteStatus") ||
88
            } else if (!entry1.first.compare("CurrentRecordQualityMode")) {
183
                       !entry1.first.compare("CurrentRecordQualityMode") ||
89
            } else if (!entry1.first.compare("PossibleRecordQualityModes")){
184
                       !entry1.first.compare("PossibleRecordQualityModes")){
185
                m_reporter->changed(entry1.first.c_str(),entry1.second.c_str());
186
187
            } else {
188
                LOGERR("AVTransport event: unknown variable: name [" <<
189
                       entry1.first << "] value [" << entry1.second << endl);
190
                m_reporter->changed(entry1.first.c_str(),entry1.second.c_str());
90
            }
191
            }
91
        }
192
        }
92
    }
193
    }
93
}
194
}
94
195
196
197
int AVTransport::setURI(const string& uri, const string& metadata,
198
                        int instanceID, bool next)
199
{
200
    SoapEncodeInput args(m_serviceType, next ? "SetNextAVTransportURI" :
201
                         "SetAVTransportURI");
202
    args("InstanceID", SoapHelp::i2s(instanceID))
203
        (next ? "NextURI" : "CurrentURI", uri)
204
        (next ? "NextURIMetaData" : "CurrentURIMetaData", metadata);
205
206
    SoapDecodeOutput data;
207
    return runAction(args, data);
208
}
209
210
int AVTransport::setPlayMode(PlayMode pm, int instanceID)
211
{
212
    SoapEncodeInput args(m_serviceType, "SetPlayMode");
213
    string playmode;
214
    switch (pm) {
215
    case PM_Normal: playmode = "NORMAL"; break;
216
    case PM_Shuffle: playmode = "SHUFFLE"; break;
217
    case PM_RepeatOne: playmode = "REPEAT_ONE"; break;
218
    case PM_RepeatAll: playmode = "REPEAT_ALL"; break;
219
    case PM_Random: playmode = "RANDOM"; break;
220
    case PM_Direct1: playmode = "DIRECT_1"; break;
221
    default: playmode = "NORMAL"; break;
222
    }
223
224
    args("InstanceID", SoapHelp::i2s(instanceID))
225
        ("NewPlayMode", playmode);
226
227
    SoapDecodeOutput data;
228
    return runAction(args, data);
229
}
230
231
int AVTransport::getMediaInfo(MediaInfo& info, int instanceID)
232
{
233
    SoapEncodeInput args(m_serviceType, "GetMediaInfo");
234
    args("InstanceID", SoapHelp::i2s(instanceID));
235
    SoapDecodeOutput data;
236
    int ret = runAction(args, data);
237
    if (ret != UPNP_E_SUCCESS) {
238
        return ret;
239
    }
240
    string s;
241
    data.getInt("NrTracks", &info.nrtracks);
242
    data.getString("MediaDuration", &s);
243
    info.mduration = upnpdurationtos(s);
244
    data.getString("CurrentURI", &info.cururi);
245
    data.getString("CurrentURIMetaData", &s);
246
    UPnPDirContent meta;
247
    meta.parse(s);
248
    if (meta.m_items.size() > 0)
249
        info.curmeta = meta.m_items[0];
250
    meta.clear();
251
    data.getString("NextURI", &info.nexturi);
252
    data.getString("NextURIMetaData", &s);
253
    if (meta.m_items.size() > 0)
254
        info.nextmeta = meta.m_items[0];
255
    data.getString("PlayMedium", &info.pbstoragemed);
256
    data.getString("RecordMedium", &info.pbstoragemed);
257
    data.getString("WriteStatus", &info.ws);
258
    return 0;
259
}
260
261
int AVTransport::getTransportInfo(TransportInfo& info, int instanceID)
262
{
263
    SoapEncodeInput args(m_serviceType, "GetTransportInfo");
264
    args("InstanceID", SoapHelp::i2s(instanceID));
265
    SoapDecodeOutput data;
266
    int ret = runAction(args, data);
267
    if (ret != UPNP_E_SUCCESS) {
268
        return ret;
269
    }
270
    string s;
271
    data.getString("CurrentTransportState", &s);
272
    info.tpstate = stringToTpState(s);
273
    data.getString("CurrentTransportStatus", &s);
274
    info.tpstatus = stringToTpStatus(s);
275
    data.getInt("CurrentSpeed", &info.curspeed);
276
    return 0;
277
}
278
279
int AVTransport::getPositionInfo(PositionInfo& info, int instanceID)
280
{
281
    SoapEncodeInput args(m_serviceType, "GetPositionInfo");
282
    args("InstanceID", SoapHelp::i2s(instanceID));
283
    SoapDecodeOutput data;
284
    int ret = runAction(args, data);
285
    if (ret != UPNP_E_SUCCESS) {
286
        return ret;
287
    }
288
    string s;
289
    data.getInt("Track", &info.track);
290
    data.getString("TrackDuration", &s);
291
    info.trackduration = upnpdurationtos(s);
292
    data.getString("TrackMetaData", &s);
293
    UPnPDirContent meta;
294
    meta.parse(s);
295
    if (meta.m_items.size() > 0) {
296
        info.trackmeta = meta.m_items[0];
297
            LOGDEB("AVTransport::getPositionInfo: size " << 
298
           meta.m_items.size() << " current title: " << meta.m_items[0].m_title
299
           << endl);
300
    }
301
    meta.clear();
302
    data.getString("TrackURI", &info.trackuri);
303
    data.getString("RelTime", &s);
304
    info.reltime = upnpdurationtos(s);
305
    data.getString("AbsTime", &s);
306
    info.abstime = upnpdurationtos(s);
307
    data.getInt("RelCount", &info.relcount);
308
    data.getInt("AbsCount", &info.abscount);
309
    return 0;
310
}
311
312
int AVTransport::getDeviceCapabilities(DeviceCapabilities& info, int iID)
313
{
314
    SoapEncodeInput args(m_serviceType, "GetDeviceCapabilities");
315
    args("InstanceID", SoapHelp::i2s(iID));
316
    SoapDecodeOutput data;
317
    int ret = runAction(args, data);
318
    if (ret != UPNP_E_SUCCESS) {
319
        return ret;
320
    }
321
    data.getString("PlayMedia", &info.playmedia);
322
    data.getString("RecMedia", &info.recmedia);
323
    data.getString("RecQualityModes", &info.recqualitymodes);
324
    return 0;
325
}
326
327
int AVTransport::getTransportSettings(TransportSettings& info, int instanceID)
328
{
329
    SoapEncodeInput args(m_serviceType, "GetTransportSettings");
330
    args("InstanceID", SoapHelp::i2s(instanceID));
331
    SoapDecodeOutput data;
332
    int ret = runAction(args, data);
333
    if (ret != UPNP_E_SUCCESS) {
334
        return ret;
335
    }
336
    string s;
337
    data.getString("PlayMedia", &s);
338
    info.playmode = stringToPlayMode(s);
339
    data.getString("RecQualityMode", &info.recqualitymode);
340
    return 0;
341
}
342
343
int AVTransport::getCurrentTransportActions(std::string& actions, int iID)
344
{
345
    SoapEncodeInput args(m_serviceType, "GetCurrentTransportActions");
346
    args("InstanceID", SoapHelp::i2s(iID));
347
    SoapDecodeOutput data;
348
    int ret = runAction(args, data);
349
    if (ret != UPNP_E_SUCCESS) {
350
        return ret;
351
    }
352
    data.getString("Actions", &actions);
353
    return 0;
354
}
355
356
int AVTransport::stop(int instanceID)
357
{
358
    SoapEncodeInput args(m_serviceType, "Stop");
359
    args("InstanceID", SoapHelp::i2s(instanceID));
360
    SoapDecodeOutput data;
361
    return runAction(args, data);
362
}
363
364
int AVTransport::pause(int instanceID)
365
{
366
    SoapEncodeInput args(m_serviceType, "Pause");
367
    args("InstanceID", SoapHelp::i2s(instanceID));
368
    SoapDecodeOutput data;
369
    return runAction(args, data);
370
}
371
372
int AVTransport::play(int speed, int instanceID)
373
{
374
    SoapEncodeInput args(m_serviceType, "Play");
375
    args("InstanceID", SoapHelp::i2s(instanceID))
376
        ("Speed", SoapHelp::i2s(speed));
377
    SoapDecodeOutput data;
378
    return runAction(args, data);
379
}
380
381
int AVTransport::seek(SeekMode mode, int target, int instanceID)
382
{
383
    string sm;
384
    switch (mode) {
385
    case SEEK_TRACK_NR: sm = "TRACK_NR"; break;
386
    case SEEK_ABS_TIME: sm = "ABS_TIME"; break;
387
    case SEEK_REL_TIME: sm = "REL_TIME"; break;
388
    case SEEK_ABS_COUNT: sm = "ABS_COUNT"; break;
389
    case SEEK_REL_COUNT: sm = "REL_COUNT"; break;
390
    case SEEK_CHANNEL_FREQ: sm = "CHANNEL_FREQ"; break;
391
    case SEEK_TAPE_INDEX: sm = "TAPE-INDEX"; break;
392
    case SEEK_FRAME: sm = "FRAME"; break;
393
    default:
394
        return UPNP_E_INVALID_PARAM;
395
    }
396
397
    SoapEncodeInput args(m_serviceType, "Play");
398
    args("InstanceID", SoapHelp::i2s(instanceID))
399
        ("Unit", sm)
400
        ("Target", SoapHelp::i2s(target));
401
    SoapDecodeOutput data;
402
    return runAction(args, data);
403
}
404
405
int AVTransport::next(int instanceID)
406
{
407
    SoapEncodeInput args(m_serviceType, "Next");
408
    args("InstanceID", SoapHelp::i2s(instanceID));
409
    SoapDecodeOutput data;
410
    return runAction(args, data);
411
}
412
413
int AVTransport::previous(int instanceID)
414
{
415
    SoapEncodeInput args(m_serviceType, "Previous");
416
    args("InstanceID", SoapHelp::i2s(instanceID));
417
    SoapDecodeOutput data;
418
    return runAction(args, data);
419
}
420
95
void AVTransport::registerCallback()
421
void AVTransport::registerCallback()
96
{
422
{
97
    Service::registerCallback(bind(&AVTransport::evtCallback, this, _1));
423
    Service::registerCallback(bind(&AVTransport::evtCallback, this, _1));
98
}
424
}
99
425