| 1 | /* |
| 2 | Copyright (C) 2011-2018 Harald Sitter <sitter@kde.org> |
| 3 | |
| 4 | This library is free software; you can redistribute it and/or |
| 5 | modify it under the terms of the GNU Lesser General Public |
| 6 | License as published by the Free Software Foundation; either |
| 7 | version 2.1 of the License, or (at your option) any later version. |
| 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 GNU |
| 12 | Lesser General Public License for more details. |
| 13 | |
| 14 | You should have received a copy of the GNU Lesser General Public |
| 15 | License along with this library. If not, see <http://www.gnu.org/licenses/>. |
| 16 | */ |
| 17 | |
| 18 | #ifndef PHONON_VLC_MEDIAPLAYER_H |
| 19 | #define PHONON_VLC_MEDIAPLAYER_H |
| 20 | |
| 21 | #include <QObject> |
| 22 | #include <QSharedPointer> |
| 23 | #include <QSize> |
| 24 | |
| 25 | #include <vlc/libvlc_version.h> |
| 26 | #include <vlc/vlc.h> |
| 27 | |
| 28 | class QImage; |
| 29 | class QString; |
| 30 | |
| 31 | namespace Phonon { |
| 32 | namespace VLC { |
| 33 | |
| 34 | class Media; |
| 35 | |
| 36 | template<class VLCArray> |
| 37 | class Descriptions |
| 38 | { |
| 39 | public: |
| 40 | typedef void (*ReleaseFunction) (VLCArray**, unsigned int) ; |
| 41 | |
| 42 | Descriptions(VLCArray **data, |
| 43 | unsigned int size, |
| 44 | ReleaseFunction release) |
| 45 | : m_release(release) |
| 46 | , m_data(data) |
| 47 | , m_size(size) |
| 48 | { |
| 49 | } |
| 50 | |
| 51 | ~Descriptions() |
| 52 | { |
| 53 | m_release(m_data, m_size); |
| 54 | } |
| 55 | |
| 56 | unsigned int size() const { return m_size; } |
| 57 | |
| 58 | private: |
| 59 | ReleaseFunction m_release; |
| 60 | |
| 61 | VLCArray **m_data; |
| 62 | unsigned int m_size; |
| 63 | }; |
| 64 | |
| 65 | typedef Descriptions<libvlc_title_description_t> TitleDescriptions; |
| 66 | typedef QSharedPointer<const TitleDescriptions> SharedTitleDescriptions; |
| 67 | |
| 68 | typedef Descriptions<libvlc_chapter_description_t> ChapterDescriptions; |
| 69 | typedef QSharedPointer<ChapterDescriptions> SharedChapterDescriptions; |
| 70 | |
| 71 | class MediaPlayer : public QObject |
| 72 | { |
| 73 | Q_OBJECT |
| 74 | public: |
| 75 | enum State { |
| 76 | NoState = 0, |
| 77 | OpeningState, |
| 78 | BufferingState, |
| 79 | PlayingState, |
| 80 | PausedState, |
| 81 | StoppedState, |
| 82 | EndedState, |
| 83 | ErrorState |
| 84 | }; |
| 85 | |
| 86 | explicit MediaPlayer(QObject *parent = nullptr); |
| 87 | ~MediaPlayer(); |
| 88 | |
| 89 | inline libvlc_media_player_t *libvlc_media_player() const { return m_player; } |
| 90 | inline operator libvlc_media_player_t *() const { return m_player; } |
| 91 | |
| 92 | void setMedia(Media *media); |
| 93 | |
| 94 | void setVideoCallbacks(); |
| 95 | void setVideoFormatCallbacks(); |
| 96 | |
| 97 | void setNsObject(void *drawable) { libvlc_media_player_set_nsobject(p_mi: m_player, drawable); } |
| 98 | void setXWindow(quint32 drawable) { libvlc_media_player_set_xwindow(p_mi: m_player, drawable); } |
| 99 | void setHwnd(void *drawable) { libvlc_media_player_set_hwnd(p_mi: m_player, drawable); } |
| 100 | |
| 101 | // Playback |
| 102 | bool play(); |
| 103 | void pause(); |
| 104 | void pausedPlay(); |
| 105 | void resume(); |
| 106 | void togglePause(); |
| 107 | Q_INVOKABLE void stop(); |
| 108 | |
| 109 | qint64 length() const; |
| 110 | qint64 time() const; |
| 111 | void setTime(qint64 newTime); |
| 112 | |
| 113 | bool isSeekable() const; |
| 114 | |
| 115 | // Video |
| 116 | QSize videoSize() const |
| 117 | { |
| 118 | unsigned int width; |
| 119 | unsigned int height; |
| 120 | libvlc_video_get_size(p_mi: m_player, num: 0, px: &width, py: &height); |
| 121 | return QSize(width, height); |
| 122 | } |
| 123 | |
| 124 | bool hasVideoOutput() const; |
| 125 | |
| 126 | /// Set new video aspect ratio. |
| 127 | /// \param aspect new video aspect-ratio or empty to reset to default |
| 128 | void setVideoAspectRatio(const QByteArray &aspect) |
| 129 | { libvlc_video_set_aspect_ratio(p_mi: m_player, psz_aspect: aspect.isEmpty() ? 0 : aspect.data()); } |
| 130 | |
| 131 | void setVideoAdjust(libvlc_video_adjust_option_t adjust, int value) |
| 132 | { libvlc_video_set_adjust_int(p_mi: m_player, option: adjust, value); } |
| 133 | |
| 134 | void setVideoAdjust(libvlc_video_adjust_option_t adjust, float value) |
| 135 | { libvlc_video_set_adjust_float(p_mi: m_player, option: adjust, value); } |
| 136 | |
| 137 | int subtitle() const |
| 138 | { return libvlc_video_get_spu(p_mi: m_player); } |
| 139 | |
| 140 | libvlc_track_description_t *videoSubtitleDescription() const |
| 141 | { return libvlc_video_get_spu_description(p_mi: m_player); } |
| 142 | |
| 143 | bool setSubtitle(int subtitle); |
| 144 | bool setSubtitle(const QString &file); |
| 145 | |
| 146 | int title() const |
| 147 | { return libvlc_media_player_get_title(p_mi: m_player); } |
| 148 | |
| 149 | int titleCount() const |
| 150 | { return libvlc_media_player_get_title_count(p_mi: m_player); } |
| 151 | |
| 152 | SharedTitleDescriptions titleDescription() const |
| 153 | { |
| 154 | libvlc_title_description_t **data; |
| 155 | unsigned int size = |
| 156 | libvlc_media_player_get_full_title_descriptions(p_mi: m_player, titles: &data); |
| 157 | return SharedTitleDescriptions( |
| 158 | new TitleDescriptions( |
| 159 | data, size, |
| 160 | &libvlc_title_descriptions_release) |
| 161 | ); |
| 162 | } |
| 163 | |
| 164 | void setTitle(int title); |
| 165 | |
| 166 | int videoChapterCount() const |
| 167 | { return libvlc_media_player_get_chapter_count(p_mi: m_player); } |
| 168 | |
| 169 | SharedChapterDescriptions videoChapterDescription(int title) const |
| 170 | { |
| 171 | libvlc_chapter_description_t **data; |
| 172 | unsigned int size = |
| 173 | libvlc_media_player_get_full_chapter_descriptions(p_mi: m_player, i_chapters_of_title: title, pp_chapters: &data); |
| 174 | return SharedChapterDescriptions( |
| 175 | new ChapterDescriptions( |
| 176 | data, size, |
| 177 | &libvlc_chapter_descriptions_release) |
| 178 | ); |
| 179 | } |
| 180 | |
| 181 | void setChapter(int chapter); |
| 182 | |
| 183 | /** Reentrant, through libvlc */ |
| 184 | QImage snapshot() const; |
| 185 | |
| 186 | // Audio |
| 187 | /// Get current audio volume. |
| 188 | /// \return the software volume in percents (0 = mute, 100 = nominal / 0dB) |
| 189 | int audioVolume() const { return m_volume; } |
| 190 | |
| 191 | /// Set new audio volume. |
| 192 | /// \param volume new volume |
| 193 | void setAudioVolume(int volume); |
| 194 | |
| 195 | /// \return mutness |
| 196 | bool mute() const; |
| 197 | |
| 198 | /** |
| 199 | * Mutes |
| 200 | * @param mute whether to mute or unmute |
| 201 | */ |
| 202 | void setMute(bool mute); |
| 203 | |
| 204 | /// Set the fade percentage, between 0 (muted) and 1.0 (no fade) |
| 205 | void setAudioFade(qreal fade); |
| 206 | |
| 207 | /// \param name name of the output to set |
| 208 | /// \returns \c true when setting was successful, \c false otherwise |
| 209 | bool setAudioOutput(const QByteArray &name) |
| 210 | { return libvlc_audio_output_set(p_mi: m_player, psz_name: name.data()) == 0; } |
| 211 | |
| 212 | /** |
| 213 | * Set audio output device by name. |
| 214 | * \param outputName the aout name (pulse, alsa, oss, etc.) |
| 215 | * \param deviceName the output name (aout dependent) |
| 216 | */ |
| 217 | void setAudioOutputDevice(const QByteArray &outputName, const QByteArray &deviceName) |
| 218 | { libvlc_audio_output_device_set(mp: m_player, module: outputName.data(), device_id: deviceName.data()); } |
| 219 | |
| 220 | int audioTrack() const |
| 221 | { return libvlc_audio_get_track(p_mi: m_player); } |
| 222 | |
| 223 | libvlc_track_description_t * audioTrackDescription() const |
| 224 | { return libvlc_audio_get_track_description(p_mi: m_player); } |
| 225 | |
| 226 | bool setAudioTrack(int track); |
| 227 | |
| 228 | void setCdTrack(int track); |
| 229 | |
| 230 | void setEqualizer(libvlc_equalizer_t *equalizer); |
| 231 | |
| 232 | Q_SIGNALS: |
| 233 | void lengthChanged(qint64 length); |
| 234 | void seekableChanged(bool seekable); |
| 235 | void stateChanged(MediaPlayer::State state); |
| 236 | void timeChanged(qint64 time); |
| 237 | void bufferChanged(int percent); |
| 238 | |
| 239 | /** Emitted when the vout availability has changed */ |
| 240 | void hasVideoChanged(bool hasVideo); |
| 241 | |
| 242 | void mutedChanged(bool mute); |
| 243 | void volumeChanged(float volume); |
| 244 | |
| 245 | private: |
| 246 | static void event_cb(const libvlc_event_t *event, void *opaque); |
| 247 | void setVolumeInternal(); |
| 248 | |
| 249 | Media *m_media; |
| 250 | |
| 251 | libvlc_media_player_t *m_player; |
| 252 | |
| 253 | bool m_doingPausedPlay; |
| 254 | int m_volume; |
| 255 | qreal m_fadeAmount; |
| 256 | }; |
| 257 | |
| 258 | QDebug operator<<(QDebug dbg, const MediaPlayer::State &s); |
| 259 | |
| 260 | } // namespace VLC |
| 261 | } // namespace Phonon |
| 262 | |
| 263 | #endif // PHONON_VLC_MEDIAPLAYER_H |
| 264 | |