~ubuntu-branches/ubuntu/saucy/phonon-backend-gstreamer/saucy-proposed

« back to all changes in this revision

Viewing changes to gstreamer/mediaobject.cpp

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-02-04 14:30:52 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20130204143052-yfhzb2p4vm4xal2r
Tags: 4:4.7.0really4.6.3-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
    static int count = 0;
89
89
    m_name = "MediaObject" + QString::number(count++);
90
90
 
91
 
    if (!m_backend->isValid()) {
92
 
        setError(tr("Cannot start playback. \n\nCheck your GStreamer installation and make sure you "
93
 
                    "\nhave libgstreamer-plugins-base installed."), Phonon::FatalError);
94
 
    } else {
95
 
        m_root = this;
96
 
        m_pipeline = new Pipeline(this);
97
 
        m_isValid = true;
98
 
        GlobalSubtitles::instance()->register_(this);
99
 
 
100
 
        connect(m_pipeline, SIGNAL(aboutToFinish()),
101
 
                this, SLOT(handleAboutToFinish()), Qt::DirectConnection);
102
 
        connect(m_pipeline, SIGNAL(eos()),
103
 
                this, SLOT(handleEndOfStream()));
104
 
        connect(m_pipeline, SIGNAL(warning(QString)),
105
 
                this, SLOT(logWarning(QString)));
106
 
        connect(m_pipeline, SIGNAL(durationChanged(qint64)),
107
 
                this, SLOT(handleDurationChange(qint64)));
108
 
        connect(m_pipeline, SIGNAL(buffering(int)),
109
 
                this, SIGNAL(bufferStatus(int)));
110
 
        connect(m_pipeline, SIGNAL(stateChanged(GstState,GstState)),
111
 
                this, SLOT(handleStateChange(GstState,GstState)));
112
 
        connect(m_pipeline, SIGNAL(errorMessage(QString,Phonon::ErrorType)),
113
 
                this, SLOT(setError(QString,Phonon::ErrorType)));
114
 
        connect(m_pipeline, SIGNAL(metaDataChanged(QMultiMap<QString,QString>)),
115
 
                this, SIGNAL(metaDataChanged(QMultiMap<QString,QString>)));
116
 
        connect(m_pipeline, SIGNAL(availableMenusChanged(QList<MediaController::NavigationMenu>)),
117
 
                this, SIGNAL(availableMenusChanged(QList<MediaController::NavigationMenu>)));
118
 
        connect(m_pipeline, SIGNAL(videoAvailabilityChanged(bool)),
119
 
                this, SIGNAL(hasVideoChanged(bool)));
120
 
        connect(m_pipeline, SIGNAL(seekableChanged(bool)),
121
 
                this, SIGNAL(seekableChanged(bool)));
122
 
        connect(m_pipeline, SIGNAL(streamChanged()),
123
 
                this, SLOT(handleStreamChange()));
124
 
 
125
 
        connect(m_pipeline, SIGNAL(textTagChanged(int)),
126
 
                this, SLOT(getSubtitleInfo(int)));
127
 
        connect(m_pipeline, SIGNAL(trackCountChanged(int)),
128
 
                this, SLOT(handleTrackCountChange(int)));
129
 
 
130
 
        connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick()));
131
 
    }
 
91
    m_root = this;
 
92
    m_pipeline = new Pipeline(this);
 
93
    m_isValid = true;
 
94
    GlobalSubtitles::instance()->register_(this);
 
95
 
 
96
    connect(m_pipeline, SIGNAL(aboutToFinish()),
 
97
            this, SLOT(handleAboutToFinish()), Qt::DirectConnection);
 
98
    connect(m_pipeline, SIGNAL(eos()),
 
99
            this, SLOT(handleEndOfStream()));
 
100
    connect(m_pipeline, SIGNAL(warning(QString)),
 
101
            this, SLOT(logWarning(QString)));
 
102
    connect(m_pipeline, SIGNAL(durationChanged(qint64)),
 
103
            this, SLOT(handleDurationChange(qint64)));
 
104
    connect(m_pipeline, SIGNAL(buffering(int)),
 
105
            this, SIGNAL(bufferStatus(int)));
 
106
    connect(m_pipeline, SIGNAL(stateChanged(GstState,GstState)),
 
107
            this, SLOT(handleStateChange(GstState,GstState)));
 
108
    connect(m_pipeline, SIGNAL(errorMessage(QString,Phonon::ErrorType)),
 
109
            this, SLOT(setError(QString,Phonon::ErrorType)));
 
110
    connect(m_pipeline, SIGNAL(metaDataChanged(QMultiMap<QString,QString>)),
 
111
            this, SIGNAL(metaDataChanged(QMultiMap<QString,QString>)));
 
