~ubuntu-branches/ubuntu/trusty/digikam/trusty

« back to all changes in this revision

Viewing changes to extra/kipi-plugins/dlnaexport/extra/hupnp_av/src/contentdirectory/hcontentdirectory_service.cpp

  • Committer: Package Import Robot
  • Author(s): Rohan Garg
  • Date: 2012-11-26 18:24:20 UTC
  • mfrom: (1.9.1) (3.1.23 experimental)
  • Revision ID: package-import@ubuntu.com-20121126182420-qoy6z0nx4ai0wzcl
Tags: 4:3.0.0~beta3-0ubuntu1
* New upstream release
  - Add build-deps :  libhupnp-dev, libqtgstreamer-dev, libmagickcore-dev
* Merge from debian, remaining changes:
  - Make sure libqt4-opengl-dev, libgl1-mesa-dev and libglu1-mesa-dev only
    install on i386,amd64 and powerpc
  - Depend on libtiff-dev instead of libtiff4-dev
  - Drop digikam breaks/replaces kipi-plugins-common since we're past the
    LTS release now
  - digikam to recommend mplayerthumbs | ffmpegthumbs. We currently only
    have latter in the archives, even though former is also supposed to
    be part of kdemultimedia. (LP: #890059)
  - kipi-plugins to recommend www-browser rather than konqueror directly
    since 2.8 no direct usage of konqueror is present in the flickr
    plugin anymore (LP: #1011211)
  - Keep kubuntu_mysqld_executable_name.diff
  - Don't install libkipi translations
  - Keep deps on libcv-dev, libcvaux-dev
  - Keep split packaging of libraries
  - Replace icons from KDE 3 time in debian/xpm.d/*.xpm with the new
    versions (LP: #658047)
* Update debian/not-installed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2011 Tuomo Penttinen, all rights reserved.
 
3
 *
 
4
 *  Author: Tuomo Penttinen <tp@herqq.org>
 
5
 *
 
6
 *  This file is part of Herqq UPnP Av (HUPnPAv) library.
 
7
 *
 
8
 *  Herqq UPnP Av is free software: you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License as published by
 
10
 *  the Free Software Foundation, either version 3 of the License, or
 
11
 *  (at your option) any later version.
 
12
 *
 
13
 *  Herqq UPnP Av is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
16
 *  GNU General Public License for more details.
 
17
 *
 
18
 *  You should have received a copy of the GNU General Public License
 
19
 *  along with Herqq UPnP Av. If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include "hcontentdirectory_service.h"
 
23
#include "hcontentdirectory_service_p.h"
 
24
 
 
25
#include "hsearchresult.h"
 
26
#include "htransferprogressinfo.h"
 
27
 
 
28
#include "../cds_model/hsortinfo.h"
 
29
#include "../cds_model/model_mgmt/hcdsproperty.h"
 
30
#include "../cds_model/model_mgmt/hcdsproperty_db.h"
 
31
#include "../cds_model/model_mgmt/hcds_dlite_serializer.h"
 
32
 
 
33
#include <HUpnpCore/private/hlogger_p.h>
 
34
 
 
35
#include <QtCore/QSet>
 
36
#include <QtCore/QString>
 
37
#include <QtCore/QStringList>
 
38
#include <QtCore/QXmlStreamWriter>
 
39
 
 
40
namespace Herqq
 
41
{
 
42
 
 
43
namespace Upnp
 
44
{
 
45
 
 
46
namespace Av
 
47
{
 
48
 
 
49
/*******************************************************************************
 
50
 * HContentDirectoryServicePrivate
 
51
 ******************************************************************************/
 
52
HContentDirectoryServicePrivate::HContentDirectoryServicePrivate() :
 
53
    m_dataSource(0), m_lastEventSent(false), m_timer(), m_modificationEvents()
 
54
{
 
55
}
 
56
 
 
57
HContentDirectoryServicePrivate::~HContentDirectoryServicePrivate()
 
58
{
 
59
    qDeleteAll(m_modificationEvents);
 
60
}
 
61
 
 
62
namespace
 
63
{
 
64
class Sorter
 
65
{
 
66
private:
 
67
 
 
68
    QList<HSortInfo> m_sortInfoObjects;
 
69
 
 
70
public:
 
71
 
 
72
    Sorter(){}
 
73
 
 
74
    Sorter(const QList<HSortInfo>& infoObjects) :
 
75
        m_sortInfoObjects(infoObjects)
 
76
    {
 
77
    }
 
78
 
 
79
    bool operator()(HObject* obj1, HObject* obj2) const
 
80
    {
 
81
        Q_ASSERT(obj1);
 
82
        Q_ASSERT(obj2);
 
83
 
 
84
        for(qint32 i = 0; i < m_sortInfoObjects.size(); ++i)
 
85
        {
 
86
            qint32 rc = 0;
 
87
            HSortInfo si = m_sortInfoObjects[i];
 
88
            QString property = si.property();
 
89
 
 
90
            QVariant value1, value2;
 
91
            if (obj1->getCdsProperty(property, &value1))
 
92
            {
 
93
                if (obj2->getCdsProperty(property, &value2))
 
94
                {
 
95
                    HCdsProperty prop = HCdsPropertyDb::instance().property(property);
 
96
                    if (prop.isValid())
 
97
                    {
 
98
                        if (!prop.handler().comparer()(value1, value2, &rc))
 
99
                        {
 
100
                            continue;
 
101
                        }
 
102
                    }
 
103
                }
 
104
            }
 
105
 
 
106
            if (rc < 0)
 
107
            {
 
108
                return si.sortModifier().ascending();
 
109
            }
 
110
            else if (rc > 0)
 
111
            {
 
112
                return !si.sortModifier().ascending();
 
113
            }
 
114
        }
 
115
 
 
116
        return true;
 
117
    }
 
118
};
 
119
}
 
120
 
 
121
qint32 HContentDirectoryServicePrivate::sort(
 
122
    const QStringList& sortCriteria, QList<HObject*>& objects)
 
123
{
 
124
    HLOG2(H_AT, H_FUN, m_loggingIdentifier);
 
125
    H_Q(HContentDirectoryService);
 
126
 
 
127
    QList<HSortInfo> sortInfoObjects;
 
128
    for (qint32 i = 0; i < sortCriteria.size(); ++i)
 
129
    {
 
130
        QString tmp = sortCriteria[i].trimmed();
 
131
 
 
132
        if (tmp.isEmpty())
 
133
        {
 
134
            continue;
 
135
        }
 
136
 
 
137
        qint32 j = 0;
 
138
        QChar ch = 0;
 
139
        QString sortExtension;
 
140
        for(; j < tmp.size(); ++j)
 
141
        {
 
142
            ch = tmp[j];
 
143
            if (ch == '+' || ch == '-')
 
144
            {
 
145
                break;
 
146
            }
 
147
            sortExtension.append(ch);
 
148
        }
 
149
 
 
150
        if (ch != '+' && ch != '-')
 
151
        {
 
152
            return HContentDirectoryInfo::InvalidSortCriteria;
 
153
        }
 
154
 
 
155
        bool ascending = ch == '+';
 
156
 
 
157
        QStringList sortExtensions;
 
158
        q->getSortExtensionCapabilities(&sortExtensions);
 
159
 
 
160
        if (!sortExtension.isEmpty() && !sortExtension.contains(
 
161
            sortExtension, Qt::CaseInsensitive))
 
162
        {
 
163
            return HContentDirectoryInfo::InvalidSortCriteria;
 
164
        }
 
165
 
 
166
        QString sortProperty;
 
167
        for(++j; j < tmp.size(); ++j)
 
168
        {
 
169
            ch = tmp[j];
 
170
            sortProperty.append(ch);
 
171
        }
 
172
 
 
173
        QStringList sortCapabilities;
 
174
        q->getSortCapabilities(&sortCapabilities);
 
175
 
 
176
        if (!sortCapabilities.contains(sortProperty, Qt::CaseInsensitive) &&
 
177
            !sortCapabilities.contains("*"))
 
178
        {
 
179
            return HContentDirectoryInfo::InvalidSortCriteria;
 
180
        }
 
181
 
 
182
        HSortModifier modifier(
 
183
            QString("%1%2").arg(
 
184
                sortExtension, ascending ? QString("+") : QString("-")));
 
185
 
 
186
        HSortInfo so(sortProperty, modifier);
 
187
        sortInfoObjects.append(so);
 
188
    }
 
189
 
 
190
    qStableSort(objects.begin(), objects.end(), Sorter(sortInfoObjects));
 
191
 
 
192
    return 0;
 
193
}
 
194
 
 
195
qint32 HContentDirectoryServicePrivate::browseDirectChildren(
 
196
    const QString& containerId, const QSet<QString>& filter,
 
197
    const QStringList& sortCriteria, quint32 startingIndex,
 
198
    quint32 requestedCount, HSearchResult* result)
 
199
{
 
200
    HLOG2(H_AT, H_FUN, m_loggingIdentifier);
 
201
    H_Q(HContentDirectoryService);
 
202
 
 
203
    HContainer* container = m_dataSource->findContainer(containerId);
 
204
    if (!container)
 
205
    {
 
206
        HLOG_WARN(QString(
 
207
            "The specified object ID [%1] does not map to a container").arg(
 
208
                containerId));
 
209
 
 
210
        return HContentDirectoryInfo::InvalidObjectId;
 
211
    }
 
212
 
 
213
    HLOG_DBG(QString(
 
214
        "Browsing container [id: %1, startingIndex: %2, "
 
215
        "requestedCount: %3, filter: %4, sortCriteria: %5]").arg(
 
216
            containerId,
 
217
            QString::number(startingIndex),
 
218
            QString::number(requestedCount),
 
219
            QStringList(filter.toList()).join(","),
 
220
            sortCriteria.join(",")));
 
221
 
 
222
    QSet<QString> childIDs = container->childIds();
 
223
    quint32 childCount = static_cast<quint32>(childIDs.size());
 
224
 
 
225
    if (startingIndex > childCount)
 
226
    {
 
227
        return UpnpInvalidArgs;
 
228
    }
 
229
 
 
230
    HObjects objects = m_dataSource->findObjects(childIDs);
 
231
    Q_ASSERT(objects.size() == childIDs.size());
 
232
 
 
233
    if (!sortCriteria.isEmpty())
 
234
    {
 
235
        qint32 rc = sort(sortCriteria, objects);
 
236
        if (rc != 0)
 
237
        {
 
238
            return rc;
 
239
        }
 
240
    }
 
241
 
 
242
    quint32 numberReturned = requestedCount > 0 ?
 
243
        qMin(requestedCount, childCount - startingIndex) :
 
244
        childCount - startingIndex;
 
245
 
 
246
    objects = objects.mid(startingIndex, requestedCount ? requestedCount : -1);
 
247
 
 
248
    HCdsDidlLiteSerializer ser;
 
249
    QString dliteDoc = ser.serializeToXml(objects, filter);
 
250
 
 
251
    HSearchResult retVal(
 
252
        dliteDoc, numberReturned, childCount,
 
253
        q->stateVariables().value("A_ARG_TYPE_UpdateID")->value().toUInt());
 
254
 
 
255
    *result = retVal;
 
256
 
 
257
    return UpnpSuccess;
 
258
}
 
259
 
 
260
qint32 HContentDirectoryServicePrivate::browseMetadata(
 
261
    const QString& objectId, const QSet<QString>& filter, quint32 startingIndex,
 
262
    HSearchResult* result)
 
263
{
 
264
    HLOG2(H_AT, H_FUN, m_loggingIdentifier);
 
265
    H_Q(HContentDirectoryService);
 
266
 
 
267
    if (startingIndex)
 
268
    {
 
269
        HLOG_WARN(QString(
 
270
            "The starting index was specified as [%1], although it "
 
271
            "should be zero when browsing meta data").arg(
 
272
                QString::number(startingIndex)));
 
273
 
 
274
        return UpnpInvalidArgs;
 
275
    }
 
276
 
 
277
    HObject* object = m_dataSource->findObject(objectId);
 
278
    if (!object)
 
279
    {
 
280
        HLOG_WARN(QString(
 
281
            "No object was found with the specified object ID [%1]").arg(
 
282
                objectId));
 
283
 
 
284
        return HContentDirectoryInfo::InvalidObjectId;
 
285
    }
 
286
 
 
287
    HCdsDidlLiteSerializer serializer;
 
288
    QString dliteDoc = serializer.serializeToXml(
 
289
        *object, filter, HCdsDidlLiteSerializer::Document);
 
290
 
 
291
    HSearchResult retVal(
 
292
        dliteDoc, 1, 1,
 
293
        q->stateVariables().value("A_ARG_TYPE_UpdateID")->value().toUInt());
 
294
 
 
295
    *result = retVal;
 
296
 
 
297
    return UpnpSuccess;
 
298
}
 
299
 
 
300
void HContentDirectoryServicePrivate::enableChangeTracking()
 
301
{
 
302
    H_Q(HContentDirectoryService);
 
303
 
 
304
    bool ok = QObject::connect(
 
305
        m_dataSource, SIGNAL(objectModified(Herqq::Upnp::Av::HObject*, Herqq::Upnp::Av::HObjectEventInfo)),
 
306
        q, SLOT(objectModified(Herqq::Upnp::Av::HObject*, Herqq::Upnp::Av::HObjectEventInfo)));
 
307
    Q_ASSERT(ok); Q_UNUSED(ok)
 
308
 
 
309
    ok = QObject::connect(
 
310
        m_dataSource, SIGNAL(containerModified(Herqq::Upnp::Av::HContainer*, Herqq::Upnp::Av::HContainerEventInfo)),
 
311
        q, SLOT(containerModified(Herqq::Upnp::Av::HContainer*, Herqq::Upnp::Av::HContainerEventInfo)));
 
312
    Q_ASSERT(ok);
 
313
 
 
314
    ok = QObject::connect(
 
315
        m_dataSource, SIGNAL(independentObjectAdded(Herqq::Upnp::Av::HObject*)),
 
316
        q, SLOT(independentObjectAdded(Herqq::Upnp::Av::HObject*)));
 
317
    Q_ASSERT(ok);
 
318
 
 
319
    foreach(HObject* object, m_dataSource->objects())
 
320
    {
 
321
        object->setTrackChangesOption(true);
 
322
    }
 
323
 
 
324
    m_timer.start();
 
325
}
 
326
 
 
327
QString HContentDirectoryServicePrivate::generateLastChange()
 
328
{
 
329
    QString retVal;
 
330
 
 
331
    QXmlStreamWriter writer(&retVal);
 
332
 
 
333
    writer.setCodec("UTF-8");
 
334
    writer.writeStartDocument();
 
335
    writer.writeStartElement("StateEvent");
 
336
    writer.writeDefaultNamespace("urn:schemas-upnp-org:av:cds-event");
 
337
    writer.writeAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
 
338
    writer.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
 
339
 
 
340
    writer.writeAttribute("xsi:schemaLocation",
 
341
        "urn:schemas-upnp-org:av:cds-event" \
 
342
        "http://www.upnp.org/schemas/av/cds-events.xsd");
 
343
 
 
344
    foreach(const HModificationEvent* event, m_modificationEvents)
 
345
    {
 
346
        if (event->type() == HModificationEvent::ContainerModification)
 
347
        {
 
348
            HContainerEventInfo cEvent = event->containerEvent();
 
349
 
 
350
            switch(cEvent.type())
 
351
            {
 
352
            case HContainerEventInfo::ChildAdded:
 
353
                if (event->source())
 
354
                {
 
355
                    HObject* newObj = m_dataSource->findObject(cEvent.childId());
 
356
                    if (newObj)
 
357
                    {
 
358
                        writer.writeStartElement("objAdd");
 
359
                        writer.writeAttribute("objParentID", event->source()->id());
 
360
                        writer.writeAttribute("objClass", newObj->clazz());
 
361
                    }
 
362
                }
 
363
                break;
 
364
            case HContainerEventInfo::ChildRemoved:
 
365
                writer.writeStartElement("objDel");
 
366
                break;
 
367
            case HContainerEventInfo::ChildModified:
 
368
                writer.writeStartElement("objMod");
 
369
                break;
 
370
            default:
 
371
                Q_ASSERT(false);
 
372
                break;
 
373
            }
 
374
 
 
375
            writer.writeAttribute("objID", cEvent.childId());
 
376
            writer.writeAttribute("updateID", QString::number(cEvent.updateId()));
 
377
            writer.writeAttribute("stUpdate", "0");
 
378
            writer.writeEndElement();
 
379
        }
 
380
        else
 
381
        {
 
382
            if (event->source())
 
383
            {
 
384
                HObjectEventInfo oEvent = event->objectEvent();
 
385
                writer.writeStartElement("objMod");
 
386
                writer.writeAttribute("objID", event->source()->id());
 
387
                writer.writeAttribute("updateID", QString::number(oEvent.updateId()));
 
388
                writer.writeAttribute("stUpdate", "0");
 
389
                writer.writeEndElement();
 
390
            }
 
391
        }
 
392
    }
 
393
    writer.writeEndElement();
 
394
 
 
395
    return retVal;
 
396
}
 
397
 
 
398
/*******************************************************************************
 
399
 * HContentDirectoryService
 
400
 ******************************************************************************/
 
401
HContentDirectoryService::HContentDirectoryService(
 
402
    HContentDirectoryServicePrivate& dd) :
 
403
        HAbstractContentDirectoryService(dd)
 
404
{
 
405
    H_D(HContentDirectoryService);
 
406
    h->m_timer.setInterval(200);
 
407
    bool ok = connect(&h->m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
 
408
    Q_ASSERT(ok); Q_UNUSED(ok)
 
409
}
 
410
 
 
411
HContentDirectoryService::HContentDirectoryService(HAbstractCdsDataSource* dataSource) :
 
412
    HAbstractContentDirectoryService(
 
413
        *new HContentDirectoryServicePrivate())
 
414
{
 
415
    H_D(HContentDirectoryService);
 
416
    Q_ASSERT_X(dataSource, "", "Valid HCdsDataSource has to be provided");
 
417
    h->m_dataSource = dataSource;
 
418
    h->m_timer.setInterval(200);
 
419
    bool ok = connect(&h->m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
 
420
    Q_ASSERT(ok); Q_UNUSED(ok)
 
421
}
 
422
 
 
423
void HContentDirectoryService::timeout()
 
424
{
 
425
    H_D(HContentDirectoryService);
 
426
    if (!h->m_lastEventSent && h->m_modificationEvents.size())
 
427
    {
 
428
        QString lastChangeData = h->generateLastChange();
 
429
        bool ok = setValue("LastChange", lastChangeData);
 
430
        h->m_lastEventSent = true;
 
431
        Q_ASSERT(ok); Q_UNUSED(ok)
 
432
    }
 
433
}
 
434
 
 
435
void HContentDirectoryService::objectModified(
 
436
    HObject* source, const HObjectEventInfo& eventInfo)
 
437
{
 
438
    H_D(HContentDirectoryService);
 
439
    if (h->m_lastEventSent)
 
440
    {
 
441
        h->m_modificationEvents.clear();
 
442
        h->m_lastEventSent = false;
 
443
    }
 
444
 
 
445
    HObjectEventInfo einfo(eventInfo);
 
446
 
 
447
    quint32 sysUpdateId;
 
448
    qint32 retVal = getSystemUpdateId(&sysUpdateId);
 
449
    Q_ASSERT(retVal == UpnpSuccess); Q_UNUSED(retVal)
 
450
 
 
451
    einfo.setUpdateId(sysUpdateId);
 
452
 
 
453
    source->setObjectUpdateId(sysUpdateId);
 
454
 
 
455
    h->m_modificationEvents.append(new HModificationEvent(source, einfo));
 
456
}
 
457
 
 
458
void HContentDirectoryService::containerModified(
 
459
    HContainer* source, const HContainerEventInfo& eventInfo)
 
460
{
 
461
    H_D(HContentDirectoryService);
 
462
 
 
463
    if (eventInfo.type() == HContainerEventInfo::ChildAdded)
 
464
    {
 
465
        HItem* item = h->m_dataSource->findItem(eventInfo.childId());
 
466
        if (item)
 
467
        {
 
468
            if (stateVariables().contains("LastChange"))
 
469
            {
 
470
                item->setTrackChangesOption(true);
 
471
            }
 
472
        }
 
473
    }
 
474
 
 
475
    if (h->m_lastEventSent)
 
476
    {
 
477
        h->m_modificationEvents.clear();
 
478
        h->m_lastEventSent = false;
 
479
    }
 
480
 
 
481
    HContainerEventInfo einfo(eventInfo);
 
482
 
 
483
    quint32 sysUpdateId;
 
484
    qint32 retVal = getSystemUpdateId(&sysUpdateId);
 
485
    Q_ASSERT(retVal == UpnpSuccess); Q_UNUSED(retVal)
 
486
 
 
487
    einfo.setUpdateId(sysUpdateId);
 
488
 
 
489
    source->setContainerUpdateId(sysUpdateId);
 
490
 
 
491
    h->m_modificationEvents.append(new HModificationEvent(source, einfo));
 
492
}
 
493
 
 
494
void HContentDirectoryService::independentObjectAdded(HObject* source)
 
495
{
 
496
    Q_UNUSED(source)
 
497
    //H_D(HContentDirectoryService);
 
498
}
 
499
 
 
500
bool HContentDirectoryService::init()
 
501
{
 
502
    H_D(HContentDirectoryService);
 
503
 
 
504
    if (stateVariables().contains("LastChange"))
 
505
    {
 
506
        h->enableChangeTracking();
 
507
    }
 
508
 
 
509
    return true;
 
510
}
 
511
 
 
512
HContentDirectoryService::~HContentDirectoryService()
 
513
{
 
514
}
 
515
 
 
516
qint32 HContentDirectoryService::getSearchCapabilities(QStringList* oarg) const
 
517
{
 
518
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);
 
519
    Q_ASSERT_X(oarg, H_AT, "Out argument(s) cannot be null");
 
520
 
 
521
    oarg->clear();
 
522
 
 
523
//    *oarg = QString(
 
524
//        "@id,@parentID,upnp:class,upnp:objectUpdateID,"
 
525
//        "upnp:containerUpdateID,dc:title,dc:creator,dc:date,res@size").split(',');
 
526
// TODO once search is included
 
527
 
 
528
    return UpnpSuccess;
 
529
}
 
530
 
 
531
qint32 HContentDirectoryService::getSortCapabilities(QStringList* oarg) const
 
532
{
 
533
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);
 
534
    Q_ASSERT_X(oarg, H_AT, "Out argument(s) cannot be null");
 
535
 
 
536
    *oarg = QString("dc:title,dc:creator,dc:date,res@size").split(',');
 
537
    return UpnpSuccess;
 
538
}
 
539
 
 
540
qint32 HContentDirectoryService::getSortExtensionCapabilities(
 
541
    QStringList* oarg) const
 
542
{
 
543
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);
 
544
    Q_ASSERT_X(oarg, H_AT, "Out argument(s) cannot be null");
 
545
 
 
546
    if (!actions().value("GetSortExtensionCapabilities"))
 
547
    {
 
548
        return UpnpOptionalActionNotImplemented;
 
549
    }
 
550
 
 
551
    *oarg = QString("+,-,TIME+,TIME-").split(',');
 
552
    return UpnpSuccess;
 
553
}
 
554
 
 
555
qint32 HContentDirectoryService::getFeatureList(QString* oarg) const
 
556
{
 
557
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);
 
558
    Q_ASSERT_X(oarg, H_AT, "Out argument(s) cannot be null");
 
559
 
 
560
    *oarg = QString();
 
561
    return UpnpSuccess;
 
562
}
 
