src/3rdparty/phonon/mmf/abstractmediaplayer.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /*  This file is part of the KDE project.
       
     2 
       
     3 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 
       
     5 This library is free software: you can redistribute it and/or modify
       
     6 it under the terms of the GNU Lesser General Public License as published by
       
     7 the Free Software Foundation, either version 2.1 or 3 of the License.
       
     8 
       
     9 This library is distributed in the hope that it will be useful,
       
    10 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12 GNU Lesser General Public License for more details.
       
    13 
       
    14 You should have received a copy of the GNU Lesser General Public License
       
    15 along with this library.  If not, see <http://www.gnu.org/licenses/>.
       
    16 
       
    17 */
       
    18 
       
    19 #include <QUrl>
       
    20 
       
    21 #include "abstractmediaplayer.h"
       
    22 #include "defs.h"
       
    23 #include "utils.h"
       
    24 
       
    25 QT_BEGIN_NAMESPACE
       
    26 
       
    27 using namespace Phonon;
       
    28 using namespace Phonon::MMF;
       
    29 
       
    30 /*! \class MMF::AbstractMediaPlayer
       
    31   \internal
       
    32 */
       
    33 
       
    34 //-----------------------------------------------------------------------------
       
    35 // Constants
       
    36 //-----------------------------------------------------------------------------
       
    37 
       
    38 const int       NullMaxVolume = -1;
       
    39 
       
    40 
       
    41 //-----------------------------------------------------------------------------
       
    42 // Constructor / destructor
       
    43 //-----------------------------------------------------------------------------
       
    44 
       
    45 MMF::AbstractMediaPlayer::AbstractMediaPlayer() :
       
    46             m_playPending(false)
       
    47         ,   m_tickTimer(new QTimer(this))
       
    48         ,   m_mmfMaxVolume(NullMaxVolume)
       
    49 {
       
    50     connect(m_tickTimer.data(), SIGNAL(timeout()), this, SLOT(tick()));
       
    51 }
       
    52 
       
    53 MMF::AbstractMediaPlayer::AbstractMediaPlayer(const AbstractPlayer& player) :
       
    54         AbstractPlayer(player)
       
    55         ,   m_playPending(false)
       
    56         ,   m_tickTimer(new QTimer(this))
       
    57         ,   m_mmfMaxVolume(NullMaxVolume)
       
    58 {
       
    59     connect(m_tickTimer.data(), SIGNAL(timeout()), this, SLOT(tick()));
       
    60 }
       
    61 
       
    62 //-----------------------------------------------------------------------------
       
    63 // MediaObjectInterface
       
    64 //-----------------------------------------------------------------------------
       
    65 
       
    66 void MMF::AbstractMediaPlayer::play()
       
    67 {
       
    68     TRACE_CONTEXT(AbstractMediaPlayer::play, EAudioApi);
       
    69     TRACE_ENTRY("state %d", privateState());
       
    70 
       
    71     switch (privateState()) {
       
    72     case GroundState:
       
    73         setError(NormalError);
       
    74         break;
       
    75 
       
    76     case LoadingState:
       
    77         m_playPending = true;
       
    78         break;
       
    79 
       
    80     case StoppedState:
       
    81     case PausedState:
       
    82         doPlay();
       
    83         startTickTimer();
       
    84         changeState(PlayingState);
       
    85         break;
       
    86 
       
    87     case PlayingState:
       
    88     case BufferingState:
       
    89     case ErrorState:
       
    90         // Do nothing
       
    91         break;
       
    92 
       
    93         // Protection against adding new states and forgetting to update this switch
       
    94     default:
       
    95         TRACE_PANIC(InvalidStatePanic);
       
    96     }
       
    97 
       
    98     TRACE_EXIT("state %d", privateState());
       
    99 }
       
   100 
       
   101 void MMF::AbstractMediaPlayer::pause()
       
   102 {
       
   103     TRACE_CONTEXT(AbstractMediaPlayer::pause, EAudioApi);
       
   104     TRACE_ENTRY("state %d", privateState());
       
   105 
       
   106     m_playPending = false;
       
   107 
       
   108     switch (privateState()) {
       
   109     case GroundState:
       
   110     case LoadingState:
       
   111     case PausedState:
       
   112     case ErrorState:
       
   113         // Do nothing
       
   114         break;
       
   115 
       
   116     case StoppedState:
       
   117     case PlayingState:
       
   118     case BufferingState:
       
   119         doPause();
       
   120         stopTickTimer();
       
   121         changeState(PausedState);
       
   122         break;
       
   123 
       
   124         // Protection against adding new states and forgetting to update this switch
       
   125     default:
       
   126         TRACE_PANIC(InvalidStatePanic);
       
   127     }
       
   128 
       
   129     TRACE_EXIT("state %d", privateState());
       
   130 }
       
   131 
       
   132 void MMF::AbstractMediaPlayer::stop()
       
   133 {
       
   134     TRACE_CONTEXT(AbstractMediaPlayer::stop, EAudioApi);
       
   135     TRACE_ENTRY("state %d", privateState());
       
   136 
       
   137     m_playPending = false;
       
   138 
       
   139     switch (privateState()) {
       
   140     case GroundState:
       
   141     case LoadingState:
       
   142     case StoppedState:
       
   143     case ErrorState:
       
   144         // Do nothing
       
   145         break;
       
   146 
       
   147     case PlayingState:
       
   148     case BufferingState:
       
   149     case PausedState:
       
   150         doStop();
       
   151         stopTickTimer();
       
   152         changeState(StoppedState);
       
   153         break;
       
   154 
       
   155         // Protection against adding new states and forgetting to update this switch
       
   156     default:
       
   157         TRACE_PANIC(InvalidStatePanic);
       
   158     }
       
   159 
       
   160     TRACE_EXIT("state %d", privateState());
       
   161 }
       
   162 
       
   163 void MMF::AbstractMediaPlayer::seek(qint64 ms)
       
   164 {
       
   165     TRACE_CONTEXT(AbstractMediaPlayer::seek, EAudioApi);
       
   166     TRACE_ENTRY("state %d pos %Ld", state(), ms);
       
   167 
       
   168     switch (privateState()) {
       
   169     // Fallthrough all these
       
   170     case GroundState:
       
   171     case StoppedState:
       
   172     case PausedState:
       
   173     case PlayingState:
       
   174     case LoadingState:
       
   175     {
       
   176         const bool tickTimerWasRunning = m_tickTimer->isActive();
       
   177         stopTickTimer();
       
   178 
       
   179         doSeek(ms);
       
   180 
       
   181         if (tickTimerWasRunning) {
       
   182             startTickTimer();
       
   183         }
       
   184         break;
       
   185     }
       
   186     case BufferingState:
       
   187     // Fallthrough
       
   188     case ErrorState:
       
   189         // Do nothing
       
   190         break;
       
   191     }
       
   192 
       
   193     TRACE_EXIT_0();
       
   194 }
       
   195 
       
   196 bool MMF::AbstractMediaPlayer::isSeekable() const
       
   197 {
       
   198     return true;
       
   199 }
       
   200 
       
   201 void MMF::AbstractMediaPlayer::doSetTickInterval(qint32 interval)
       
   202 {
       
   203     TRACE_CONTEXT(AbstractMediaPlayer::doSetTickInterval, EAudioApi);
       
   204     TRACE_ENTRY("state %d m_interval %d interval %d", privateState(), tickInterval(), interval);
       
   205 
       
   206     m_tickTimer->setInterval(interval);
       
   207 
       
   208     TRACE_EXIT_0();
       
   209 }
       
   210 
       
   211 MediaSource MMF::AbstractMediaPlayer::source() const
       
   212 {
       
   213     return m_source;
       
   214 }
       
   215 
       
   216 void MMF::AbstractMediaPlayer::setFileSource(const MediaSource &source, RFile& file)
       
   217 {
       
   218     TRACE_CONTEXT(AbstractMediaPlayer::setFileSource, EAudioApi);
       
   219     TRACE_ENTRY("state %d source.type %d", privateState(), source.type());
       
   220 
       
   221     close();
       
   222     changeState(GroundState);
       
   223 
       
   224     // TODO: is it correct to assign even if the media type is not supported in
       
   225     // the switch statement below?
       
   226     m_source = source;
       
   227 
       
   228     TInt symbianErr = KErrNone;
       
   229 
       
   230     switch (m_source.type()) {
       
   231     case MediaSource::LocalFile: {
       
   232         symbianErr = openFile(file);
       
   233         break;
       
   234     }
       
   235 
       
   236     case MediaSource::Url: {
       
   237         const QUrl url(source.url());
       
   238 
       
   239         if (url.scheme() == QLatin1String("file")) {
       
   240             symbianErr = openFile(file);
       
   241         }
       
   242         else {
       
   243             TRACE_0("Source type not supported");
       
   244             // TODO: support network URLs
       
   245             symbianErr = KErrNotSupported;
       
   246         }
       
   247 
       
   248         break;
       
   249     }
       
   250 
       
   251     case MediaSource::Invalid:
       
   252     case MediaSource::Disc:
       
   253     case MediaSource::Stream:
       
   254         TRACE_0("Source type not supported");
       
   255         symbianErr = KErrNotSupported;
       
   256         break;
       
   257 
       
   258     case MediaSource::Empty:
       
   259         TRACE_0("Empty source - doing nothing");
       
   260         TRACE_EXIT_0();
       
   261         return;
       
   262 
       
   263         // Protection against adding new media types and forgetting to update this switch
       
   264     default:
       
   265         TRACE_PANIC(InvalidMediaTypePanic);
       
   266     }
       
   267 
       
   268     if (KErrNone == symbianErr) {
       
   269         changeState(LoadingState);
       
   270     } else {
       
   271         TRACE("error %d", symbianErr)
       
   272         setError(NormalError);
       
   273     }
       
   274 
       
   275     TRACE_EXIT_0();
       
   276 }
       
   277 
       
   278 void MMF::AbstractMediaPlayer::setNextSource(const MediaSource &source)
       
   279 {
       
   280     TRACE_CONTEXT(AbstractMediaPlayer::setNextSource, EAudioApi);
       
   281     TRACE_ENTRY("state %d", privateState());
       
   282 
       
   283     // TODO: handle 'next source'
       
   284 
       
   285     m_nextSource = source;
       
   286     Q_UNUSED(source);
       
   287 
       
   288     TRACE_EXIT_0();
       
   289 }
       
   290 
       
   291 
       
   292 //-----------------------------------------------------------------------------
       
   293 // VolumeObserver
       
   294 //-----------------------------------------------------------------------------
       
   295 
       
   296 void MMF::AbstractMediaPlayer::volumeChanged(qreal volume)
       
   297 {
       
   298     TRACE_CONTEXT(AbstractMediaPlayer::volumeChanged, EAudioInternal);
       
   299     TRACE_ENTRY("state %d", privateState());
       
   300 
       
   301     AbstractPlayer::volumeChanged(volume);
       
   302     doVolumeChanged();
       
   303 
       
   304     TRACE_EXIT_0();
       
   305 }
       
   306 
       
   307 
       
   308 void MMF::AbstractMediaPlayer::doVolumeChanged()
       
   309 {
       
   310     switch (privateState()) {
       
   311     case GroundState:
       
   312     case LoadingState:
       
   313     case ErrorState:
       
   314         // Do nothing
       
   315         break;
       
   316 
       
   317     case StoppedState:
       
   318     case PausedState:
       
   319     case PlayingState:
       
   320     case BufferingState: {
       
   321         const int err = setDeviceVolume(m_volume * m_mmfMaxVolume);
       
   322 
       
   323         if (KErrNone != err) {
       
   324             setError(NormalError);
       
   325         }
       
   326         break;
       
   327     }
       
   328 
       
   329     // Protection against adding new states and forgetting to update this
       
   330     // switch
       
   331     default:
       
   332         Utils::panic(InvalidStatePanic);
       
   333     }
       
   334 }
       
   335 
       
   336 
       
   337 //-----------------------------------------------------------------------------
       
   338 // Protected functions
       
   339 //-----------------------------------------------------------------------------
       
   340 
       
   341 void MMF::AbstractMediaPlayer::startTickTimer()
       
   342 {
       
   343     m_tickTimer->start(tickInterval());
       
   344 }
       
   345 
       
   346 void MMF::AbstractMediaPlayer::stopTickTimer()
       
   347 {
       
   348     m_tickTimer->stop();
       
   349 }
       
   350 
       
   351 void MMF::AbstractMediaPlayer::maxVolumeChanged(int mmfMaxVolume)
       
   352 {
       
   353     m_mmfMaxVolume = mmfMaxVolume;
       
   354     doVolumeChanged();
       
   355 }
       
   356 
       
   357 qint64 MMF::AbstractMediaPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds &in)
       
   358 {
       
   359     return in.Int64() / 1000;
       
   360 }
       
   361 
       
   362 void MMF::AbstractMediaPlayer::changeState(PrivateState newState)
       
   363 {
       
   364     TRACE_CONTEXT(AbstractPlayer::changeState, EAudioInternal);
       
   365     TRACE_ENTRY("state %d newState %d", privateState(), newState);
       
   366 
       
   367     // TODO: add some invariants to check that the transition is valid
       
   368 
       
   369     const Phonon::State oldPhononState = phononState(privateState());
       
   370     const Phonon::State newPhononState = phononState(newState);
       
   371     if (oldPhononState != newPhononState) {
       
   372         TRACE("emit stateChanged(%d, %d)", newPhononState, oldPhononState);
       
   373         emit stateChanged(newPhononState, oldPhononState);
       
   374     }
       
   375 
       
   376     setState(newState);
       
   377 
       
   378     if (
       
   379         LoadingState == oldPhononState
       
   380         and StoppedState == newPhononState
       
   381     ) {
       
   382         // Ensure initial volume is set on MMF API before starting playback
       
   383         doVolumeChanged();
       
   384 
       
   385         // Check whether play() was called while clip was being loaded.  If so,
       
   386         // playback should be started now
       
   387         if (m_playPending) {
       
   388             TRACE_0("play was called while loading; starting playback now");
       
   389             m_playPending = false;
       
   390             play();
       
   391         }
       
   392     }
       
   393 
       
   394     TRACE_EXIT_0();
       
   395 }
       
   396 
       
   397 //-----------------------------------------------------------------------------
       
   398 // Slots
       
   399 //-----------------------------------------------------------------------------
       
   400 
       
   401 void MMF::AbstractMediaPlayer::tick()
       
   402 {
       
   403     // For the MWC compiler, we need to qualify the base class.
       
   404     emit MMF::AbstractPlayer::tick(currentTime());
       
   405 }
       
   406 
       
   407 QT_END_NAMESPACE
       
   408