File indexing completed on 2025-02-09 05:31:49
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