563
 
 
564
qint32 HContentDirectoryService::getSystemUpdateId(quint32* oarg) const
 
565
{
 
566
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);
 
567
    Q_ASSERT_X(oarg, H_AT, "Out argument(s) cannot be null");
 
568
 
 
569
    *oarg = stateVariables().value("SystemUpdateID")->value().toUInt();
 
570
    return UpnpSuccess;
 
571
}
 
572
 
 
573
qint32 HContentDirectoryService::getServiceResetToken(QString* oarg) const
 
574
{
 
575
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);
 
576
    Q_ASSERT_X(oarg, H_AT, "Out argument(s) cannot be null");
 
577
 
 
578
    *oarg = stateVariables().value("ServiceResetToken")->value().toString();
 
579
    return UpnpSuccess;
 
580
}
 
581
 
 
582
qint32 HContentDirectoryService::browse(
 
583
    const QString& objectId, HContentDirectoryInfo::BrowseFlag browseFlag,
 
584
    const QSet<QString>& filter, quint32 startingIndex, quint32 requestedCount,
 
585
    const QStringList& sortCriteria, HSearchResult* result)
 
586
{
 
587
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);
 
588
    Q_ASSERT_X(result, H_AT, "Out argument(s) cannot be null");
 
589
 
 
590
    H_D(HContentDirectoryService);
 
