File indexing completed on 2024-12-01 04:21:26
0001 /* 0002 Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com> 0003 Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com> 0004 Copyright (C) 2009 Fathi Boudra <fabo@kde.org> 0005 Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org> 0006 Copyright (C) 2010-2011 Harald Sitter <sitter@kde.org> 0007 0008 This library is free software; you can redistribute it and/or 0009 modify it under the terms of the GNU Lesser General Public 0010 License as published by the Free Software Foundation; either 0011 version 2.1 of the License, or (at your option) any later version. 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_VLC_MEDIAOBJECT_H 0023 #define PHONON_VLC_MEDIAOBJECT_H 0024 0025 #include <QtCore/QObject> 0026 #include <QtCore/QTimer> 0027 0028 #include <phonon/mediaobjectinterface.h> 0029 #include <phonon/addoninterface.h> 0030 0031 #include "mediacontroller.h" 0032 #include "mediaplayer.h" 0033 0034 namespace Phonon 0035 { 0036 namespace VLC 0037 { 0038 0039 class Media; 0040 class SinkNode; 0041 class StreamReader; 0042 0043 /** \brief Implementation for the most important class in Phonon 0044 * 0045 * The MediaObject class is the workhorse for Phonon. It handles what is needed 0046 * to play media. It has a media source object used to configure what media to 0047 * play. 0048 * 0049 * It provides the essential methods setSource(), play(), seek() and additional 0050 * methods to configure the next media source, the transition between sources, 0051 * transition times, ticks, other. 0052 * 0053 * There are numerous signals that provide information about the state of the media 0054 * and of the playing process. The aboutToFinish() and finished() signals are used 0055 * to see when the current media is finished. 0056 * 0057 * This class does not contain methods directly involved with libVLC. This part is 0058 * handled by the VLCMediaObject class. There are protected methods and slots 0059 * inherited by that class, like playInternal(), seekInternal(). 0060 * These methods have no implementation here. 0061 * 0062 * For documentation regarding the methods implemented for MediaObjectInterface, see 0063 * the Phonon documentation. 0064 * 0065 * \see Phonon::MediaObjectInterface 0066 * \see VLCMediaObject 0067 */ 0068 class MediaObject : public QObject, public MediaObjectInterface, public MediaController 0069 { 0070 Q_OBJECT 0071 Q_INTERFACES(Phonon::MediaObjectInterface Phonon::AddonInterface) 0072 friend class SinkNode; 0073 0074 public: 0075 /** 0076 * Initializes the members, connects the private slots to their corresponding signals, 0077 * sets the next media source to an empty media source. 0078 * 0079 * \param parent A parent for the QObject 0080 */ 0081 explicit MediaObject(QObject *parent); 0082 ~MediaObject(); 0083 0084 /** 0085 * Reset members (those that need resetting anyway). 0086 * Should always be called before going to a new source. 0087 */ 0088 void resetMembers(); 0089 0090 /** 0091 * If the current state is paused, it resumes playing. Else, the playback 0092 * is commenced. 0093 */ 0094 void play() override; 0095 0096 /// Pauses the playback for the media player. 0097 void pause() override; 0098 0099 /// Sets the next media source to an empty one and stops playback. 0100 void stop() override; 0101 0102 /// \returns \c true when there is a video available, \c false otherwise 0103 bool hasVideo() const override; 0104 0105 /// \returns \c true when the MediaObject is seekable, \c false otherwise 0106 bool isSeekable() const override; 0107 0108 /// \returns total time (length, duration) of the current MediaSource (-1 if unknown) 0109 qint64 totalTime() const override; 0110 0111 /// \returns An error message with the last libVLC error. 0112 QString errorString() const override; 0113 0114 /** 0115 * Adds a sink for this media object. During playInternal(), all the sinks 0116 * will have their addToMedia() called. 0117 * 0118 * \see playInternal() 0119 * \see SinkNode::addToMedia() 0120 */ 0121 void addSink(SinkNode *node); 0122 0123 /// Removes a sink from this media object. 0124 void removeSink(SinkNode *node); 0125 0126 /** 0127 * Pushes a seek command to the SeekStack for this media object. The SeekStack then 0128 * calls seekInternal() when it's popped. 0129 */ 0130 void seek(qint64 milliseconds) override; 0131 0132 /** 0133 * \return The interval between successive tick() signals. If set to 0, the emission 0134 * of these signals is disabled. 0135 */ 0136 qint32 tickInterval() const override; 0137 0138 /** 0139 * Sets the interval between successive tick() signals. If set to 0, it disables the 0140 * emission of these signals. 0141 */ 0142 void setTickInterval(qint32 tickInterval) override; 0143 0144 /** 0145 * \return The current time of the media, depending on the current state. 0146 * If the current state is stopped or loading, 0 is returned. 0147 * If the current state is error or unknown, -1 is returned. 0148 */ 0149 qint64 currentTime() const override; 0150 0151 /// \return The current state for this media object. 0152 Phonon::State state() const override; 0153 0154 /// All errors are categorized as normal errors. 0155 Phonon::ErrorType errorType() const override; 0156 0157 /// \return The current media source for this media object. 0158 MediaSource source() const override; 0159 0160 /** 0161 * Sets the current media source for this media object. Depending on the source type, 0162 * the media object loads the specified media. The MRL is passed to loadMedia(), if the media 0163 * is not a stream. The currentSourceChanged() signal 0164 * is emitted. 0165 * 0166 * Supported media source types: 0167 * \li local files 0168 * \li URL 0169 * \li discs (CD, DVD, VCD) 0170 * \li capture devices (V4L) 0171 * \li streams 0172 * 0173 * \param source The media source that will become the current source. 0174 * 0175 * \see loadMedia() 0176 */ 0177 void setSource(const MediaSource &source) override; 0178 0179 /// Sets the media source that will replace the current one, after the playback for it finishes. 0180 void setNextSource(const MediaSource &source) override; 0181 0182 qint32 prefinishMark() const override; 0183 void setPrefinishMark(qint32 msecToEnd) override; 0184 0185 qint32 transitionTime() const override; 0186 void setTransitionTime(qint32) override; 0187 0188 void emitAboutToFinish(); 0189 0190 Q_SIGNALS: 0191 // MediaController signals 0192 void availableSubtitlesChanged(); 0193 void availableAudioChannelsChanged(); 0194 0195 void availableChaptersChanged(int); 0196 void availableTitlesChanged(int); 0197 0198 void chapterChanged(int chapterNumber); 0199 void titleChanged(int titleNumber); 0200 void durationChanged(qint64 newDuration); 0201 0202 /** 0203 * New widget size computed by VLC. 0204 * 0205 * It should be applied to the widget that contains the VLC video. 0206 */ 0207 void videoWidgetSizeChanged(int i_width, int i_height); 0208 0209 void aboutToFinish(); 0210 void bufferStatus(int percentFilled); 0211 void currentSourceChanged(const MediaSource &newSource); 0212 void finished(); 0213 void hasVideoChanged(bool b_has_video); 0214 void metaDataChanged(const QMultiMap<QString, QString> & metaData); 0215 void prefinishMarkReached(qint32 msecToEnd); 0216 void seekableChanged(bool seekable); 0217 void stateChanged(Phonon::State newState, Phonon::State oldState); 0218 void tick(qint64 time); 0219 void totalTimeChanged(qint64 newTotalTime); 0220 0221 void moveToNext(); 0222 0223 private Q_SLOTS: 0224 /** 0225 * If the new state is different from the current state, the current state is 0226 * changed and the corresponding signal is emitted. 0227 */ 0228 void changeState(Phonon::State newState); 0229 0230 /** 0231 * Checks when the tick(), prefinishMarkReached(), aboutToFinish() signals need to 0232 * be emitted and emits them if necessary. 0233 * 0234 * \param currentTime The current play time for the media, in milliseconds. 0235 */ 0236 void timeChanged(qint64 time); 0237 void emitTick(qint64 time); 0238 0239 /** 0240 * If the next media source is valid, the current source is replaced and playback is commenced. 0241 * The next source is set to an empty source. 0242 * 0243 * \see setNextSource() 0244 */ 0245 void moveToNextSource(); 0246 0247 /*** Update media duration time - see comment in CPP */ 0248 void updateDuration(qint64 newDuration); 0249 0250 /** Retrieve meta data of a file (i.e ARTIST, TITLE, ALBUM, etc...). */ 0251 void updateMetaData(); 0252 void updateState(MediaPlayer::State state); 0253 0254 /** Called when the availability of video output changed */ 0255 void onHasVideoChanged(bool hasVideo); 0256 0257 void setBufferStatus(int percent); 0258 0259 /** Refreshes all MediaController descriptors if Video is present. */ 0260 void refreshDescriptors(); 0261 0262 private: 0263 /** 0264 * This method actually calls the functions needed to begin playing the media. 0265 * If another media is already playing, it is discarded. The new media filename is set 0266 * with loadMediaInternal(). A new VLC Media is created and set into the VLC Media Player. 0267 * All the connected sink nodes are connected to the new media. It connects the media object 0268 * to the events for the VLC Media, updates the meta-data, sets up the video widget id, and 0269 * starts playing. 0270 * 0271 * \see loadMediaInternal() 0272 * \see connectToMediaVLCEvents() 0273 * \see updateMetaData() 0274 * \see setVLCWidgetId() 0275 */ 0276 void setupMedia(); 0277 0278 /** 0279 * Seeks to the required position. If the state is not playing, the seek position is remembered. 0280 */ 0281 void seekInternal(qint64 milliseconds); 0282 0283 bool hasNextTrack(); 0284 0285 /** 0286 * Changes the current state to buffering and sets the new current file. 0287 * 0288 * \param filename The MRL of the media source 0289 */ 0290 void loadMedia(const QByteArray &mrl); 0291 0292 /** 0293 * Overload for loadMedia, converting a QString to a QByteArray. 0294 * 0295 * \param filename The MRL of the media source 0296 * 0297 * \see loadMedia 0298 */ 0299 void loadMedia(const QString &mrl); 0300 0301 /** 0302 * Uninitializes the media 0303 */ 0304 void unloadMedia(); 0305 0306 MediaSource m_nextSource; 0307 0308 MediaSource m_mediaSource; 0309 StreamReader *m_streamReader; 0310 Phonon::State m_state; 0311 0312 qint32 m_prefinishMark; 0313 bool m_prefinishEmitted; 0314 0315 bool m_aboutToFinishEmitted; 0316 0317 qint32 m_tickInterval; 0318 qint64 m_lastTick; 0319 qint32 m_transitionTime; 0320 0321 Media *m_media; 0322 0323 qint64 m_totalTime; 0324 QByteArray m_mrl; 0325 QMultiMap<QString, QString> m_vlcMetaData; 0326 QList<SinkNode *> m_sinks; 0327 0328 bool m_hasVideo; 0329 bool m_isScreen; 0330 0331 /** 0332 * Workaround for being able to seek before VLC goes to playing state. 0333 * Seeks before playing are stored in this var, and processed on state change 0334 * to Playing. 0335 */ 0336 qint64 m_seekpoint; 0337 0338 int m_timesVideoChecked; 0339 0340 bool m_buffering; 0341 Phonon::State m_stateAfterBuffering; 0342 }; 0343 0344 } // namespace VLC 0345 } // namespace Phonon 0346 0347 #endif // PHONON_VLC_MEDIAOBJECT_H