1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2010 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef WABSTRACT_MEDIA_H_ 8 #define WABSTRACT_MEDIA_H_ 9 10 #include <Wt/WInteractWidget.h> 11 #include <Wt/WLink.h> 12 #include <Wt/WFlags.h> 13 14 namespace Wt { 15 16 /*! \brief Enumeration for playback options 17 */ 18 enum class PlayerOption { 19 Autoplay = 1, //!< Start playing as soon as the video is loaded 20 Loop = 2, //!< Enable loop mode 21 Controls = 4 //!< Show video controls in the browser 22 }; 23 24 /*! \brief Enumeration for preload strategy 25 */ 26 enum class MediaPreloadMode { 27 None, //!< Hints that the user will probably not play the video 28 Auto, //!< Hints that it is ok to download the entire resource 29 Metadata //!< Hints that retrieving metadata is a good option 30 }; 31 32 /*! \class WAbstractMedia Wt/WAbstractMedia.h Wt/WAbstractMedia.h 33 * \brief Abstract baseclass for native media elements. 34 * 35 * This class is an abstract base class for HTML5 media elements 36 * (<audio>, <video>). 37 * 38 */ 39 class WT_API WAbstractMedia : public WInteractWidget 40 { 41 public: 42 /*! \brief Typedef for enum Wt::PlayerOption */ 43 typedef PlayerOption Option; 44 45 /*! \brief Typedef for enum Wt::MediaPreloadMode */ 46 typedef MediaPreloadMode PreloadMode; 47 48 /*! \brief Typedef for enum Wt::MediaReadyState */ 49 typedef MediaReadyState ReadyState; 50 51 /*! \brief Consctructor for a media widget. 52 * 53 * A freshly constructed media widget has no options set, no media 54 * sources, and has preload mode set to PreloadAuto. 55 */ 56 WAbstractMedia(); 57 58 ~WAbstractMedia(); 59 60 /*! \brief Set the media element options 61 * 62 * \sa Options 63 */ 64 void setOptions(const WFlags<PlayerOption> &flags); 65 66 /*! \brief Retrieve the configured options 67 */ 68 WFlags<PlayerOption> getOptions() const; 69 70 /*! \brief Set the preload mode 71 */ 72 void setPreloadMode(MediaPreloadMode mode); 73 74 /*! \brief Retrieve the preload mode 75 */ 76 MediaPreloadMode preloadMode() const; 77 78 /*! \brief Removes all source elements 79 * 80 * This method can be used to remove all media sources. Afterward, you 81 * may add new media sources with calls to addSource(). 82 * 83 * Use this to reuse a WAbstractMedia instantiation to play something else. 84 */ 85 void clearSources(); 86 87 /*! \brief Add a media source 88 * 89 * This method specifies a media source (which may be a URL or 90 * dynamic resource). You may add as many media sources as you 91 * want. The browser will select the appropriate media stream to 92 * display to the user. 93 * 94 * This method specifies a media source using the URL, the mime type, 95 * and the media attribute. HTML allows for empty type and media 96 * attributes. 97 */ 98 void addSource(const WLink& source, const std::string &type = "", 99 const std::string &media = ""); 100 101 /*! \brief Content to be shown when media cannot be played 102 * 103 * As not all browsers are HTML5 compliant, it is a good idea to 104 * provide fallback options when the media cannot be displayed. If 105 * the media can be played by the browser, the alternative content 106 * will be suppressed. 107 * 108 * The two reasons to display the alternative content are (1) the 109 * media tag is not supported, or (2) the media tag is supported, but 110 * none of the media sources are supported by the browser. In the first 111 * case, fall-back is automatic and does not rely on JavaScript in the 112 * browser; in the latter case, JavaScript is required to make the 113 * fallback work. 114 * 115 * The alternative content can be any widget: you can set it to an 116 * alternative media player (QuickTime, Flash, ...), show a 117 * Flash movie, an animated gif, a text, a poster image, ... 118 */ 119 void setAlternativeContent(std::unique_ptr<WWidget> alternative); 120 121 /*! \brief Invoke play() on the media element 122 * 123 * JavaScript must be available for this function to work. 124 */ 125 void play(); 126 127 /*! \brief Invoke pause() on the media element 128 * 129 * JavaScript must be available for this function to work. 130 */ 131 void pause(); 132 133 /*! \brief Returns whether the media is playing. 134 */ playing()135 bool playing() const { return playing_; } 136 137 /*! \brief Returns the media's readyState 138 */ readyState()139 MediaReadyState readyState() const { return readyState_; } 140 141 /*! \brief Event signal emitted when playback has begun. 142 * 143 * This event fires when play was invoked, or when the media element 144 * starts playing because the Autoplay option was provided. 145 * 146 * \note When JavaScript is disabled, the signal will never fire. 147 */ 148 EventSignal<>& playbackStarted(); 149 150 /*! \brief Event signal emitted when the playback has paused. 151 * 152 * \note When JavaScript is disabled, the signal will never fire. 153 */ 154 EventSignal<>& playbackPaused(); 155 156 /*! \brief Event signal emitted when the playback stopped because 157 * the end of the media was reached. 158 * 159 * \note When JavaScript is disabled, the signal will never fire. 160 */ 161 EventSignal<>& ended(); 162 163 /*! \brief Event signal emitted when the current playback position has 164 * changed. 165 * 166 * This event is fired when the playback position has changed, 167 * both when the media is in a normal playing mode, but also when it has 168 * changed discontinuously because of another reason. 169 * 170 * \note When JavaScript is disabled, the signal will never fire. 171 */ 172 EventSignal<>& timeUpdated(); 173 174 /*! \brief Event signal emitted when the playback volume has changed. 175 * 176 * \note When JavaScript is disabled, the signal will never fire. 177 */ 178 EventSignal<>& volumeChanged(); 179 180 /*! \brief Returns the JavaScript reference to the media object, or null. 181 * 182 * It is possible, for browser compatibility reasons, that jsRef() 183 * is not the media element. jsMediaRef() is guaranteed to be an 184 * expression that evaluates to the media object. This expression 185 * may yield null, if the video object is not rendered at all 186 * (e.g. on older versions of Internet Explorer). 187 */ 188 std::string jsMediaRef() const; 189 190 protected: 191 virtual void getDomChanges(std::vector<DomElement *>& result, 192 WApplication *app) override; 193 virtual DomElement *createDomElement(WApplication *app) override; 194 virtual void iterateChildren(const HandleWidgetMethod& method) const override; 195 196 virtual void updateMediaDom(DomElement& element, bool all); 197 virtual DomElement *createMediaDomElement() = 0; 198 199 virtual void setFormData(const FormData& formData) override; 200 virtual void enableAjax() override; 201 202 private: 203 struct Source 204 #ifdef WT_TARGET_JAVA 205 : public WObject 206 #endif 207 { 208 Source(WAbstractMedia *parent, const WLink& link, const std::string &type, 209 const std::string &media); 210 ~Source(); 211 212 void resourceChanged(); 213 214 WAbstractMedia *parent; 215 Wt::Signals::connection connection; 216 std::string type, media; 217 WLink link; 218 }; 219 void renderSource(DomElement* element, WAbstractMedia::Source &source, 220 bool isLast); 221 222 std::vector<std::unique_ptr<Source> > sources_; 223 std::size_t sourcesRendered_; 224 std::string mediaId_; 225 WFlags<PlayerOption> flags_; 226 MediaPreloadMode preloadMode_; 227 std::unique_ptr<WWidget> alternative_; 228 bool flagsChanged_, preloadChanged_, sourcesChanged_; 229 230 // Vars received from client 231 bool playing_; 232 double volume_; 233 double current_; 234 double duration_; 235 bool ended_; 236 MediaReadyState readyState_; 237 238 static const char *PLAYBACKSTARTED_SIGNAL; 239 static const char *PLAYBACKPAUSED_SIGNAL; 240 static const char *ENDED_SIGNAL; 241 static const char *TIMEUPDATED_SIGNAL; 242 static const char *VOLUMECHANGED_SIGNAL; 243 244 void loadJavaScript(); 245 }; 246 247 W_DECLARE_OPERATORS_FOR_FLAGS(PlayerOption) 248 249 } 250 251 #endif // WABSTRACT_MEDIA_H_ 252 253