File indexing completed on 2024-04-14 04:38:25

0001 /*  This file is part of the KDE project
0002     Copyright (C) 2005 Matthias Kretz <kretz@kde.org>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Lesser General Public
0006     License as published by the Free Software Foundation; either
0007     version 2.1 of the License, or (at your option) version 3, or any
0008     later version accepted by the membership of KDE e.V. (or its
0009     successor approved by the membership of KDE e.V.), Nokia Corporation
0010     (or its successors, if any) and the KDE Free Qt Foundation, which shall
0011     act as a proxy defined in Section 6 of version 3 of the license.
0012 
0013     This library is distributed in the hope that it will be useful,
0014     but WITHOUT ANY WARRANTY; without even the implied warranty of
0015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016     Lesser General Public License for more details.
0017 
0018     You should have received a copy of the GNU Lesser General Public
0019     License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0020 
0021 */
0022 #ifndef Phonon_MEDIAOBJECT_H
0023 #define Phonon_MEDIAOBJECT_H
0024 
0025 #include "medianode.h"
0026 #include "mediasource.h"
0027 #include "phonon_export.h"
0028 #include "phonondefs.h"
0029 #include "phononnamespace.h"
0030 
0031 
0032 namespace Phonon
0033 {
0034     class MediaObjectPrivate;
0035 
0036     /** \class MediaObject mediaobject.h phonon/MediaObject
0037      * \short Interface for media playback of a given URL.
0038      *
0039      * This class is the most important class in %Phonon. Use it to open a media
0040      * file at an arbitrary location, a CD or DVD or to stream media data from
0041      * the application to the backend.
0042      *
0043      * This class controls the state (play, pause, stop, seek)
0044      * and you can use it to get a lot of information about the media data.
0045      *
0046      * Notice that most functions of this class are asynchronous.
0047      * That means if you call play() the object only starts playing when the
0048      * stateChanged() signal tells you that the object changed into PlayingState.
0049      * The states you can expect are documented for those methods.
0050      *
0051      * A common usage example is the following:
0052      * \code
0053      * media = new MediaObject(this);
0054      * connect(media, SIGNAL(finished()), SLOT(slotFinished());
0055      * media->setCurrentSource("/home/username/music/filename.ogg");
0056      * media->play();
0057      * \endcode
0058      *
0059      * If you want to play more than one media file (one after another) you can
0060      * either tell MediaObject about all those files
0061      * \code
0062      * media->setCurrentSource(":/sounds/startsound.ogg");
0063      * media->enqueue("/home/username/music/song.mp3");
0064      * media->enqueue(":/sounds/endsound.ogg");
0065      * \endcode
0066      * or provide the next file just in time:
0067      * \code
0068      *   media->setCurrentSource(":/sounds/startsound.ogg");
0069      *   connect(media, SIGNAL(aboutToFinish()), SLOT(enqueueNextSource()));
0070      * }
0071      *
0072      * void enqueueNextSource()
0073      * {
0074      *   media->enqueue("/home/username/music/song.mp3");
0075      * }
0076      * \endcode
0077      *
0078      * This integration is opt-in only and can be enabled by setting the
0079      * PlaybackTracking property to true:
0080      * \code
0081      * media->setProperty("PlaybackTracking", true);
0082      * \endcode
0083      *
0084      * This kind of information is normally used to provide a universal history
0085      * view to the user, such as what songs were played when, regardless of the
0086      * media player. This is in addition to any emails read, IM conversations,
0087      * websites viewed, etc.
0088      *
0089      * \ingroup Playback
0090      * \ingroup Recording
0091      * \author Matthias Kretz <kretz@kde.org>
0092      */
0093     class PHONON_EXPORT MediaObject : public QObject, public MediaNode
0094     {
0095         friend class FrontendInterfacePrivate;
0096         Q_OBJECT
0097         P_DECLARE_PRIVATE(MediaObject)
0098         PHONON_OBJECT(MediaObject)
0099         /**
0100          * \brief Defines the time between media sources.
0101          *
0102          * A positive transition time defines a gap of silence between queued
0103          * media sources.
0104          *
0105          * A transition time of 0 ms requests gapless playback (sample precise
0106          * queueing of the next source).
0107          *
0108          * A negative transition time defines a crossfade between the queued
0109          * media sources.
0110          *
0111          * Defaults to 0 (gapless playback).
0112          *
0113          * \warning This feature might not work reliably on every platform.
0114          */
0115         Q_PROPERTY(qint32 transitionTime READ transitionTime WRITE setTransitionTime)
0116 
0117         /**
0118          * \brief Get a signal before playback finishes.
0119          *
0120          * This property specifies the time in milliseconds the
0121          * prefinishMarkReached signal is
0122          * emitted before the playback finishes. A value of \c 0 disables the
0123          * signal.
0124          *
0125          * Defaults to \c 0 (disabled).
0126          *
0127          * \warning For some media data the total time cannot be determined
0128          * accurately, therefore the accuracy of the prefinishMarkReached signal
0129          * can be bad sometimes. Still, it is better to use this method than to
0130          * look at totalTime() and currentTime() to emulate the behaviour
0131          * because the backend might have more information available than your
0132          * application does through totalTime and currentTime.
0133          *
0134          * \see prefinishMarkReached
0135          */
0136         Q_PROPERTY(qint32 prefinishMark READ prefinishMark WRITE setPrefinishMark)
0137 
0138         /**
0139          * \brief The time interval in milliseconds between two ticks.
0140          *
0141          * The %tick interval is the time that elapses between the emission of two tick signals.
0142          * If you set the interval to \c 0 the tick signal gets disabled.
0143          *
0144          * Defaults to \c 0 (disabled).
0145          *
0146          * \warning The back-end is free to choose a different tick interval close
0147          * to what you asked for. This means that the following code \em may \em fail:
0148          * \code
0149          * int x = 200;
0150          * media->setTickInterval(x);
0151          * Q_ASSERT(x == producer->tickInterval());
0152          * \endcode
0153          * On the other hand the following is guaranteed:
0154          * \code
0155          * int x = 200;
0156          * media->setTickInterval(x);
0157          * Q_ASSERT(x >= producer->tickInterval() &&
0158          *          x <= 2 * producer->tickInterval());
0159          * \endcode
0160          *
0161          * \see tick
0162          */
0163         Q_PROPERTY(qint32 tickInterval READ tickInterval WRITE setTickInterval)
0164         public:
0165             /**
0166              * Destroys the MediaObject.
0167              */
0168             ~MediaObject() override;
0169 
0170             /**
0171              * Get the current state.
0172              *
0173              * @return The state of the object.
0174              *
0175              * @see State
0176              * \see stateChanged
0177              */
0178             State state() const;
0179 
0180             /**
0181              * Check whether the media data includes a video stream.
0182              *
0183              * \warning This information cannot be known immediately. It is best
0184              * to also listen to the hasVideoChanged signal.
0185              *
0186              * \code
0187              *   connect(media, SIGNAL(hasVideoChanged(bool)), hasVideoChanged(bool));
0188              *   media->setCurrentSource("somevideo.avi");
0189              *   media->hasVideo(); // returns false;
0190              * }
0191              *
0192              * void hasVideoChanged(bool b)
0193              * {
0194              *   // b == true
0195              *   media->hasVideo(); // returns true;
0196              * }
0197              * \endcode
0198              *
0199              * \return \c true if the media contains video data. \c false
0200              * otherwise.
0201              *
0202              * \see hasVideoChanged
0203              */
0204             bool hasVideo() const;
0205 
0206             /**
0207              * Check whether the current media may be seeked.
0208              *
0209              * \warning This information cannot be known immediately. It is best
0210              * to also listen to the seekableChanged signal.
0211              *
0212              * \code
0213              *   connect(media, SIGNAL(seekableChanged(bool)), seekableChanged(bool));
0214              *   media->setCurrentSource("somevideo.avi");
0215              *   media->isSeekable(); // returns false;
0216              * }
0217              *
0218              * void seekableChanged(bool b)
0219              * {
0220              *   // b == true
0221              *   media->isSeekable(); // returns true;
0222              * }
0223              * \endcode
0224              *
0225              * \return \c true when the current media may be seeked. \c false
0226              * otherwise.
0227              *
0228              * \see seekableChanged()
0229              */
0230             bool isSeekable() const;
0231 
0232             /**
0233              * \brief The time interval in milliseconds between two ticks.
0234              *
0235              * The %tick interval is the time that elapses between the emission
0236              * of two tick signals.
0237              *
0238              * \returns the tick interval in milliseconds
0239              */
0240             qint32 tickInterval() const;
0241 
0242             /**
0243              * Returns the strings associated with the given \p key.
0244              *
0245              * Backends should use the keys specified in the Ogg Vorbis
0246              * documentation: http://xiph.org/vorbis/doc/v-comment.html
0247              *
0248              * Therefore the following should work with every backend:
0249              *
0250              * A typical usage looks like this:
0251              * \code
0252              * setMetaArtist (media->metaData("ARTIST"     ));
0253              * setMetaAlbum  (media->metaData("ALBUM"      ));
0254              * setMetaTitle  (media->metaData("TITLE"      ));
0255              * setMetaDate   (media->metaData("DATE"       ));
0256              * setMetaGenre  (media->metaData("GENRE"      ));
0257              * setMetaTrack  (media->metaData("TRACKNUMBER"));
0258              * setMetaComment(media->metaData("DESCRIPTION"));
0259              * \endcode
0260              *
0261              * For Audio CDs you can query
0262              * \code
0263              * metaData("MUSICBRAINZ_DISCID");
0264              * \endcode
0265              * to get a DiscID hash that you can use with the MusicBrainz
0266              * service:
0267              * http://musicbrainz.org/doc/ClientHOWTO
0268              */
0269             QStringList metaData(const QString &key) const;
0270 
0271             /**
0272              * Returns the strings associated with the given \p key.
0273              *
0274              * Same as above except that the keys are defined in the
0275              * Phonon::MetaData enum.
0276              */
0277             QStringList metaData(Phonon::MetaData key) const;
0278 
0279             /**
0280              * Returns all meta data.
0281              */
0282             QMultiMap<QString, QString> metaData() const;
0283 
0284             /**
0285              * Returns a human-readable description of the last error that occurred.
0286              */
0287             QString errorString() const;
0288 
0289             /**
0290              * Tells your program what to do about the error.
0291              *
0292              * \see Phonon::ErrorType
0293              */
0294             ErrorType errorType() const;
0295 
0296             /**
0297              * Returns the current media source.
0298              *
0299              * \see setCurrentSource
0300              */
0301             MediaSource currentSource() const;
0302 
0303             /**
0304              * Set the media source the MediaObject should use.
0305              *
0306              * \param source The MediaSource object to the media data. You can
0307              * just as well use a QUrl or QString (for a local file) here.
0308              * Setting an empty (invalid) source, will stop and remove the
0309              * current source.
0310              *
0311              * \code
0312              * QUrl url("http://www.example.com/music.ogg");
0313              * media->setCurrentSource(url);
0314              * \endcode
0315              *
0316              * \see currentSource
0317              */
0318             void setCurrentSource(const MediaSource &source);
0319 
0320             /**
0321              * Returns the queued media sources. This list does not include
0322              * the current source (returned by currentSource).
0323              */
0324             QList<MediaSource> queue() const;
0325 
0326             /**
0327              * Set the MediaSources to play when the current media has finished.
0328              *
0329              * This function will overwrite the current queue.
0330              *
0331              * \see clearQueue
0332              * \see enqueue
0333              */
0334             void setQueue(const QList<MediaSource> &sources);
0335 
0336             /**
0337              * Set the MediaSources to play when the current media has finished.
0338              *
0339              * This function overwrites the current queue.
0340              *
0341              * \see clearQueue
0342              * \see enqueue
0343              */
0344             void setQueue(const QList<QUrl> &urls);
0345 
0346             /**
0347              * Appends one source to the queue. Use this function to provide
0348              * the next source just in time after the aboutToFinish signal was
0349              * emitted.
0350              *
0351              * \see aboutToFinish
0352              * \see setQueue
0353              * \see clearQueue
0354              */
0355             void enqueue(const MediaSource &source);
0356 
0357             /**
0358              * Appends multiple sources to the queue.
0359              *
0360              * \see setQueue
0361              * \see clearQueue
0362              */
0363             void enqueue(const QList<MediaSource> &sources);
0364 
0365             /**
0366              * Appends multiple sources to the queue.
0367              *
0368              * \see setQueue
0369              * \see clearQueue
0370              */
0371             void enqueue(const QList<QUrl> &urls);
0372 
0373             /**
0374              * Clears the queue of sources.
0375              */
0376             void clearQueue();
0377 
0378             /**
0379              * Get the current time (in milliseconds) of the file currently being played.
0380              *
0381              * \return The current time in milliseconds.
0382              *
0383              * \see tick
0384              */
0385             qint64 currentTime() const;
0386 
0387             /**
0388              * Get the total time (in milliseconds) of the file currently being played.
0389              *
0390              * \return The total time in milliseconds.
0391              *
0392              * \note The total time may change throughout playback as more accurate
0393              *       calculations become available, so it is recommended to connect
0394              *       and use the totalTimeChanged signal whenever possible unless
0395              *       best precision is not of importance.
0396              *
0397              * \warning The total time is undefined until the MediaObject entered
0398              *          the PlayingState. A valid total time is always indicated by
0399              *          emission of the totalTimeChanged signal.
0400              * \see totalTimeChanged
0401              */
0402             qint64 totalTime() const;
0403 
0404             /**
0405              * Get the remaining time (in milliseconds) of the file currently being played.
0406              *
0407              * \return The remaining time in milliseconds.
0408              */
0409             qint64 remainingTime() const;
0410 
0411             qint32 prefinishMark() const;
0412             void setPrefinishMark(qint32 msecToEnd);
0413 
0414             qint32 transitionTime() const;
0415             void setTransitionTime(qint32 msec);
0416 
0417         public Q_SLOTS:
0418 
0419             /**
0420              * Sets the tick interval in milliseconds.
0421              *
0422              * \param newTickInterval the new tick interval in milliseconds.
0423              *
0424              * \see tickInterval
0425              */
0426             void setTickInterval(qint32 newTickInterval);
0427 
0428             /**
0429              * Requests playback of the media data to start. Playback only
0430              * starts when stateChanged() signals that it goes into PlayingState,
0431              * though.
0432              *
0433              * \par Possible states right after this call:
0434              * \li BufferingState
0435              * \li PlayingState
0436              * \li ErrorState
0437              */
0438             void play();
0439 
0440             /**
0441              * Requests playback to pause. If it was paused before nothing changes.
0442              * If the media cannot be paused, some backends will internally call
0443              * stop instead of pause.
0444              *
0445              * \par Possible states right after this call:
0446              * \li PlayingState
0447              * \li PausedState
0448              * \li StoppedState
0449              * \li ErrorState
0450              */
0451             void pause();
0452 
0453             /**
0454              * Requests playback to stop. If it was stopped before nothing changes.
0455              *
0456              * \par Possible states right after this call:
0457              * \li the state it was in before (e.g. PlayingState)
0458              * \li StoppedState
0459              * \li ErrorState
0460              */
0461             void stop();
0462 
0463             /**
0464              * Requests a seek to the time indicated.
0465              *
0466              * You can only seek if state() == PlayingState, BufferingState or PausedState.
0467              *
0468              * The call is asynchronous, so currentTime can still be the old
0469              * value right after this method was called. If all you need is a
0470              * slider that shows the current position and allows the user to
0471              * seek use the class SeekSlider.
0472              *
0473              * @param time The time in milliseconds where to continue playing.
0474              *
0475              * \par Possible states right after this call:
0476              * \li BufferingState
0477              * \li PlayingState
0478              * \li ErrorState
0479              *
0480              * \see SeekSlider
0481              */
0482             void seek(qint64 time);
0483 
0484             /**
0485              * Stops and removes all playing and enqueued media sources.
0486              *
0487              * \see setCurrentSource
0488              */
0489             void clear();
0490 
0491         Q_SIGNALS:
0492             /**
0493              * Emitted when the state of the MediaObject has changed.
0494              *
0495              * @param newstate The state the Player is in now.
0496              * @param oldstate The state the Player was in before.
0497              */
0498             void stateChanged(Phonon::State newstate, Phonon::State oldstate);
0499 
0500             /**
0501              * This signal gets emitted every tickInterval milliseconds.
0502              *
0503              * @param time The position of the media file in milliseconds.
0504              *
0505              * @see setTickInterval, tickInterval
0506              */
0507             void tick(qint64 time);
0508 
0509             /**
0510              * This signal is emitted whenever the audio/video data that is
0511              * being played is associated with new meta data. E.g. for radio
0512              * streams this happens when the next song is played.
0513              *
0514              * You can get the new meta data with the metaData methods.
0515              */
0516             void metaDataChanged();
0517 
0518             /**
0519              * Emitted whenever the return value of isSeekable() changes.
0520              *
0521              * Normally you'll check isSeekable() first and then let this signal
0522              * tell you whether seeking is possible now or not. That way you
0523              * don't have to poll isSeekable().
0524              *
0525              * \param isSeekable \p true  if the stream is seekable (i.e. calling
0526              *                            seek() works)
0527              *                   \p false if the stream is not seekable (i.e.
0528              *                            all calls to seek() will be ignored)
0529              */
0530             void seekableChanged(bool isSeekable);
0531 
0532             /**
0533              * Emitted whenever the return value of hasVideo() changes.
0534              *
0535              * Normally you'll check hasVideo() first and then let this signal
0536              * tell you whether video is available now or not. That way you
0537              * don't have to poll hasVideo().
0538              *
0539              * \param hasVideo \p true  The stream contains video and adding a
0540              *                          VideoWidget will show a video.
0541              *                 \p false There is no video data in the stream and
0542              *                          adding a VideoWidget will show an empty (black)
0543              *                          VideoWidget.
0544              */
0545 #ifndef QT_NO_PHONON_VIDEO
0546             void hasVideoChanged(bool hasVideo);
0547 #endif //QT_NO_PHONON_VIDEO
0548 
0549             /**
0550              * Tells about the status of the buffer.
0551              *
0552              * You can use this signal to show a progress bar to the user when
0553              * in BufferingState:
0554              *
0555              * \code
0556              * progressBar->setRange(0, 100); // this is the default
0557              * connect(media, SIGNAL(bufferStatus(int)), progressBar, SLOT(setValue(int)));
0558              * \endcode
0559              *
0560              * \param percentFilled A number between 0 and 100 telling you how
0561              *                      much the buffer is filled.
0562              */ // other names: bufferingProgress
0563             void bufferStatus(int percentFilled);
0564 
0565             /**
0566              * Emitted when the object has finished playback.
0567              * It is not emitted if you call stop(), pause() or
0568              * load(), but only on end-of-queue or a critical error.
0569              *
0570              * \warning This signal is not emitted when the current source has
0571              * finished and there's another source in the queue. It is only
0572              * emitted when the queue is empty.
0573              *
0574              * \see currentSourceChanged
0575              * \see aboutToFinish
0576              * \see prefinishMarkReached
0577              */
0578             void finished();
0579 
0580             /**
0581              * Emitted when the MediaObject makes a transition to the next
0582              * MediaSource in the queue().
0583              *
0584              * In other words, it is emitted when an individual MediaSource is
0585              * finished.
0586              *
0587              * \param newSource The source that starts to play at the time the
0588              * signal is emitted.
0589              */
0590             void currentSourceChanged(const Phonon::MediaSource &newSource);
0591 
0592             /**
0593              * Emitted before the playback of the whole queue stops. When this
0594              * signal is emitted you still have time to provide the next
0595              * MediaSource (using enqueue()) so that playback continues.
0596              *
0597              * This signal can be used to provide the next MediaSource just in
0598              * time for the transition still to work.
0599              *
0600              * \see enqueue
0601              */
0602             void aboutToFinish();
0603 
0604             /**
0605              * Emitted when there are only \p msecToEnd milliseconds left
0606              * for playback.
0607              *
0608              * \param msecToEnd The remaining time until the playback queue finishes.
0609              *
0610              * \warning This signal is not emitted when there is another source in the queue.
0611              * It is only emitted when the queue is empty.
0612              *
0613              * \see setPrefinishMark
0614              * \see prefinishMark
0615              * \see aboutToFinish
0616              * \see finished
0617              */
0618             void prefinishMarkReached(qint32 msecToEnd);
0619 
0620             /**
0621              * This signal is emitted as soon as the total time of the media file is
0622              * known or has changed. For most non-local media data the total
0623              * time of the media can only be known after some time. Initially the
0624              * totalTime function can not return useful information. You have
0625              * to wait for this signal to know the real total time.
0626              *
0627              * This signal may appear at any given point after a MediaSource was set.
0628              * Namely in the LoadingState, BufferingState, PlayingState or PausedState.
0629              *
0630              * \note When changing the currentSource there is no signal emission until
0631              *       a reasonable value for the new source has been calculated.
0632              *
0633              * \param newTotalTime The length of the media file in milliseconds.
0634              *
0635              * \see totalTime
0636              */
0637             void totalTimeChanged(qint64 newTotalTime);
0638 
0639         protected:
0640             //MediaObject(Phonon::MediaObjectPrivate &dd, QObject *parent);
0641 
0642         private:
0643             Q_PRIVATE_SLOT(k_func(), void _k_resumePlay())
0644             Q_PRIVATE_SLOT(k_func(), void _k_resumePause())
0645             Q_PRIVATE_SLOT(k_func(), void _k_metaDataChanged(const QMultiMap<QString, QString> &))
0646 #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
0647             Q_PRIVATE_SLOT(k_func(), void _k_stateChanged(Phonon::State, Phonon::State))
0648 #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
0649             Q_PRIVATE_SLOT(k_func(), void _k_aboutToFinish())
0650             Q_PRIVATE_SLOT(k_func(), void _k_currentSourceChanged(const MediaSource &))
0651             Q_PRIVATE_SLOT(k_func(), void _k_stateChanged(Phonon::State, Phonon::State))
0652     };
0653 
0654     /**
0655      * Convenience function to create a MediaObject and AudioOutput connected by
0656      * a path.
0657      */
0658     PHONON_EXPORT MediaObject *createPlayer(Phonon::Category category, const MediaSource &source = MediaSource());
0659 } //namespace Phonon
0660 
0661 
0662 // vim: sw=4 ts=4 tw=80
0663 #endif // Phonon_MEDIAOBJECT_H