591
 
 
592
    if (!result)
 
593
    {
 
594
        Q_ASSERT(false);
 
595
        return UpnpInvalidArgs;
 
596
    }
 
597
 
 
598
    HLOG_INFO(QString("processing browse request to object id %1").arg(objectId));
 
599
 
 
600
    qint32 retVal = 0;
 
601
    switch(browseFlag)
 
602
    {
 
603
    case HContentDirectoryInfo::BrowseDirectChildren:
 
604
 
 
605
        retVal = h->browseDirectChildren(
 
606
            objectId, filter, sortCriteria, startingIndex, requestedCount,
 
607
            result);
 
608
 
 
609
        break;
 
610
 
 
611
    case HContentDirectoryInfo::BrowseMetadata:
 
612
 
 
613
        retVal = h->browseMetadata(objectId, filter, startingIndex, result);
 
614
        break;
 
615
 
 
616
    default:
 
617
        HLOG_WARN(QString("received invalid browse flag"));
 
618
        retVal = UpnpInvalidArgs;
 
619
        break;
 
620
    }
 
621
 
 
622
    if (retVal != UpnpSuccess)
 
623
    {
 
624
        return retVal;
 
625
    }
 
626
 
 
627
    HLOG_INFO(QString(
 
628
        "Browse handled successfully: returned: [%1] matching objects of [%2] "
 
629
        "possible totals.").arg(
 
630
            QString::number(result->numberReturned()),
 
631
            QString::number(result->totalMatches())));
 
