~ubuntu-branches/ubuntu/oneiric/phonon/oneiric-201108111512

« back to all changes in this revision

Viewing changes to phonon/mediaobject.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Romain Perier
  • Date: 2011-03-29 18:52:38 UTC
  • mfrom: (0.5.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110329185238-zsdke31jv37427js
Tags: 4:4.7.0really4.5.0-0ubuntu1
* New upstream release, LP: #750480
* Create new package libphonon4-designer for the Qt4 Designer plugin
* Add libqzeitgeist to build dependencies
* debian/libphononexperimental4.install:
  Change library name to libphononexperimental4.so.4.*
* Update symbols

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*  This file is part of the KDE project
2
2
    Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>
 
3
    Copyright (C) 2011 Trever Fischer <tdfischer@kde.org>
3
4
 
4
5
    This library is free software; you can redistribute it and/or
5
6
    modify it under the terms of the GNU Lesser General Public
30
31
#include "abstractmediastream_p.h"
31
32
#include "frontendinterface_p.h"
32
33
 
 
34
#include <QtCore/QStringBuilder>
33
35
#include <QtCore/QStringList>
 
36
#include <QtCore/QDateTime>
 
37
#include <QtCore/QTimer>
34
38
#include <QtCore/QUrl>
35
 
#include <QtCore/QTimer>
 
39
 
 
40
#ifdef HAVE_QZEITGEIST
 
41
#include <QtZeitgeist/DataModel/Event>
 
42
#include <QtZeitgeist/Interpretation>
 
43
#include <QtZeitgeist/Log>
 
44
#include <QtZeitgeist/Manifestation>
 
45
#include <QtZeitgeist/QtZeitgeist>
 
46
#endif
36
47
 
37
48
#include "phononnamespace_p.h"
38
49
#include "platform_p.h"
159
170
{
160
171
    switch (f) {
161
172
    case ArtistMetaData:
162
 
        return metaData(QLatin1String("ARTIST"     ));
 
173
        return metaData(QLatin1String("ARTIST"));
163
174
    case AlbumMetaData:
164
 
        return metaData(QLatin1String("ALBUM"      ));
 
175
        return metaData(QLatin1String("ALBUM"));
165
176
    case TitleMetaData:
166
 
        return metaData(QLatin1String("TITLE"      ));
 
177
        return metaData(QLatin1String("TITLE"));
167
178
    case DateMetaData:
168
 
        return metaData(QLatin1String("DATE"       ));
 
179
        return metaData(QLatin1String("DATE"));
169
180
    case GenreMetaData:
170
 
        return metaData(QLatin1String("GENRE"      ));
 
181
        return metaData(QLatin1String("GENRE"));
171
182
    case TracknumberMetaData:
172
183
        return metaData(QLatin1String("TRACKNUMBER"));
173
184
    case DescriptionMetaData:
238
249
            // for setting a new URL
239
250
 
240
251
    d->mediaSource = newSource;
241
 
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
242
 
    d->kiofallback = 0; // kiofallback auto-deletes
243
 
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
244
 
 
245
 
//X         if (url.scheme() == "http") {
246
 
//X             d->kiofallback = Platform::createMediaStream(url, this);
247
 
//X             if (d->kiofallback) {
248
 
//X                 ...
249
 
//X                 return;
250
 
//X             }
251
 
//X         }
252
 
 
253
 
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
 
252
 
 
253
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
 
254
    d->abstractStream = 0; // abstractStream auto-deletes
254
255
    if (d->mediaSource.type() == MediaSource::Stream) {
255
256
        Q_ASSERT(d->mediaSource.stream());
256
257
        d->mediaSource.stream()->d_func()->setMediaObjectPrivate(d);
318
319
    d->sourceQueue.clear();
319
320
}
320
321
 
 
322
void MediaObjectPrivate::sendToZeitgeist(const QString &event_interpretation,
 
323
                                         const QString &event_manifestation,
 
324
                                         const QString &event_actor,
 
325
                                         const QDateTime &subject_timestamp,
 
326
                                         const QUrl &subject_uri,
 
327
                                         const QString &subject_text,
 
328
                                         const QString &subject_interpretation,
 
329
                                         const QString &subject_manifestation,
 
330
                                         const QString &subject_mimetype)
 
331
{
 
332
#ifdef HAVE_QZEITGEIST
 
333
    QtZeitgeist::DataModel::Subject subject;
 
334
    QString url = subject_uri.toString();
 
335
    QString path = url.left(url.lastIndexOf(QLatin1Char('/')));
 
336
    subject.setUri(url);
 
337
    subject.setText(subject_text);
 
338
    subject.setInterpretation(subject_interpretation);
 
339
    subject.setManifestation(subject_manifestation);
 
340
    subject.setOrigin(path);
 
341
    subject.setMimeType(subject_mimetype);
 
342
 
 
343
    QtZeitgeist::DataModel::SubjectList subjects;
 
344
    subjects << subject;
 
345
 
 
346
    QtZeitgeist::DataModel::Event event;
 
347
    event.setTimestamp(subject_timestamp);
 
348
    event.setInterpretation(event_interpretation);
 
349
    event.setManifestation(event_manifestation);
 
350
    event.setActor(event_actor);
 
351
    event.setSubjects(subjects);
 
352
 
 
353
    QtZeitgeist::DataModel::EventList events;
 
354
    events << event;
 
355
 
 
356
    QDBusPendingReply<QtZeitgeist::DataModel::EventIdList> reply =
 
357
        log->insertEvents(events);
 
358
#else
 
359
    Q_UNUSED(event_interpretation)
 
360
    Q_UNUSED(event_manifestation)
 
361
    Q_UNUSED(event_actor)
 
362
    Q_UNUSED(subject_timestamp)
 
363
    Q_UNUSED(subject_uri)
 
364
    Q_UNUSED(subject_text)
 
365
    Q_UNUSED(subject_interpretation)
 
366
    Q_UNUSED(subject_manifestation)
 
367
    Q_UNUSED(subject_mimetype)
 
368
#endif
 
369
}
 
370
 
 
371
void MediaObjectPrivate::sendToZeitgeist(State eventState)
 
372
{
 
373
#ifdef HAVE_QZEITGEIST
 
374
    Q_Q(MediaObject);
 
375
    if (readyForZeitgeist && q->property("PlaybackTracking").toBool()) {
 
376
        pDebug() << "Current state:" << eventState;
 
377
        QString eventInterpretation;
 
378
        switch (eventState) {
 
379
        case PlayingState:
 
380
            eventInterpretation = QtZeitgeist::Interpretation::Event::ZGAccessEvent;
 
381
            break;
 
382
        case ErrorState:
 
383
        case StoppedState:
 
384
            eventInterpretation = QtZeitgeist::Interpretation::Event::ZGLeaveEvent;
 
385
            break;
 
386
        //These states are not signifigant events.
 
387
        case LoadingState:
 
388
        case BufferingState:
 
389
        case PausedState:
 
390
            return;
 
391
            break;
 
392
        }
 
393
 
 
394
        QStringList titles = q->metaData(TitleMetaData);
 
395
        QStringList artists = q->metaData(ArtistMetaData);
 
396
        QString title;
 
397
        if (titles.empty()) {
 
398
            QString file = mediaSource.url().toString();
 
399
            title = file.right(file.length()-file.lastIndexOf("/")-1);
 
400
        } else {
 
401
            if (artists.empty()) {
 
402
                title = titles[0];
 
403
            } else {
 
404
                title = QString(QObject::tr("%0 by %1")).arg(titles[0]).arg(artists[0]);
 
405
            }
 
406
        }
 
407
        pDebug() << "Sending" << title << "to zeitgeist";
 
408
 
 
409
        QString mime;
 
410
        QString subjectInterpretation;
 
411
        if (q->hasVideo()) {
 
412
            subjectInterpretation = QtZeitgeist::Interpretation::Subject::NFOVideo;
 
413
            mime = "video/raw";
 
414
        } else {
 
415
            subjectInterpretation = QtZeitgeist::Interpretation::Subject::NFOAudio;
 
416
            mime = "audio/raw";
 
417
        }
 
418
        pDebug() << "Zeitgeist mime type:" << mime;
 
419
        pDebug() << "Zeitgeist URL:" << mediaSource.url();
 
420
        pDebug() << "mediasource type:" << mediaSource.type();
 
421
 
 
422
        QString subjectType;
 
423
        switch (mediaSource.type()) {
 
424
        case MediaSource::Empty:
 
425
        case MediaSource::Invalid:
 
426
            return;
 
427
        case MediaSource::Url:
 
428
            subjectType = QtZeitgeist::Manifestation::Subject::NFORemoteDataObject;
 
429
            break;
 
430
        case MediaSource::CaptureDevice:
 
431
        case MediaSource::Disc:
 
432
        case MediaSource::Stream:
 
433
            subjectType = QtZeitgeist::Manifestation::Subject::NFOMediaStream;
 
434
            break;
 
435
        case MediaSource::LocalFile:
 
436
            subjectType = QtZeitgeist::Manifestation::Subject::NFOFileDataObject;
 
437
            break;
 
438
        }
 
439
 
 
440
        sendToZeitgeist(eventInterpretation,
 
441
                        QtZeitgeist::Manifestation::Event::ZGUserActivity,
 
442
                        QLatin1Literal("app://" ) % Platform::applicationName() % QLatin1Literal(".desktop"),
 
443
                        QDateTime::currentDateTime(),
 
444
                        mediaSource.url(),
 
445
                        title,
 
446
                        subjectInterpretation,
 
447
                        subjectType,
 
448
                        mime);
 
449
    }
 
450
    // Unset this so we don't send it again after a pause+play
 
451
    readyForZeitgeist = false;
 
452
#else
 
453
    Q_UNUSED(eventState)
 
454
#endif
 
455
}
 
456
 
 
457
void MediaObjectPrivate::sendToZeitgeist()
 
458
{
 
459
    Q_Q(MediaObject);
 
460
    sendToZeitgeist(q->state());
 
461
}
 
462
 
321
463
bool MediaObjectPrivate::aboutToDeleteBackendObject()
322
464
{
323
465
    //pDebug() << Q_FUNC_INFO;
344
486
    QMetaObject::invokeMethod(q, "stateChanged", Qt::QueuedConnection, Q_ARG(Phonon::State, Phonon::ErrorState), Q_ARG(Phonon::State, lastState));
345
487
    //emit q->stateChanged(ErrorState, lastState);
346
488
}
 
489
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
347
490
 
 
491
// TODO: this needs serious cleanup...
348
492
void MediaObjectPrivate::_k_stateChanged(Phonon::State newstate, Phonon::State oldstate)
349
493
{
350
494
    Q_Q(MediaObject);
351
495
 
 
496
    // Zeitgeist ---------------------------------------------------------------
 
497
    if (newstate == StoppedState) {
 
498
        readyForZeitgeist = true;
 
499
    }
 
500
    pDebug() << "State changed from" << oldstate << "to" << newstate << "-> sending to zeitgeist.";
 
501
    sendToZeitgeist(newstate);
 
502
 
 
503
    // AbstractMediaStream fallback stuff --------------------------------------
352
504
    if (errorOverride) {
353
505
        errorOverride = false;
354
506
        if (newstate == ErrorState) {
364
516
    }
365
517
 
366
518
    // backend MediaObject reached ErrorState, try a KioMediaSource
367
 
    if (newstate == Phonon::ErrorState && !kiofallback) {
368
 
        kiofallback = Platform::createMediaStream(mediaSource.url(), q);
369
 
        if (!kiofallback) {
 
519
    if (newstate == Phonon::ErrorState && !abstractStream) {
 
520
        abstractStream = Platform::createMediaStream(mediaSource.url(), q);
 
521
        if (!abstractStream) {
370
522
            pDebug() << "backend MediaObject reached ErrorState, no KIO fallback available";
371
523
            emit q->stateChanged(newstate, oldstate);
372
524
            return;
390
542
            emit q->stateChanged(Phonon::LoadingState, oldstate);
391
543
            break;
392
544
        }
393
 
        kiofallback->d_func()->setMediaObjectPrivate(this);
394
 
        MediaSource mediaSource(kiofallback);
 
545
        abstractStream->d_func()->setMediaObjectPrivate(this);
 
546
        MediaSource mediaSource(abstractStream);
395
547
        mediaSource.setAutoDelete(true);
396
548
        pINTERFACE_CALL(setSource(mediaSource));
397
549
        if (oldstate == Phonon::BufferingState) {
399
551
        }
400
552
        return;
401
553
    } else if (ignoreLoadingToBufferingStateChange &&
402
 
            kiofallback &&
 
554
            abstractStream &&
403
555
            oldstate == Phonon::LoadingState) {
404
556
        if (newstate != Phonon::BufferingState) {
405
557
            emit q->stateChanged(newstate, Phonon::BufferingState);
406
558
        }
407
559
        return;
408
 
    } else if (ignoreErrorToLoadingStateChange && kiofallback && oldstate == ErrorState) {
 
560
    } else if (ignoreErrorToLoadingStateChange && abstractStream && oldstate == ErrorState) {
409
561
        if (newstate != LoadingState) {
410
562
            emit q->stateChanged(newstate, Phonon::LoadingState);
411
563
        }
414
566
 
415
567
    emit q->stateChanged(newstate, oldstate);
416
568
}
417
 
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
418
569
 
419
570
void MediaObjectPrivate::_k_aboutToFinish()
420
571
{
422
573
    pDebug() << Q_FUNC_INFO;
423
574
 
424
575
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
425
 
    kiofallback = 0; // kiofallback auto-deletes
 
576
    abstractStream = 0; // abstractStream auto-deletes
426
577
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
427
578
 
428
579
    if (sourceQueue.isEmpty()) {
433
584
    }
434
585
 
435
586
    mediaSource = sourceQueue.head();
 
587
    readyForZeitgeist = false;
436
588
    pINTERFACE_CALL(setNextSource(mediaSource));
437
589
}
438
590
 
516
668
 
517
669
    // set up attributes
518
670
    if (isPlayable(mediaSource.type())) {
 
671
        readyForZeitgeist = false;
519
672
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
520
673
        if (mediaSource.type() == MediaSource::Stream) {
521
674
            Q_ASSERT(mediaSource.stream());
546
699
{
547
700
    metaData = newMetaData;
548
701
    emit q_func()->metaDataChanged();
 
702
    pDebug() << "Metadata ready, sending to zeitgeist";
 
703
    readyForZeitgeist = true;
 
704
    sendToZeitgeist();
549
705
}
550
706
 
551
707
void MediaObjectPrivate::phononObjectDestroyed(MediaNodePrivate *bp)