112
    connect(m_pipeline, SIGNAL(availableMenusChanged(QList<MediaController::NavigationMenu>)),
 
113
            this, SIGNAL(availableMenusChanged(QList<MediaController::NavigationMenu>)));
 
114
    connect(m_pipeline, SIGNAL(videoAvailabilityChanged(bool)),
 
115
            this, SIGNAL(hasVideoChanged(bool)));
 
116
    connect(m_pipeline, SIGNAL(seekableChanged(bool)),
 
117
            this, SIGNAL(seekableChanged(bool)));
 
118
    connect(m_pipeline, SIGNAL(streamChanged()),
 
119
            this, SLOT(handleStreamChange()));
 
120
 
 
121
    connect(m_pipeline, SIGNAL(textTagChanged(int)),
 
122
            this, SLOT(getSubtitleInfo(int)));
 
123
    connect(m_pipeline, SIGNAL(trackCountChanged(int)),
 
124
            this, SLOT(handleTrackCountChange(int)));
 
125
 
 
126
    connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick()));
132
127
}
133
128
 
134
129
MediaObject::~MediaObject()
378
373
 */
379
374
void MediaObject::setSource(const MediaSource &source)
380
375
{
381
 
    if (!isValid())
382
 
        return;
383
 
 
384
376
    DEBUG_BLOCK;
385
377
 
386
378
    if (source.type() == Phonon::MediaSource::Invalid) {
453
445
 
454
446
void MediaObject::seek(qint64 time)
455
447
{
456
 
    if (!isValid())
457
 
        return;
458
 
 
459
448
    DEBUG_BLOCK;
460
449
 
461
450
    if (m_waitingForNextSource) {
861
850
    m_aboutToFinishLock.lock();
862
851
    m_handlingAboutToFinish = true;
863
852
    emit aboutToFinish();
864
 
    // Three seconds should be more than enough for any application to get their act together.
865
 
    // Any longer than that and they have bigger issues.  If Phonon does no supply a next source
866
 
    // within 3 seconds, treat as if there is no next source to come, and finish the current source.
 
853
    // As our signal gets emitted queued we need to wait here until either a
 
854
    // new source or a timeout is reached.
 
855
    // If we got a new source in time -> hooray + gapless
 
856
    // If we did not get a new source in time -> boooh + stop()
867
857
    if (!m_skipGapless) {
868
 
      if (m_aboutToFinishWait.wait(&m_aboutToFinishLock, 3000)) {
869
 
          debug() << "Finally got a source";
870
 
          if (m_skipGapless) { // Was explicitly set by stateChange interrupt
871
 
              debug() << "...oh, no, just got aborted, skipping EOS";
872
 
              m_skippingEOS = false;
873
 
          }
874
 
      } else {
875
 
          warning() << "aboutToFinishWait timed out!";
876
 
          m_skippingEOS = false;
877
 
      }
 
858
        // Dynamic lock timeout is our friend.
 
859
        // Instead of simply waiting for a fixed amount of ms for the next source, we wait for the
 
860
        // most sensible amount of time. This is whatever amount of time is remaining to play
 
861
        // minus a 0.5 seconds safety delta (time values not precise etc.).
 
862
        // A source for which we have no time or for which the remaining time is < 0.5 seconds is
 
863
        // immediately unlocked again. Otherwise the consumer has as much time as gst gave us to
 
864
        // set a new source.
 
865
        // This in particular prevents pointless excessive locking on sources which have a totalTime
 
866
        // < whatever fixed lock value we have (so that we'd lock longer than what we are playing).
 
867
        // An issue apparent with notification-like sounds, that are rather short and do not need
 
868
        // gapless transitioning. As outlined in https://bugs.kde.org/show_bug.cgi?id=307530
 
869
        unsigned long timeout = 0;
 
870
        if (totalTime() <= 0 || (remainingTime() - 500 <= 0))
 
871
            timeout = 0;
 
872
        else
 
873
            timeout = remainingTime() - 500;
 
874
 
 
875
        debug() << "waiting for" << timeout;
 
876
        if (m_aboutToFinishWait.wait(&m_aboutToFinishLock, timeout)) {
 
877
            debug() << "Finally got a source";
 
878
            if (m_skipGapless) { // Was explicitly set by stateChange interrupt
 
879
                debug() << "...oh, no, just got aborted, skipping EOS";
 
880
                m_skippingEOS = false;
 
881
            }
 
882
        } else {
 
883
            warning() << "aboutToFinishWait timed out!";
 
884
            m_skippingEOS = false;
 
885
        }
878
886
    } else {
879
 
      debug() << "Skipping gapless audio";
880
 
      m_skippingEOS = false;
 
887
        debug() << "Skipping gapless audio";
 
888
        m_skippingEOS = false;
881
889
    }
882
890
    m_handlingAboutToFinish = false;
883
891
    m_aboutToFinishLock.unlock();