632
 
 
633
    return retVal;
 
634
}
 
635
 
 
636
qint32 HContentDirectoryService::search(
 
637
    const QString& containerId, const QString& /*searchCriteria*/,
 
638
    const QSet<QString>& /*filter*/, quint32 /*startingIndex*/,
 
639
    quint32 /*requestedCount*/, const QStringList& /*sortCriteria*/,
 
640
    HSearchResult* result)
 
641
{
 
642
    H_D(HContentDirectoryService);
 
643
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);
 
644
 
 
645
    if (!result)
 
646
    {
 
647
        Q_ASSERT(false);
 
648
        return UpnpInvalidArgs;
 
649
    }
 
650
 
 
651
    if (!actions().value("Search"))
 
652
    {
 
653
        return UpnpOptionalActionNotImplemented;
 
654
    }
 
655
 
 
656
    HLOG_INFO(QString("attempting to locate container with id %1").arg(
 
657
        containerId));
 
658
 
 
659
    HContainer* container = qobject_cast<HContainer*>(
 
660
        h->m_dataSource->findObject(containerId));
 
661
 
 
662
    if (!container)
 
663
    {
 
664
        return HContentDirectoryInfo::InvalidObjectId;
 
665
    }
 
666
 
 
667
    return UpnpSuccess;
 
668
}
 
669
 
 
670
}
 
671
}
 
672
}