Changeset View
Changeset View
Standalone View
Standalone View
phonon/mediaobject.cpp
Show All 31 Lines | |||||
32 | #include "frontendinterface_p.h" | 32 | #include "frontendinterface_p.h" | ||
33 | 33 | | |||
34 | #include <QtCore/QStringBuilder> | 34 | #include <QtCore/QStringBuilder> | ||
35 | #include <QtCore/QStringList> | 35 | #include <QtCore/QStringList> | ||
36 | #include <QtCore/QDateTime> | 36 | #include <QtCore/QDateTime> | ||
37 | #include <QtCore/QTimer> | 37 | #include <QtCore/QTimer> | ||
38 | #include <QtCore/QUrl> | 38 | #include <QtCore/QUrl> | ||
39 | 39 | | |||
40 | #ifdef HAVE_QZEITGEIST | | |||
41 | #include <QZeitgeist/DataModel/Event> | | |||
42 | #include <QZeitgeist/Interpretation> | | |||
43 | #include <QZeitgeist/Log> | | |||
44 | #include <QZeitgeist/Manifestation> | | |||
45 | #include <QZeitgeist/QZeitgeist> | | |||
46 | #endif | | |||
47 | | ||||
48 | #include "phononnamespace_p.h" | 40 | #include "phononnamespace_p.h" | ||
49 | #include "platform_p.h" | 41 | #include "platform_p.h" | ||
50 | #include "statesvalidator_p.h" | 42 | #include "statesvalidator_p.h" | ||
51 | 43 | | |||
52 | #ifndef PHONON_NO_GRAPHICSVIEW | 44 | #ifndef PHONON_NO_GRAPHICSVIEW | ||
53 | #include <graphicsview/videographicsobject.h> | 45 | #include <graphicsview/videographicsobject.h> | ||
54 | #endif | 46 | #endif | ||
55 | 47 | | |||
▲ Show 20 Lines • Show All 217 Lines • ▼ Show 20 Line(s) | 263 | #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM | |||
273 | if (d->mediaSource.type() == MediaSource::Stream) { | 265 | if (d->mediaSource.type() == MediaSource::Stream) { | ||
274 | Q_ASSERT(d->mediaSource.stream()); | 266 | Q_ASSERT(d->mediaSource.stream()); | ||
275 | d->mediaSource.stream()->d_func()->setMediaObjectPrivate(d); | 267 | d->mediaSource.stream()->d_func()->setMediaObjectPrivate(d); | ||
276 | } | 268 | } | ||
277 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM | 269 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM | ||
278 | 270 | | |||
279 | d->playingQueuedSource = false; | 271 | d->playingQueuedSource = false; | ||
280 | 272 | | |||
281 | d->sendToZeitgeist(StoppedState); | | |||
282 | INTERFACE_CALL(setSource(d->mediaSource)); | 273 | INTERFACE_CALL(setSource(d->mediaSource)); | ||
283 | d->sendToZeitgeist(); | | |||
284 | } | 274 | } | ||
285 | 275 | | |||
286 | void MediaObject::clear() | 276 | void MediaObject::clear() | ||
287 | { | 277 | { | ||
288 | P_D(MediaObject); | 278 | P_D(MediaObject); | ||
289 | d->sourceQueue.clear(); | 279 | d->sourceQueue.clear(); | ||
290 | setCurrentSource(MediaSource()); | 280 | setCurrentSource(MediaSource()); | ||
291 | } | 281 | } | ||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | |||||
336 | } | 326 | } | ||
337 | 327 | | |||
338 | void MediaObject::clearQueue() | 328 | void MediaObject::clearQueue() | ||
339 | { | 329 | { | ||
340 | P_D(MediaObject); | 330 | P_D(MediaObject); | ||
341 | d->sourceQueue.clear(); | 331 | d->sourceQueue.clear(); | ||
342 | } | 332 | } | ||
343 | 333 | | |||
344 | void MediaObjectPrivate::sendToZeitgeist(const QString &event_interpretation, | | |||
345 | const QString &event_manifestation, | | |||
346 | const QString &event_actor, | | |||
347 | const QDateTime &subject_timestamp, | | |||
348 | const QUrl &subject_uri, | | |||
349 | const QString &subject_text, | | |||
350 | const QString &subject_interpretation, | | |||
351 | const QString &subject_manifestation, | | |||
352 | const QString &subject_mimetype) | | |||
353 | { | | |||
354 | #ifdef HAVE_QZEITGEIST | | |||
355 | QZeitgeist::DataModel::Subject subject; | | |||
356 | QString url = subject_uri.toString(); | | |||
357 | QString path = url.left(url.lastIndexOf(QLatin1Char('/'))); | | |||
358 | subject.setUri(url); | | |||
359 | subject.setText(subject_text); | | |||
360 | subject.setInterpretation(subject_interpretation); | | |||
361 | subject.setManifestation(subject_manifestation); | | |||
362 | subject.setOrigin(path); | | |||
363 | subject.setMimeType(subject_mimetype); | | |||
364 | | ||||
365 | QZeitgeist::DataModel::SubjectList subjects; | | |||
366 | subjects << subject; | | |||
367 | | ||||
368 | QZeitgeist::DataModel::Event event; | | |||
369 | event.setTimestamp(subject_timestamp); | | |||
370 | event.setInterpretation(event_interpretation); | | |||
371 | event.setManifestation(event_manifestation); | | |||
372 | event.setActor(event_actor); | | |||
373 | event.setSubjects(subjects); | | |||
374 | | ||||
375 | QZeitgeist::DataModel::EventList events; | | |||
376 | events << event; | | |||
377 | | ||||
378 | QDBusPendingReply<QZeitgeist::DataModel::EventIdList> reply = | | |||
379 | log->insertEvents(events); | | |||
380 | #else | | |||
381 | Q_UNUSED(event_interpretation) | | |||
382 | Q_UNUSED(event_manifestation) | | |||
383 | Q_UNUSED(event_actor) | | |||
384 | Q_UNUSED(subject_timestamp) | | |||
385 | Q_UNUSED(subject_uri) | | |||
386 | Q_UNUSED(subject_text) | | |||
387 | Q_UNUSED(subject_interpretation) | | |||
388 | Q_UNUSED(subject_manifestation) | | |||
389 | Q_UNUSED(subject_mimetype) | | |||
390 | #endif | | |||
391 | } | | |||
392 | | ||||
393 | void MediaObjectPrivate::sendToZeitgeist(State eventState) | | |||
394 | { | | |||
395 | #ifdef HAVE_QZEITGEIST | | |||
396 | P_Q(MediaObject); | | |||
397 | if (readyForZeitgeist && q->property("PlaybackTracking").toBool()) { | | |||
398 | pDebug() << "Current state:" << eventState; | | |||
399 | QString eventInterpretation; | | |||
400 | switch (eventState) { | | |||
401 | case PlayingState: | | |||
402 | eventInterpretation = QZeitgeist::Interpretation::Event::ZGAccessEvent; | | |||
403 | break; | | |||
404 | case ErrorState: | | |||
405 | case StoppedState: | | |||
406 | eventInterpretation = QZeitgeist::Interpretation::Event::ZGLeaveEvent; | | |||
407 | break; | | |||
408 | //These states are not signifigant events. | | |||
409 | case LoadingState: | | |||
410 | case BufferingState: | | |||
411 | case PausedState: | | |||
412 | return; | | |||
413 | break; | | |||
414 | } | | |||
415 | | ||||
416 | QStringList titles = q->metaData(TitleMetaData); | | |||
417 | QStringList artists = q->metaData(ArtistMetaData); | | |||
418 | QString title; | | |||
419 | if (titles.empty()) { | | |||
420 | QString file = mediaSource.url().toString(); | | |||
421 | title = file.right(file.length()-file.lastIndexOf("/")-1); | | |||
422 | } else { | | |||
423 | if (artists.empty()) { | | |||
424 | title = titles[0]; | | |||
425 | } else { | | |||
426 | title = QString(QObject::tr("%0 by %1")).arg(titles[0]).arg(artists[0]); | | |||
427 | } | | |||
428 | } | | |||
429 | pDebug() << "Sending" << title << "to zeitgeist"; | | |||
430 | | ||||
431 | QString mime; | | |||
432 | QString subjectInterpretation; | | |||
433 | if (q->hasVideo()) { | | |||
434 | subjectInterpretation = QZeitgeist::Interpretation::Subject::NFOVideo; | | |||
435 | mime = "video/raw"; | | |||
436 | } else { | | |||
437 | subjectInterpretation = QZeitgeist::Interpretation::Subject::NFOAudio; | | |||
438 | mime = "audio/raw"; | | |||
439 | } | | |||
440 | pDebug() << "Zeitgeist mime type:" << mime; | | |||
441 | pDebug() << "Zeitgeist URL:" << mediaSource.url(); | | |||
442 | pDebug() << "mediasource type:" << mediaSource.type(); | | |||
443 | | ||||
444 | QString subjectType; | | |||
445 | switch (mediaSource.type()) { | | |||
446 | case MediaSource::Empty: | | |||
447 | case MediaSource::Invalid: | | |||
448 | return; | | |||
449 | case MediaSource::Url: | | |||
450 | subjectType = QZeitgeist::Manifestation::Subject::NFORemoteDataObject; | | |||
451 | break; | | |||
452 | case MediaSource::CaptureDevice: | | |||
453 | case MediaSource::Disc: | | |||
454 | case MediaSource::Stream: | | |||
455 | subjectType = QZeitgeist::Manifestation::Subject::NFOMediaStream; | | |||
456 | break; | | |||
457 | case MediaSource::LocalFile: | | |||
458 | subjectType = QZeitgeist::Manifestation::Subject::NFOFileDataObject; | | |||
459 | break; | | |||
460 | } | | |||
461 | | ||||
462 | QString eventManifestation; | | |||
463 | if (playingQueuedSource) | | |||
464 | eventManifestation = QZeitgeist::Manifestation::Event::ZGScheduledActivity; | | |||
465 | else | | |||
466 | eventManifestation = QZeitgeist::Manifestation::Event::ZGUserActivity; | | |||
467 | | ||||
468 | sendToZeitgeist(eventInterpretation, | | |||
469 | eventManifestation, | | |||
470 | QLatin1Literal("application://" ) % Platform::applicationName() % QLatin1Literal(".desktop"), | | |||
471 | QDateTime::currentDateTime(), | | |||
472 | mediaSource.url(), | | |||
473 | title, | | |||
474 | subjectInterpretation, | | |||
475 | subjectType, | | |||
476 | mime); | | |||
477 | } | | |||
478 | // Unset this so we don't send it again after a pause+play | | |||
479 | readyForZeitgeist = false; | | |||
480 | playingQueuedSource = false; | | |||
481 | #else | | |||
482 | Q_UNUSED(eventState) | | |||
483 | #endif | | |||
484 | } | | |||
485 | | ||||
486 | void MediaObjectPrivate::sendToZeitgeist() | | |||
487 | { | | |||
488 | P_Q(MediaObject); | | |||
489 | sendToZeitgeist(q->state()); | | |||
490 | } | | |||
491 | | ||||
492 | bool MediaObjectPrivate::aboutToDeleteBackendObject() | 334 | bool MediaObjectPrivate::aboutToDeleteBackendObject() | ||
493 | { | 335 | { | ||
494 | //pDebug() << Q_FUNC_INFO; | 336 | //pDebug() << Q_FUNC_INFO; | ||
495 | prefinishMark = pINTERFACE_CALL(prefinishMark()); | 337 | prefinishMark = pINTERFACE_CALL(prefinishMark()); | ||
496 | transitionTime = pINTERFACE_CALL(transitionTime()); | 338 | transitionTime = pINTERFACE_CALL(transitionTime()); | ||
497 | //pDebug() << Q_FUNC_INFO; | 339 | //pDebug() << Q_FUNC_INFO; | ||
498 | if (m_backendObject) { | 340 | if (m_backendObject) { | ||
499 | state = pINTERFACE_CALL(state()); | 341 | state = pINTERFACE_CALL(state()); | ||
Show All 17 Lines | |||||
517 | } | 359 | } | ||
518 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM | 360 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM | ||
519 | 361 | | |||
520 | // TODO: this needs serious cleanup... | 362 | // TODO: this needs serious cleanup... | ||
521 | void MediaObjectPrivate::_k_stateChanged(Phonon::State newstate, Phonon::State oldstate) | 363 | void MediaObjectPrivate::_k_stateChanged(Phonon::State newstate, Phonon::State oldstate) | ||
522 | { | 364 | { | ||
523 | P_Q(MediaObject); | 365 | P_Q(MediaObject); | ||
524 | 366 | | |||
525 | // Zeitgeist --------------------------------------------------------------- | | |||
526 | if (newstate == StoppedState) { | | |||
527 | readyForZeitgeist = true; | | |||
528 | } | | |||
529 | pDebug() << "State changed from" << oldstate << "to" << newstate << "-> sending to zeitgeist."; | | |||
530 | sendToZeitgeist(newstate); | | |||
531 | | ||||
532 | // AbstractMediaStream fallback stuff -------------------------------------- | 367 | // AbstractMediaStream fallback stuff -------------------------------------- | ||
533 | if (errorOverride) { | 368 | if (errorOverride) { | ||
534 | errorOverride = false; | 369 | errorOverride = false; | ||
535 | if (newstate == ErrorState) { | 370 | if (newstate == ErrorState) { | ||
536 | return; | 371 | return; | ||
537 | } | 372 | } | ||
538 | oldstate = ErrorState; | 373 | oldstate = ErrorState; | ||
539 | } | 374 | } | ||
Show All 29 Lines | 403 | default: | |||
569 | pError() << "backend MediaObject reached ErrorState after " << oldstate | 404 | pError() << "backend MediaObject reached ErrorState after " << oldstate | ||
570 | << ". It seems a KioMediaStream will not help here, trying anyway."; | 405 | << ". It seems a KioMediaStream will not help here, trying anyway."; | ||
571 | emit q->stateChanged(Phonon::LoadingState, oldstate); | 406 | emit q->stateChanged(Phonon::LoadingState, oldstate); | ||
572 | break; | 407 | break; | ||
573 | } | 408 | } | ||
574 | abstractStream->d_func()->setMediaObjectPrivate(this); | 409 | abstractStream->d_func()->setMediaObjectPrivate(this); | ||
575 | MediaSource mediaSource(abstractStream); | 410 | MediaSource mediaSource(abstractStream); | ||
576 | mediaSource.setAutoDelete(true); | 411 | mediaSource.setAutoDelete(true); | ||
577 | sendToZeitgeist(StoppedState); | | |||
578 | pINTERFACE_CALL(setSource(mediaSource)); | 412 | pINTERFACE_CALL(setSource(mediaSource)); | ||
579 | sendToZeitgeist(); | | |||
580 | if (oldstate == Phonon::BufferingState) { | 413 | if (oldstate == Phonon::BufferingState) { | ||
581 | q->play(); | 414 | q->play(); | ||
582 | } | 415 | } | ||
583 | return; | 416 | return; | ||
584 | } else if (ignoreLoadingToBufferingStateChange && | 417 | } else if (ignoreLoadingToBufferingStateChange && | ||
585 | abstractStream && | 418 | abstractStream && | ||
586 | oldstate == Phonon::LoadingState) { | 419 | oldstate == Phonon::LoadingState) { | ||
587 | if (newstate != Phonon::BufferingState) { | 420 | if (newstate != Phonon::BufferingState) { | ||
Show All 22 Lines | 441 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM | |||
610 | if (sourceQueue.isEmpty()) { | 443 | if (sourceQueue.isEmpty()) { | ||
611 | emit q->aboutToFinish(); | 444 | emit q->aboutToFinish(); | ||
612 | if (sourceQueue.isEmpty()) { | 445 | if (sourceQueue.isEmpty()) { | ||
613 | return; | 446 | return; | ||
614 | } | 447 | } | ||
615 | } | 448 | } | ||
616 | 449 | | |||
617 | mediaSource = sourceQueue.head(); | 450 | mediaSource = sourceQueue.head(); | ||
618 | readyForZeitgeist = false; | | |||
619 | playingQueuedSource = true; | 451 | playingQueuedSource = true; | ||
620 | pINTERFACE_CALL(setNextSource(mediaSource)); | 452 | pINTERFACE_CALL(setNextSource(mediaSource)); | ||
621 | 453 | | |||
622 | if (validator) | 454 | if (validator) | ||
623 | validator->sourceQueued(); | 455 | validator->sourceQueued(); | ||
624 | } | 456 | } | ||
625 | 457 | | |||
626 | void MediaObjectPrivate::_k_currentSourceChanged(const MediaSource &source) | 458 | void MediaObjectPrivate::_k_currentSourceChanged(const MediaSource &source) | ||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Line(s) | |||||
714 | #ifndef QT_NO_PHONON_MEDIACONTROLLER | 546 | #ifndef QT_NO_PHONON_MEDIACONTROLLER | ||
715 | for (int i = 0 ; i < interfaceList.count(); ++i) { | 547 | for (int i = 0 ; i < interfaceList.count(); ++i) { | ||
716 | interfaceList.at(i)->_backendObjectChanged(); | 548 | interfaceList.at(i)->_backendObjectChanged(); | ||
717 | } | 549 | } | ||
718 | #endif //QT_NO_PHONON_MEDIACONTROLLER | 550 | #endif //QT_NO_PHONON_MEDIACONTROLLER | ||
719 | 551 | | |||
720 | // set up attributes | 552 | // set up attributes | ||
721 | if (isPlayable(mediaSource.type())) { | 553 | if (isPlayable(mediaSource.type())) { | ||
722 | readyForZeitgeist = false; | | |||
723 | #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM | 554 | #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM | ||
724 | if (mediaSource.type() == MediaSource::Stream) { | 555 | if (mediaSource.type() == MediaSource::Stream) { | ||
725 | Q_ASSERT(mediaSource.stream()); | 556 | Q_ASSERT(mediaSource.stream()); | ||
726 | mediaSource.stream()->d_func()->setMediaObjectPrivate(this); | 557 | mediaSource.stream()->d_func()->setMediaObjectPrivate(this); | ||
727 | } | 558 | } | ||
728 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM | 559 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM | ||
729 | sendToZeitgeist(StoppedState); | | |||
730 | pINTERFACE_CALL(setSource(mediaSource)); | 560 | pINTERFACE_CALL(setSource(mediaSource)); | ||
731 | sendToZeitgeist(); | | |||
732 | } | 561 | } | ||
733 | } | 562 | } | ||
734 | 563 | | |||
735 | void MediaObjectPrivate::_k_resumePlay() | 564 | void MediaObjectPrivate::_k_resumePlay() | ||
736 | { | 565 | { | ||
737 | qobject_cast<MediaObjectInterface *>(m_backendObject)->play(); | 566 | qobject_cast<MediaObjectInterface *>(m_backendObject)->play(); | ||
738 | if (currentTime > 0) { | 567 | if (currentTime > 0) { | ||
739 | qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime); | 568 | qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime); | ||
740 | } | 569 | } | ||
741 | } | 570 | } | ||
742 | 571 | | |||
743 | void MediaObjectPrivate::_k_resumePause() | 572 | void MediaObjectPrivate::_k_resumePause() | ||
744 | { | 573 | { | ||
745 | pINTERFACE_CALL(pause()); | 574 | pINTERFACE_CALL(pause()); | ||
746 | if (currentTime > 0) { | 575 | if (currentTime > 0) { | ||
747 | qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime); | 576 | qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime); | ||
748 | } | 577 | } | ||
749 | } | 578 | } | ||
750 | 579 | | |||
751 | void MediaObjectPrivate::_k_metaDataChanged(const QMultiMap<QString, QString> &newMetaData) | 580 | void MediaObjectPrivate::_k_metaDataChanged(const QMultiMap<QString, QString> &newMetaData) | ||
752 | { | 581 | { | ||
753 | metaData = newMetaData; | 582 | metaData = newMetaData; | ||
754 | emit q_func()->metaDataChanged(); | 583 | emit q_func()->metaDataChanged(); | ||
755 | pDebug() << "Metadata ready, sending to zeitgeist"; | | |||
756 | readyForZeitgeist = true; | | |||
757 | sendToZeitgeist(); | | |||
758 | } | 584 | } | ||
759 | 585 | | |||
760 | void MediaObjectPrivate::phononObjectDestroyed(MediaNodePrivate *bp) | 586 | void MediaObjectPrivate::phononObjectDestroyed(MediaNodePrivate *bp) | ||
761 | { | 587 | { | ||
762 | // this method is called from Phonon::Base::~Base(), meaning the AudioPath | 588 | // this method is called from Phonon::Base::~Base(), meaning the AudioPath | ||
763 | // dtor has already been called, also virtual functions don't work anymore | 589 | // dtor has already been called, also virtual functions don't work anymore | ||
764 | // (therefore qobject_cast can only downcast from Base) | 590 | // (therefore qobject_cast can only downcast from Base) | ||
765 | Q_ASSERT(bp); | 591 | Q_ASSERT(bp); | ||
Show All 21 Lines |