File Coverage

lib/HTML/Object/DOM/Element/Media.pm
Criterion Covered Total %
statement 30 143 20.9
branch 0 16 0.0
condition 0 4 0.0
subroutine 10 81 12.3
pod 43 65 66.1
total 83 309 26.8


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## HTML Object - ~/lib/HTML/Object/DOM/Element/Media.pm
3             ## Version v0.2.0
4             ## Copyright(c) 2021 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2021/12/23
7             ## Modified 2022/09/18
8             ## All rights reserved
9             ##
10             ##
11             ## This program is free software; you can redistribute it and/or modify it
12             ## under the same terms as Perl itself.
13             ##----------------------------------------------------------------------------
14             package HTML::Object::DOM::Element::Media;
15             BEGIN
16             {
17 1     1   577 use strict;
  1         2  
  1         30  
18 1     1   5 use warnings;
  1         2  
  1         27  
19 1     1   5 use parent qw( HTML::Object::DOM::Element );
  1         2  
  1         5  
20 1     1   62 use vars qw( @EXPORT_OK %EXPORT_TAGS $VERSION );
  1         2  
  1         56  
21 1     1   11 use HTML::Object::DOM::Element::Shared qw( :media );
  1         2  
  1         103  
22 1     1   423 use HTML::Object::DOM::TrackEvent;
  1         4  
  1         22  
23             use constant {
24             # For HTML::Object::DOM::Element::Media
25             # There is no data yet. Also, readyState is HAVE_NOTHING.
26 1         137 NETWORK_EMPTY => 0,
27             # HTMLMediaElement is active and has selected a resource, but is not using the network.
28             NETWORK_IDLE => 1,
29             # The browser is downloading HTMLMediaElement data.
30             NETWORK_LOADING => 2,
31             # No HTMLMediaElement src found.
32             NETWORK_NO_SOURCE => 3,
33 1     1   481 };
  1         9  
34 1     1   5 our @EXPORT_OK = qw( NETWORK_EMPTY NETWORK_IDLE NETWORK_LOADING NETWORK_NO_SOURCE );
35 1         4 our %EXPORT_TAGS = (
36             all => [qw( NETWORK_EMPTY NETWORK_IDLE NETWORK_LOADING NETWORK_NO_SOURCE )],
37             );
38 1         17 our $VERSION = 'v0.2.0';
39             };
40              
41 1     1   8 use strict;
  1         6  
  1         25  
42 1     1   7 use warnings;
  1         4  
  1         1778  
43              
44             sub init
45             {
46 0     0 1   my $self = shift( @_ );
47 0           $self->{ended} = 0;
48 0           $self->{paused} = 1;
49 0           $self->{sinkid} = undef;
50 0           $self->{_init_strict_use_sub} = 1;
51 0 0         $self->SUPER::init( @_ ) || return( $self->pass_error );
52 0           $self->{_callback_off} = 0;
53 0           $self->{_exception_class} = 'HTML::Object::MediaError';
54 0 0         $self->{tag} = 'media' if( !CORE::length( "$self->{tag}" ) );
55             $self->_set_get_internal_attribute_callback( controlslist => sub
56             {
57 0     0     my( $this, $val ) = @_;
58 0           my $list;
59 0 0         return if( !( $list = $this->{_controlslist_list} ) );
60             # $list->debug( $self->debug );
61 0           $list->update( $val );
62 0           });
63 0           return( $self );
64             }
65              
66             sub addTextTrack
67             {
68 0     0 1   my $self = shift( @_ );
69 0           my $list = $self->textTracks;
70 0 0         $self->_load_class( 'HTML::Object::DOM::TextTrack' ) || return( $self->pass_error );
71 0   0       my $new = HTML::Object::DOM::TextTrack->new( @_ ) ||
72             return( $self->pass_error( HTML::Object::DOM::TextTrack->error ) );
73 0           $list->push( $new );
74             # There is no parent, because a TextTrack parent is actually a HTML::Object::DOM::Element::Track object
75             # and here we only add a TextTrack object directly.
76             # $new->parent( $self );
77 0           return( $self );
78             }
79              
80             # Note: property
81 0     0 1   sub audioTracks : lvalue { return( shift->_set_get_property( 'audiotracks', @_ ) ); }
82              
83             # Note: property
84 0     0 1   sub autoplay : lvalue { return( shift->_set_get_property( { attribute => 'autoplay', is_boolean => 1 }, @_ ) ); }
85              
86             # Note: property read-only
87 0     0 1   sub buffered { return; }
88              
89 0     0 1   sub canPlayType { return; }
90              
91 0     0 1   sub captureStream { return; }
92              
93             # Note: property
94 0     0 1   sub controller { return; }
95              
96             # Note: property
97 0     0 1   sub controls : lvalue { return( shift->_set_get_property( { attribute => 'controls', is_boolean => 1 }, @_ ) ); }
98              
99             # Note: property read-only
100             sub controlsList
101             {
102 0     0 1   my $self = shift( @_ );
103 0 0         unless( $self->{_controlslist_list} )
104             {
105 0           my $controls = $self->attr( 'controlslist' );
106 0           require HTML::Object::TokenList;
107 0   0       $self->{_controlslist_list} = HTML::Object::TokenList->new( $controls, element => $self, attribute => 'controlslist', debug => $self->debug ) ||
108             return( $self->pass_error( HTML::Object::TokenList->error ) );
109             }
110 0           return( $self->{_controlslist_list} );
111             }
112              
113             # Note: property crossOrigin inherited
114              
115             # Note: property read-only currentSrc inherited
116              
117             # Note: property
118             sub currentTime : lvalue { return( shift->_set_get_number({
119             field => 'currentTime',
120             callbacks =>
121             {
122 0     0     add => sub{ shift->_trigger_event_for( timeupdate => 'HTML::Object::Event', bubbles => 0, cancellable => 0 ) },
123             }
124 0     0 1   }, @_ ) ); }
125              
126             # Note: property
127 0     0 1   sub defaultMuted : lvalue { return( shift->_set_get_property( { attribute => 'muted', is_boolean => 1 }, @_ ) ); }
128              
129             # Note: property
130 0     0 1   sub defaultPlaybackRate : lvalue { return( shift->_set_get_number( 'defaultplaybackrate', @_ ) ); }
131              
132             # Note: property
133 0     0 1   sub disableRemotePlayback : lvalue { return( shift->_set_get_property( { attribute => 'disableremoteplayback', is_boolean => 1 }, @_ ) ); }
134              
135             # Note: property
136             sub duration : lvalue { return( shift->_set_get_number({
137             field => 'duration',
138             callbacks => {
139 0     0     add => sub{ shift->_trigger_event_for( durationchange => 'HTML::Object::Event', bubbles => 0, cancellable => 0 ) },
140             }
141 0     0 1   }, @_ ) ); }
142              
143             # Note: property read-only
144 0     0 1   sub ended : lvalue { return( shift->_set_get_boolean( 'ended', @_ ) ); }
145              
146             # Note: property read-only error is inherited from Module::Generic
147              
148 0     0 1   sub fastSeek { return; }
149              
150             # TODO: Maybe do some interesting stuff loading a new file? However, since we cannot do much with audio or video under perl, there is not uch prospect as far as I can tell.
151 0     0 1   sub load { return; }
152              
153             # Note: property
154 0     0 1   sub loop : lvalue { return( shift->_set_get_property( { attribute => 'loop', is_boolean => 1 }, @_ ) ); }
155              
156             # Note: property read-only
157 0     0 1   sub mediaKeys { return; }
158              
159             # Note: property
160 0     0 1   sub muted : lvalue { return( shift->_set_get_boolean( 'muted', @_ ) ); }
161              
162             # Note: property read-only
163 0     0 1   sub networkState : lvalue { return( shift->_set_get_number( 'networkstate', @_ ) ); }
164              
165 0     0 0   sub onabort : lvalue { return( shift->on( 'abort', @_ ) ); }
166              
167 0     0 0   sub oncanplay : lvalue { return( shift->on( 'canplay', @_ ) ); }
168              
169 0     0 0   sub oncanplaythrough : lvalue { return( shift->on( 'canplaythrough', @_ ) ); }
170              
171 0     0 0   sub ondurationchange : lvalue { return( shift->on( 'durationchange', @_ ) ); }
172              
173 0     0 0   sub onemptied : lvalue { return( shift->on( 'emptied', @_ ) ); }
174              
175 0     0 1   sub onencrypted : lvalue { return( shift->on( 'encrypted', @_ ) ); }
176              
177 0     0 0   sub onended : lvalue { return( shift->on( 'ended', @_ ) ); }
178              
179 0     0 0   sub onerror : lvalue { return( shift->on( 'error', @_ ) ); }
180              
181 0     0 0   sub onloadeddata : lvalue { return( shift->on( 'loadeddata', @_ ) ); }
182              
183 0     0 0   sub onloadedmetadata : lvalue { return( shift->on( 'loadedmetadata', @_ ) ); }
184              
185 0     0 0   sub onloadstart : lvalue { return( shift->on( 'loadstart', @_ ) ); }
186              
187 0     0 0   sub onpause : lvalue { return( shift->on( 'pause', @_ ) ); }
188              
189 0     0 0   sub onplay : lvalue { return( shift->on( 'play', @_ ) ); }
190              
191 0     0 0   sub onplaying : lvalue { return( shift->on( 'playing', @_ ) ); }
192              
193 0     0 0   sub onprogress : lvalue { return( shift->on( 'progress', @_ ) ); }
194              
195 0     0 0   sub onratechange : lvalue { return( shift->on( 'ratechange', @_ ) ); }
196              
197 0     0 0   sub onseeked : lvalue { return( shift->on( 'seeked', @_ ) ); }
198              
199 0     0 0   sub onseeking : lvalue { return( shift->on( 'seeking', @_ ) ); }
200              
201 0     0 0   sub onstalled : lvalue { return( shift->on( 'stalled', @_ ) ); }
202              
203 0     0 0   sub onsuspend : lvalue { return( shift->on( 'suspend', @_ ) ); }
204              
205 0     0 0   sub ontimeupdate : lvalue { return( shift->on( 'timeupdate', @_ ) ); }
206              
207 0     0 0   sub onvolumechange : lvalue { return( shift->on( 'volumechange', @_ ) ); }
208              
209 0     0 0   sub onwaiting : lvalue { return( shift->on( 'waiting', @_ ) ); }
210              
211 0     0 1   sub onwaitingforkey : lvalue { return( shift->on( 'waitingforkey', @_ ) ); }
212              
213             sub pause
214             {
215 0     0 1   my $self = shift( @_ );
216 0           $self->{_callback_off} = 1;
217 0           $self->paused(1);
218 0           $self->{_callback_off} = 0;
219 0           $self->_trigger_event_for( pause => 'HTML::Object::Event', bubbles => 0, cancellable => 0 );
220 0           return( $self )
221             }
222              
223             # Note: property read-only
224             sub paused : lvalue { return( shift->_set_get_boolean({
225             field => 'paused',
226             callbacks => {
227             add => sub
228             {
229 0     0     my $self = shift( @_ );
230 0 0         return if( $self->{_callback_off} );
231 0           $self->_trigger_event_for( paused => 'HTML::Object::Event', bubbles => 0, cancellable => 0 );
232             }
233             }
234 0     0 1   }, @_ ) ); }
235              
236             sub play
237             {
238 0     0 1   my $self = shift( @_ );
239 0           $self->{_callback_off} = 1;
240 0           $self->paused(0);
241 0           $self->{_callback_off} = 0;
242 0           $self->_trigger_event_for( play => 'HTML::Object::Event', bubbles => 0, cancellable => 0 );
243 0           return( $self );
244             }
245              
246             # Note: property
247             sub playbackRate : lvalue { return( shift->_set_get_number({
248             field => 'playbackrate',
249             callbacks =>
250             {
251 0     0     add => sub{ return( shift->_trigger_event_for( ratechange => 'HTML::Object::Event', bubbles => 0, cancellable => 0 ) ); },
252             }
253 0     0 1   }, @_ ) ); }
254              
255             # Note: property read-only
256 0     0 1   sub played { return; }
257              
258             # Note: property
259 0     0 1   sub preload : lvalue { return( shift->_set_get_property( 'preload', @_ ) ); }
260              
261             # Note: property
262 0     0 1   sub preservesPitch : lvalue { return( shift->_set_get_boolean( 'preservespitch', @_ ) ); }
263              
264             # Note: property read-only
265 0     0 1   sub readyState : lvalue { return( shift->_set_get_number( 'readystate', @_ ) ); }
266              
267             # TODO: removeTextTrack
268             sub removeTextTrack
269             {
270 0     0 1   my $self = shift( @_ );
271 0           my $obj = shift( @_ );
272 0 0         return( $self->error({
273             message => "Value provided is not a HTML::Object::DOM::TextTrack object.",
274             class => 'HTML::Object::TypeError',
275             }) ) if( !$self->_is_a( $obj => 'HTML::Object::DOM::TextTrack' ) );
276 0           my $list = $self->textTracks;
277 0           my $pos = $list->pos( $obj );
278 0 0         return if( !defined( $pos ) );
279 0           $list->splice( $pos, 1 );
280             # There is no parent, because a TextTrack parent is actually a HTML::Object::DOM::Element::Track object
281             # and here we only add or remove a TextTrack object directly.
282             # $obj->parent( undef );
283 0           return( $obj );
284             }
285              
286             # Note: property read-only
287 0     0 1   sub seekable { return; }
288              
289             # Note: property read-only
290 0     0 1   sub seeking : lvalue { return( shift->_set_get_boolean( 'seeking', @_ ) ); }
291              
292 0     0 1   sub seekToNextFrame { return; }
293              
294 0     0 1   sub setMediaKeys { return; }
295              
296 0     0 1   sub setSinkId { return( shift->_set_get_scalar_as_object( 'sinkid', @_ ) ); }
297              
298             # Note: property read-only
299 0     0 1   sub sinkId : lvalue { return( shift->_set_get_scalar_as_object( 'sinkid', @_ ) ); }
300              
301             # Note: property src inherited
302              
303             # Note: property
304 0     0 1   sub srcObject { return; }
305              
306             # Note: property read-only
307 0     0 1   sub textTracks { return( shift->_set_get_object( 'textTracks', 'HTML::Object::DOM::TextTrackList', @_ ) ); }
308              
309             # Note: property read-only
310 0     0 1   sub videoTracks { return( shift->_set_get_object( 'textTracks', 'HTML::Object::DOM::VideoTrackList', @_ ) ); }
311              
312             # Note: property
313             sub volume : lvalue { return( shift->_set_get_number({
314             field => 'volume',
315             callbacks =>
316             {
317 0     0     add => sub{ shift->_trigger_event_for( volumechange => 'HTML::Object::Event', bubbles => 0, cancellable => 0 ) },
318             }
319 0     0 1   }, @_ ) ); }
320              
321             1;
322             # NOTE: POD
323             __END__
324              
325             =encoding utf-8
326              
327             =head1 NAME
328              
329             HTML::Object::DOM::Element::Media - HTML Object DOM Media Class
330              
331             =head1 SYNOPSIS
332              
333             use HTML::Object::DOM::Element::Media;
334             my $media = HTML::Object::DOM::Element::Media->new ||
335             die( HTML::Object::DOM::Element::Media->error, "\n" );
336              
337             =head1 VERSION
338              
339             v0.2.0
340              
341             =head1 DESCRIPTION
342              
343             This interface adds to L<HTML::Object::DOM::Element> the properties and methods needed to support basic media-related capabilities that are common to L<audio|HTML::Object::DOM::Element::Audio> and L<video|HTML::Object::DOM::Element::Video>.
344              
345             =head1 INHERITANCE
346              
347             +-----------------------+ +---------------------------+ +-------------------------+ +----------------------------+ +-----------------------------------+
348             | HTML::Object::Element | --> | HTML::Object::EventTarget | --> | HTML::Object::DOM::Node | --> | HTML::Object::DOM::Element | --> | HTML::Object::DOM::Element::Media |
349             +-----------------------+ +---------------------------+ +-------------------------+ +----------------------------+ +-----------------------------------+
350              
351             =head1 PROPERTIES
352              
353             Inherits properties from its parent L<HTML::Object::DOM::Element>
354              
355             =head2 audioTracks
356              
357             A AudioTrackList that lists the AudioTrack objects contained in the element.
358              
359             Example:
360              
361             my $video = $doc->getElementById("video");
362              
363             for( my $i = 0; $i < $video->audioTracks->length; $i += 1 )
364             {
365             $video->audioTracks->[$i]->enabled = 0; # false
366             }
367              
368             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/audioTracks>
369              
370             =head2 autoplay
371              
372             A boolean value that reflects the C<autoplay> HTML attribute, indicating whether playback should automatically begin as soon as enough media is available to do so without interruption.
373              
374             Note: Automatically playing audio when the user does not expect or desire it is a poor user experience and should be avoided in most cases, though there are exceptions. See the L<Mozilla Autoplay guide for media and Web Audio APIs|https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide> for more information. Keep in mind that browsers may ignore autoplay requests, so you should ensure that your code is not dependent on C<autoplay> working.
375              
376             Example:
377              
378             <video id="video" autoplay="" controls>
379             <source src="https://player.vimeo.com/external/250688977.sd.mp4?s=d14b1f1a971dde13c79d6e436b88a6a928dfe26b&profile_id=165">
380             </video>
381              
382             # *** Disable autoplay (recommended) ***
383             # false is the default value
384             $doc->querySelector('#video')->autoplay = 0; # false
385             # <video id="video" controls>
386              
387             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/autoplay>
388              
389             =head2 buffered
390              
391             This returns C<undef> under perl.
392              
393             Normally, under JavaScript, this returns a C<TimeRanges> object that indicates the ranges of the media source that the browser has buffered (if any) at the moment the buffered property is accessed.
394              
395             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/buffered>
396              
397             =head2 controller
398              
399             This returns C<undef> under perl.
400              
401             Normally, under JavaScript, this returns a C<MediaController> object that represents the media controller assigned to the element, or C<undef> if none is assigned.
402              
403             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/controller>
404              
405             =head2 controls
406              
407             Is a boolean that reflects the controls HTML attribute, indicating whether user interface items for controlling the resource should be displayed.
408              
409             Example:
410              
411             my $obj = $doc->createElement('video');
412             $obj->controls = 1; # true
413              
414             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/controls>
415              
416             =head2 controlsList
417              
418             Returns a L<HTML::Object::TokenList> that helps the user agent select what controls to show on the media element whenever the user agent shows its own set of controls. The L<HTML::Object::TokenList> takes one or more of three possible values: C<nodownload>, C<nofullscreen>, and C<noremoteplayback>.
419              
420             Example:
421              
422             To disable the dowload button for HTML5 audio and video player:
423              
424             <audio controls controlsList="nodownload"><source src="song.mp3" type="audio/mpeg"></audio>
425              
426             <video controls controlsList="nodownload"><source src="video.mp4" type="video/mp4"></video>
427              
428             Another example:
429              
430             <video controls controlsList="nofullscreen nodownload noremoteplayback"></video>
431              
432             Using code:
433              
434             my $video = $doc->querySelector('video');
435             $video->controls; # true
436             $video->controlsList; # ["nofullscreen", "nodownload", "noremoteplayback"]
437             $video->controlsList->remove('noremoteplayback');
438             $video->controlsList; # ["nofullscreen", "nodownload"]
439             $video->getAttribute('controlsList'); # "nofullscreen nodownload"
440              
441             # Actually, under perl, 'supports' always returns true
442             $video->controlsList->supports('foo'); # false
443             $video->controlsList->supports('noremoteplayback'); # true
444              
445             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/controlsList>, L<Chromium documentation|https://developers.google.com/web/updates/2017/03/chrome-58-media-updates>
446              
447             =head2 crossOrigin
448              
449             A string indicating the CORS setting for this media element.
450              
451             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/crossOrigin>
452              
453             =head2 currentSrc
454              
455             Returns a string with the absolute URL of the chosen media resource.
456              
457             Example:
458              
459             my $obj = $doc->createElement('video');
460             say($obj->currentSrc); # ""
461              
462             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/currentSrc>
463              
464             =head2 currentTime
465              
466             This returns whatever number you set it to under perl, as a L<Module::Generic::Number> object.
467              
468             Normally, under JavaScript, this returns a double-precision floating-point value indicating the current playback time in seconds; if the media has not started to play and has not been seeked, this value is the media's initial playback time. Setting this value seeks the media to the new time. The time is specified relative to the media's timeline.
469              
470             Example:
471              
472             my $video = $doc->createElement('$video');
473             say( $video->currentTime );
474             $vide->currentTime = 35;
475              
476             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/currentTime>
477              
478             =head2 defaultMuted
479              
480             A Boolean that reflects the C<muted> HTML attribute, which indicates whether the media element's audio output should be muted by default.
481              
482             Example:
483              
484             my $video = $doc->createElement('video');
485             $video->defaultMuted = 1; # true
486             say( $video->outerHTML ); # <video muted=""></video>
487              
488             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/defaultMuted>
489              
490             =head2 defaultPlaybackRate
491              
492             This returns whatever number you set it to under perl, as a L<Module::Generic::Number> object.
493              
494             Normally, under JavaScript, this returns a double indicating the default playback rate for the media.
495              
496             Example:
497              
498             my $obj = $doc->createElement('video');
499             say($obj->defaultPlaybackRate); # 1
500              
501             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/defaultPlaybackRate>
502              
503             =head2 disableRemotePlayback
504              
505             A boolean that sets or returns the remote playback state of the HTML attribute, indicating whether the media element is allowed to have a remote playback UI.
506              
507             Example:
508              
509             my $obj = $doc->createElement('audio');
510             # <audio></audio>
511             $obj->disableRemotePlayback = 1; # true
512             # <audio disableremoteplayback=""></audio>
513              
514             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/disableRemotePlayback>
515              
516             =head2 duration
517              
518             This returns whatever number you set it to under perl, as a L<Module::Generic::Number> object.
519              
520             Normally, under JavaScript, this returns a read-only double-precision floating-point value indicating the total duration of the media in seconds. If no media data is available, the returned value is C<NaN>. If the media is of indefinite length (such as streamed live media, a WebRTC call's media, or similar), the value is C<+Infinity>.
521              
522             Example:
523              
524             my $obj = $doc->createElement('video');
525             say( $obj->duration ); # NaN
526              
527             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/duration>
528              
529             =head2 ended
530              
531             Returns a Boolean that indicates whether the media element has finished playing.
532              
533             Example:
534              
535             my $obj = $doc->createElement('video');
536             say($obj->ended); # false
537              
538             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/ended>
539              
540             =head2 error
541              
542             Read-only.
543              
544             This returns a L<HTML::Object::MediaError> object for the most recent error, or C<undef> if there has not been an error.
545              
546             Example:
547              
548             my $video = $doc->createElement('video');
549             $video->onerror = sub
550             {
551             say( "Error " . $video->error->code . "; details: " . $video->error->message );
552             }
553             $video->src = 'https://example.org/badvideo.mp4';
554              
555             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/error>
556              
557             =head2 loop
558              
559             A Boolean that reflects the C<loop> HTML attribute, which indicates whether the media element should start over when it reaches the end.
560              
561             Example:
562              
563             my $obj = $doc->createElement('video');
564             $obj->loop = 1; # true
565              
566             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/loop>
567              
568             =head2 mediaKeys
569              
570             This always returns C<undef> under perl.
571              
572             Normally, under JavaScript, this returns a L<MediaKeys object|https://developer.mozilla.org/en-US/docs/Web/API/MediaKeys> or C<undef>. L<MediaKeys|https://developer.mozilla.org/en-US/docs/Web/API/MediaKeys> is a set of keys that an associated L<HTML::Object::DOM::Element::Media> can use for decryption of media data during playback.
573              
574             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/mediaKeys>
575              
576             =head2 muted
577              
578             Is a boolean that determines whether audio is muted. true if the audio is muted and false otherwise. This does not affect the DOM.
579              
580             Example:
581              
582             my $obj = $doc->createElement('video');
583             say( $obj->muted ); # false
584              
585             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/muted>
586              
587             =head2 networkState
588              
589             Set or get an integer (enumeration) indicating the current state of fetching the media over the network.
590              
591             Example:
592              
593             <audio id="example" preload="auto">
594             <source src="sound.ogg" type="audio/ogg" />
595             </audio>
596              
597             # Export constants
598             use HTML::Object::DOM::Element::Media qw( :all );
599             my $obj = $doc->getElementById('example');
600             $obj->addEventListener( playing => sub
601             {
602             if( $obj->networkState == NETWORK_LOADING )
603             {
604             # Still loading...
605             }
606             });
607              
608             See L</CONSTANTS> below for the constants that can be exported and used.
609              
610             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/networkState>
611              
612             =head2 paused
613              
614             Returns a boolean that indicates whether the media element is paused. This is set to true if you use the L</pause> method and set to false when you use the L</play> method.
615              
616             Example:
617              
618             my $obj = $doc->createElement('video');
619             say( $obj->paused ); # true
620              
621             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/paused>
622              
623             =head2 playbackRate
624              
625             This only sets or gets a number under perl environment.
626              
627             Normally, under JavaScript, this is a double that indicates the rate at which the media is being played back.
628              
629             Example:
630              
631             my $obj = $doc->createElement('video');
632             say( $obj->playbackRate ); # Expected Output: 1
633              
634             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/playbackRate>
635              
636             =head2 played
637              
638             This always returns C<undef> under perl.
639              
640             Normally, under JavaScript, this returns a L<TimeRanges object|https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges> that contains the ranges of the media source that the browser has played, if any.
641              
642             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/played>
643              
644             =head2 preload
645              
646             Is a string that reflects the C<preload> HTML attribute, indicating what data should be preloaded, if any. Possible values are: C<none>, C<metadata>, C<auto>.
647              
648             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/preload>
649              
650             =head2 preservesPitch
651              
652             Under perl environment, this is just a boolean value you can set or get.
653              
654             Under JavaScript environment, this is a boolean that determines if the pitch of the sound will be preserved. If set to false, the pitch will adjust to the speed of the audio. This is implemented with prefixes in Firefox (C<mozPreservesPitch>) and WebKit (C<webkitPreservesPitch>).
655              
656             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/preservesPitch>
657              
658             =head2 readyState
659              
660             Set or get an integer (enumeration) indicating the readiness state of the media.
661              
662             Example:
663              
664             <audio id="example" preload="auto">
665             <source src="sound.ogg" type="audio/ogg" />
666             </audio>
667              
668             use HTML::Object::DOM::Element::Media qw( :all );
669             my $obj = $doc->getElementById('example');
670             $obj->addEventListener( loadeddata => sub
671             {
672             if( $obj->readyState >= NETWORK_LOADING )
673             {
674             $obj->play();
675             }
676             });
677              
678             See L</CONSTANTS> for the constants that can be exported and used.
679              
680             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState>
681              
682             =head2 seekable
683              
684             This always returns C<undef> under perl.
685              
686             Normally, under JavaScript, this returns a L<TimeRanges object|https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges> that contains the time ranges that the user is able to seek to, if any.
687              
688             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seekable>
689              
690             =head2 seeking
691              
692             Under perl environment, this is just a boolean value you can set or get.
693              
694             Under JavaScript environment, this is a boolean that indicates whether the media is in the process of seeking to a new position.
695              
696             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seeking>
697              
698             =head2 sinkId
699              
700             This returns C<undef> by default under perl. You can set a value using L</setSinkId>.
701              
702             Normally, under JavaScript, this returns a string that is the unique ID of the audio device delivering output, or an empty string if it is using the user agent default. This ID should be one of the C<MediaDeviceInfo.deviceid> values returned from C<MediaDevices.enumerateDevices()>, id-multimedia, or id-communications.
703              
704             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/sinkId>
705              
706             =head2 src
707              
708             Is a string that reflects the C<src> HTML attribute, which contains the URL of a media resource to use.
709              
710             Example:
711              
712             my $obj = $doc->createElement('video');
713             say( $obj->src ); # ""
714              
715             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/src>
716              
717             =head2 srcObject
718              
719             This always returns C<undef> under perl.
720              
721             Normally, under JavaScript, this is a L<MediaStream|https://developer.mozilla.org/en-US/docs/Web/API/MediaStream> representing the media to play or that has played in the current L<HTML::Object::DOM::Element::Media>, or C<undef> if not assigned.
722              
723             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/srcObject>
724              
725             =head2 textTracks
726              
727             Read-only.
728              
729             Returns the list of L<TextTrack|HTML::Object::DOM::TextTrack> objects contained in the element.
730              
731             Example:
732              
733             <video controls poster="/images/sample.gif">
734             <source src="sample.mp4" type="video/mp4">
735             <source src="sample.ogv" type="video/ogv">
736             <track kind="captions" src="sampleCaptions.vtt" srclang="en">
737             <track kind="descriptions" src="sampleDescriptions.vtt" srclang="en">
738             <track kind="chapters" src="sampleChapters.vtt" srclang="en">
739             <track kind="subtitles" src="sampleSubtitles_de.vtt" srclang="de">
740             <track kind="subtitles" src="sampleSubtitles_en.vtt" srclang="en">
741             <track kind="subtitles" src="sampleSubtitles_ja.vtt" srclang="ja">
742             <track kind="subtitles" src="sampleSubtitles_oz.vtt" srclang="oz">
743             <track kind="metadata" src="keyStage1.vtt" srclang="en" label="Key Stage 1">
744             <track kind="metadata" src="keyStage2.vtt" srclang="en" label="Key Stage 2">
745             <track kind="metadata" src="keyStage3.vtt" srclang="en" label="Key Stage 3">
746             </video>
747              
748             my $tracks = $doc->querySelector('video')->textTracks;
749              
750             # $tracks->length == 10
751             for( my $i = 0, $L = $tracks->length; $i < $L; $i++ )
752             {
753             if( $tracks->[$i]->language eq 'en' )
754             {
755             say( $tracks->[$i] );
756             }
757             }
758              
759             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/textTracks>
760              
761             =head2 videoTracks
762              
763             Read-only.
764              
765             Returns the list of L<VideoTrack|HTML::Object::DOM::VideoTrack> objects contained in the element.
766              
767             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/videoTracks>
768              
769             =head2 volume
770              
771             Is a double indicating the audio volume, from 0.0 (silent) to 1.0 (loudest).
772              
773             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/volume>
774              
775             =head1 METHODS
776              
777             Inherits methods from its parent L<HTML::Object::DOM::Element>
778              
779             =head2 addTextTrack
780              
781             Adds a L<text track|HTML::Object::DOM::TextTrack> (such as a track for subtitles) to a media element.
782              
783             This takes a track C<kind>, C<label> and C<language> and returns a new L<HTML::Object::DOM::TextTrack> object.
784              
785             Possible values for C<kind> are:
786              
787             =over 4
788              
789             =item caption
790              
791             =item chapters
792              
793             =item descriptions
794              
795             =item metadata
796              
797             =item subtitles
798              
799             =back
800              
801             C<label> is a string specifying the label for the text track. Is used to identify the text track for the users.
802              
803             C<language> in iso 639 format (e.g. C<en-US> or C<ja-JP>).
804              
805             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/addTextTrack>
806              
807             =head2 canPlayType
808              
809             This always returns C<undef> under perl.
810              
811             Normally, under JavaScript, given a string specifying a MIME media type (potentially with the codecs parameter included), C<canPlayType>() returns the string probably if the media should be playable, maybe if there's not enough information to determine whether the media will play or not, or an empty string if the media cannot be played.
812              
813             Example:
814              
815             my $obj = $doc->createElement('video');
816             say( $obj->canPlayType('video/mp4') ); # "maybe"
817              
818             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType>
819              
820             =head2 captureStream
821              
822             This always returns C<undef> under perl.
823              
824             Normally, under JavaScript, this returns C<MediaStream>, captures a stream of the media content.
825              
826             Example:
827              
828             $doc->querySelector('.playAndRecord')->addEventListener( click => sub
829             {
830             my $playbackElement = $doc->getElementById("playback");
831             my $captureStream = $playbackElement->captureStream();
832             $playbackElement->play();
833             });
834              
835             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/captureStream>
836              
837             =head2 fastSeek
838              
839             This always returns C<undef> under perl.
840              
841             Normally, under JavaScript, this quickly seeks to the given time with low precision.
842              
843             Example:
844              
845             my $myVideo = $doc->getElementById("myVideoElement");
846              
847             $myVideo->fastSeek(20);
848              
849             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/fastSeek>
850              
851             =head2 load
852              
853             This always returns C<undef> under perl.
854              
855             Normally, under JavaScript, this resets the media to the beginning and selects the best available source from the sources provided using the src attribute or the <source> element.
856              
857             Example:
858              
859             my $mediaElem = $doc->querySelector("video");
860             $mediaElem->load();
861              
862             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/load>
863              
864             =head2 pause
865              
866             Under perl, this does not do anything particular except setting the L</paused> boolean value to true.
867              
868             Pauses the media playback.
869              
870             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/pause>
871              
872             =head2 play
873              
874             This does not do anything in particular under perl, except setting the C<paused> boolean value to false.
875              
876             Normally, under JavaScript, this begins playback of the media.
877              
878             Example:
879              
880             use Nice::Try;
881             my $videoElem = $doc->getElementById( 'video' );
882             my $playButton = $doc->getElementById( 'playbutton' );
883              
884             $playButton->addEventListener( 'click', \&handlePlayButton, { capture => 0 });
885             playVideo();
886              
887             sub playVideo
888             {
889             try
890             {
891             $videoElem->play();
892             $playButton->classList->add( 'playing' );
893             }
894             catch($err)
895             {
896             $playButton->classList->remove( 'playing' );
897             }
898             }
899              
900             sub handlePlayButton
901             {
902             if( $videoElem->paused )
903             {
904             playVideo();
905             }
906             else
907             {
908             $videoElem->pause();
909             $playButton->classList->remove( 'playing' );
910             }
911             }
912              
913             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play>
914              
915             =head2 removeTextTrack
916              
917             Provided with a L<HTML::Object::DOM::TextTrack> object and this will remove it.
918              
919             It returns the L<HTML::Object::DOM::TextTrack> object upon success, or if it cannot be found, it returns C<undef>
920              
921             =head2 seekToNextFrame
922              
923             This always returns C<undef> under perl.
924              
925             Normally, under JavaScript, this seeks to the next frame in the media. This non-standard, experimental method makes it possible to manually drive reading and rendering of media at a custom speed, or to move through the media frame-by-frame to perform filtering or other operations.
926              
927             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seekToNextFrame>
928              
929             =head2 setMediaKeys
930              
931             This always returns C<undef> under perl.
932              
933             Normally, under JavaScript, this returns Promise. Sets the MediaKeys keys to use when decrypting media during playback.
934              
935             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setMediaKeys>
936              
937             =head2 setSinkId
938              
939             This does not do anything particular under perl, except setting the value of L</sinkid>.
940              
941             Normally, under JavaScript, this sets the ID of the audio device to use for output and returns a Promise. This only works when the application is authorized to use the specified device.
942              
943             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId>
944              
945             =head1 EVENTS
946              
947             =head2 abort
948              
949             This is not used under perl, but you can trigger that event yourself.
950              
951             Under JavaScript, this is fired when the resource was not fully loaded, but not as the result of an error.
952              
953             Example:
954              
955             my $video = $doc->querySelector('video');
956             my $videoSrc = 'https://example.org/path/to/video.webm';
957              
958             $video->addEventListener( abort => sub
959             {
960             say( "Abort loading: ", $videoSrc );
961             });
962              
963             my $source = $doc->createElement('source');
964             $source->setAttribute( src => $videoSrc );
965             $source->setAttribute( type => 'video/webm' );
966              
967             $video->appendChild( $source );
968              
969             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/abort_event>
970              
971             =head2 canplay
972              
973             This is not used under perl, but you can trigger that event yourself.
974              
975             Under JavaScript, this is fired when the user agent can play the media, but estimates that not enough data has been loaded to play the media up to its end without having to stop for further buffering of content
976              
977             Example:
978              
979             my $video = $doc->querySelector( 'video' );
980              
981             $video->addEventListener( canplay => sub
982             {
983             my $event = shift( @_ );
984             say( 'Video can start, but not sure it will play through.' );
985             });
986              
987             my $video = $doc->querySelector( 'video' );
988             $video->oncanplay = sub
989             {
990             my $event = shift( @_ );
991             say( 'Video can start, but not sure it will play through.' );
992             };
993              
994             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canplay_event>
995              
996             =head2 canplaythrough
997              
998             This is not used under perl, but you can trigger that event yourself.
999              
1000             Under JavaScript, this is fired when the user agent can play the media, and estimates that enough data has been loaded to play the media up to its end without having to stop for further buffering of content.
1001              
1002             Example:
1003              
1004             my $video = $doc->querySelector( 'video' );
1005              
1006             $video->addEventListener( canplaythrough => sub
1007             {
1008             my $event = shift( @_ );
1009             say( "I think I can play through the entire video without ever having to stop to buffer." );
1010             });
1011              
1012             my $video = $doc->querySelector( 'video' );
1013              
1014             $video->oncanplaythrough = sub
1015             {
1016             my $event = shift( @_ );
1017             say( "I think I can play through the entire video without ever having to stop to buffer." );
1018             };
1019              
1020             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canplaythrough_event>
1021              
1022             =head2 durationchange
1023              
1024             This is fired when the duration property has been updated.
1025              
1026             Example:
1027              
1028             my $video = $doc->querySelector('video');
1029             $video->addEventListener( durationchange => sub
1030             {
1031             say( 'Not sure why, but the duration of the $video has changed.' );
1032             });
1033              
1034             my $video = $doc->querySelector('video');
1035              
1036             $video->ondurationchange = sub
1037             {
1038             say( 'Not sure why, but the duration of the video has changed.' );
1039             };
1040              
1041             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/durationchange_event>
1042              
1043             =head2 emptied
1044              
1045             This is not used under perl, but you can trigger that event yourself.
1046              
1047             Under JavaScript, this is fired when the media has become empty; for example, when the media has already been loaded (or partially loaded), and the L<HTML::Object::DOM::Element::Media/load> method is called to reload it.
1048              
1049             Example:
1050              
1051             my $video = $doc->querySelector('video');
1052              
1053             $video->addEventListener( emptied => sub
1054             {
1055             say( 'Uh oh. The media is empty. Did you call load()?' );
1056             });
1057              
1058             my $video = $doc->querySelector('video');
1059              
1060             $video->onemptied = sub
1061             {
1062             say( 'Uh oh. The media is empty. Did you call load()?' );
1063             };
1064              
1065             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/emptied_event>
1066              
1067             =head2 ended
1068              
1069             This is not used under perl, but you can trigger that event yourself.
1070              
1071             Under JavaScript, this is fired when playback stops when end of the media (<audio> or <video>) is reached or because no further data is available.
1072              
1073             Example:
1074              
1075             my $obj = $doc->createElement('video');
1076             say( $obj->ended ); # false
1077              
1078             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/ended_event>
1079              
1080             =head2 error
1081              
1082             Fired when the resource could not be loaded due to an error.
1083              
1084             Example:
1085              
1086             my $videoElement = $doc->createElement( 'video' );
1087             $videoElement->onerror = sub
1088             {
1089             say( "Error " . $videoElement->error->code . "; details: " . $videoElement->error->message );
1090             }
1091             $videoElement->src = "https://example.org/bogusvideo.mp4";
1092              
1093             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/error_event>
1094              
1095             =head2 loadeddata
1096              
1097             This is not used under perl, but you can trigger that event yourself.
1098              
1099             Under JavaScript, this is fired when the first frame of the media has finished loading.
1100              
1101             Example:
1102              
1103             my $video = $doc->querySelector('video');
1104              
1105             $video->addEventListener( loadeddata => sub
1106             {
1107             say( 'Yay! The readyState just increased to HAVE_CURRENT_DATA or greater for the first time.' );
1108             });
1109              
1110             my $video = $doc->querySelector('video');
1111              
1112             $video->onloadeddata = sub
1113             {
1114             say( 'Yay! The readyState just increased to HAVE_CURRENT_DATA or greater for the first time.' );
1115             };
1116              
1117             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/loadeddata_event>
1118              
1119             =head2 loadedmetadata
1120              
1121             This is not used under perl, but you can trigger that event yourself.
1122              
1123             Under JavaScript, this is fired when the metadata has been loaded
1124              
1125             Example:
1126              
1127             my $video = $doc->querySelector('video');
1128              
1129             $video->addEventListener( loadedmetadata => sub
1130             {
1131             say( 'The duration and dimensions of the media and tracks are now known.' );
1132             });
1133              
1134             my $video = $doc->querySelector('video');
1135              
1136             $video->onloadedmetadata = sub
1137             {
1138             say( 'The duration and dimensions of the media and tracks are now known.' );
1139             };
1140              
1141             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/loadedmetadata_event>
1142              
1143             =head2 loadstart
1144              
1145             This is not used under perl, but you can trigger that event yourself.
1146              
1147             Under JavaScript, this is fired when the browser has started to load a resource.
1148              
1149             Example:
1150              
1151             <div class="example">
1152             <button type="button">Load video</button>
1153             <video controls width="250"></video>
1154              
1155             <div class="event-log">
1156             <label>Event log:</label>
1157             <textarea readonly class="event-log-contents"></textarea>
1158             </div>
1159             </div>
1160              
1161             use feature 'signatures';
1162             my $loadVideo = $doc->querySelector('button');
1163             my $video = $doc->querySelector('video');
1164             my $eventLog = $doc->querySelector('.event-log-contents');
1165             my $source;
1166              
1167             sub handleEvent( $event )
1168             {
1169             $eventLog->textContent = $eventLog->textContent . $event->type . "\n";
1170             }
1171              
1172             $video->addEventListener( 'loadstart', \&handleEvent);
1173             $video->addEventListener( 'progress', \&handleEvent);
1174             $video->addEventListener( 'canplay', \&handleEvent);
1175             $video->addEventListener( 'canplaythrough', \&handleEvent);
1176              
1177             $loadVideo->addEventListener( click => sub
1178             {
1179             if( $source )
1180             {
1181             $doc->location->reload();
1182             }
1183             else
1184             {
1185             $loadVideo->textContent = "Reset example";
1186             $source = $doc->createElement( 'source' );
1187             $source->setAttribute( 'src', 'https://example.org/some/where/media/examples/video.webm' );
1188             $source->setAttribute( 'type', 'video/webm' );
1189             $video->appendChild( $source );
1190             }
1191             });
1192              
1193             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/loadstart_event>
1194              
1195             =head2 pause
1196              
1197             Fired when a request to pause play is handled and the activity has entered its paused state, most commonly occurring when the media's L<HTML::Object::DOM::Element::Media/pause> method is called.
1198              
1199             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/pause_event>
1200              
1201             =head2 play
1202              
1203             Fired when the paused property is changed from true to false, as a result of the L<HTML::Object::DOM::Element::Media/play> method, or the autoplay attribute
1204              
1205             Example:
1206              
1207             use Nice::Try; # for the try{}catch block
1208             my $videoElem = $doc->getElementById( 'video' );
1209             my $playButton = $doc->getElementById( 'playbutton' );
1210              
1211             $playButton->addEventListener( click => \&handlePlayButton, { capture => 0 });
1212             playVideo();
1213              
1214             sub playVideo
1215             {
1216             try {
1217             $videoElem->play();
1218             $playButton->classList->add( 'playing' );
1219             } catch( $err ) {
1220             $playButton->classList->remove( 'playing' );
1221             }
1222             }
1223              
1224             sub handlePlayButton
1225             {
1226             if( $videoElem->paused )
1227             {
1228             playVideo();
1229             }
1230             else
1231             {
1232             $videoElem->pause();
1233             $playButton->classList->remove( 'playing' );
1234             }
1235             }
1236              
1237             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play_event>
1238              
1239             =head2 playing
1240              
1241             This is not used under perl, but you can trigger that event yourself.
1242              
1243             Under JavaScript, this is fired when playback is ready to start after having been paused or delayed due to lack of data
1244              
1245             Example:
1246              
1247             my $video = $doc->querySelector('video');
1248              
1249             $video->addEventListener( playing =>sub
1250             {
1251             say( 'Video is no longer paused' );
1252             });
1253              
1254             my $video = $doc->querySelector('video');
1255              
1256             $video->onplaying = sub
1257             {
1258             say( 'Video is no longer paused.' );
1259             };
1260              
1261             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/playing_event>
1262              
1263             =head2 progress
1264              
1265             This is not used under perl, but you can trigger that event yourself.
1266              
1267             Under JavaScript, this is fired periodically as the browser loads a resource.
1268              
1269             Example:
1270              
1271             <div class="example">
1272             <button type="button">Load video</button>
1273             <video controls width="250"></video>
1274              
1275             <div class="event-log">
1276             <label>Event log:</label>
1277             <textarea readonly class="event-log-contents"></textarea>
1278             </div>
1279             </div>
1280              
1281             use feature 'signatures';
1282             my $loadVideo = $doc->querySelector('button');
1283             my $video = $doc->querySelector('video');
1284             my $eventLog = $doc->querySelector('.event-log-contents');
1285             my $source;
1286              
1287             sub handleEvent( $event )
1288             {
1289             $eventLog->textContent = $eventLog->textContent . $event->type . "\n";
1290             }
1291              
1292             $video->addEventListener( 'loadstart', \&handleEvent );
1293             $video->addEventListener( 'progress', \&handleEvent );
1294             $video->addEventListener( 'canplay', \&handleEvent );
1295             $video->addEventListener( 'canplaythrough', \&handleEvent );
1296              
1297             $loadVideo->addEventListener( click => sub
1298             {
1299             if( $source )
1300             {
1301             $doc->location->reload();
1302             }
1303             else
1304             {
1305             $loadVideo->textContent = "Reset example";
1306             $source = $doc->createElement('source');
1307             $source->setAttribute( 'src', 'https://example.org/some/where/video.mp4' );
1308             $source->setAttribute( 'type', 'video/mp4' );
1309             $video->appendChild( $source );
1310             }
1311             });
1312              
1313             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/progress_event>
1314              
1315             =head2 ratechange
1316              
1317             This is fired when the playback rate has changed, i.e. when the property L</playbackRate> is changed.
1318              
1319             Example:
1320              
1321             my $video = $doc->querySelector( 'video' );
1322              
1323             $video->addEventListener( 'ratechange' => sub
1324             {
1325             say( 'The playback rate changed.' );
1326             });
1327              
1328             my $video = $doc->querySelector('video');
1329              
1330             $video->onratechange = sub
1331             {
1332             say( 'The playback rate changed.' );
1333             };
1334              
1335             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/ratechange_event>
1336              
1337             =head2 seeked
1338              
1339             This is not used under perl, but you can trigger that event yourself.
1340              
1341             Under JavaScript, this is fired when a seek operation completes
1342              
1343             Example:
1344              
1345             my $video = $doc->querySelector('video');
1346             $video->addEventListener( seeked => sub
1347             {
1348             say( 'Video found the playback position it was looking for.' );
1349             });
1350             my $video = $doc->querySelector( 'video' );
1351             $video->onseeked = sub
1352             {
1353             say( 'Video found the playback position it was looking for.' );
1354             };
1355              
1356             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seeked_event>
1357              
1358             =head2 seeking
1359              
1360             This is not used under perl, but you can trigger that event yourself.
1361              
1362             Under JavaScript, this is fired when a seek operation begins
1363              
1364             Example:
1365              
1366             my $video = $doc->querySelector( 'video' );
1367             $video->addEventListener( seeking => sub
1368             {
1369             say( 'Video is seeking a new position.' );
1370             });
1371             my $video = $doc->querySelector( 'video' );
1372             $video->onseeking = sub
1373             {
1374             say( 'Video is seeking a new position.' );
1375             };
1376              
1377             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seeking_event>
1378              
1379             =head2 stalled
1380              
1381             This is not used under perl, but you can trigger that event yourself.
1382              
1383             Under JavaScript, this is fired when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming.
1384              
1385             Example:
1386              
1387             my $video = $doc->querySelector('video');
1388              
1389             $video->addEventListener( stalled => sub
1390             {
1391             say( 'Failed to fetch data, but trying.' );
1392             });
1393              
1394             my $video = $doc->querySelector('video');
1395              
1396             $video->onstalled = sub
1397             {
1398             say( 'Failed to fetch data, but trying.' );
1399             };
1400              
1401             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/stalled_event>
1402              
1403             =head2 suspend
1404              
1405             This is not used under perl, but you can trigger that event yourself.
1406              
1407             Under JavaScript, this is fired when the media data loading has been suspended.
1408              
1409             Example:
1410              
1411             my $video = $doc->querySelector('video');
1412              
1413             $video->addEventListener( suspend => sub
1414             {
1415             say( 'Data loading has been suspended.' );
1416             });
1417              
1418             my $video = $doc->querySelector( 'video' );
1419              
1420             $video->onsuspend = sub
1421             {
1422             say( 'Data loading has been suspended.' );
1423             };
1424              
1425             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/suspend_event>
1426              
1427             =head2 timeupdate
1428              
1429             Fired when the time indicated by the L</currentTime> property has been updated.
1430              
1431             Example:
1432              
1433             my $video = $doc->querySelector('video');
1434              
1435             $video->addEventListener( timeupdate => sub
1436             {
1437             say( 'The currentTime attribute has been updated. Again.' );
1438             });
1439              
1440             my $video = $doc->querySelector('video');
1441              
1442             $video->ontimeupdate = sub
1443             {
1444             say( 'The currentTime attribute has been updated. Again.' );
1445             };
1446              
1447             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/timeupdate_event>
1448              
1449             =head2 volumechange
1450              
1451             Fired when the volume has changed, i.e. when the value for the L</volume> property has changed.
1452              
1453             Example:
1454              
1455             my $video = $doc->querySelector('video');
1456              
1457             $video->addEventListener( volumechange => sub
1458             {
1459             say( 'The volume changed.' );
1460             });
1461              
1462             my $video = $doc->querySelector('video');
1463             $video->onvolumechange = sub
1464             {
1465             say( 'The volume changed.' );
1466             };
1467              
1468             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/volumechange_event>
1469              
1470             =head2 waiting
1471              
1472             This is not used under perl, but you can trigger that event yourself.
1473              
1474             Under JavaScript, this is fired when playback has stopped because of a temporary lack of data.
1475              
1476             Example:
1477              
1478             my $video = $doc->querySelector('video');
1479              
1480             $video->addEventListener( waiting => sub
1481             {
1482             say( 'Video is waiting for more data.' );
1483             });
1484              
1485             my $video = $doc->querySelector('video');
1486             $video->onwaiting = sub
1487             {
1488             say( 'Video is waiting for more data.' );
1489             };
1490              
1491             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/waiting_event>
1492              
1493             =head1 EVENT HANDLERS
1494              
1495             =head2 onencrypted
1496              
1497             Sets the event handler called when the media is encrypted.
1498              
1499             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/onencrypted>
1500              
1501             =head2 onwaitingforkey
1502              
1503             Sets the event handler called when playback is blocked while waiting for an encryption key.
1504              
1505             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/onwaitingforkey>
1506              
1507             =head1 CONSTANTS
1508              
1509             The following constants can be exported and used, such as:
1510              
1511             use HTML::Object::DOM::Element::Media qw( :all );
1512             # or directly from HTML::Object::DOM
1513             use HTML::Object::DOM qw( :media );
1514              
1515             =over 4
1516              
1517             =item NETWORK_EMPTY (0)
1518              
1519             There is no data yet. Also, readyState is HAVE_NOTHING.
1520              
1521             =item NETWORK_IDLE (1)
1522              
1523             L<Media element|HTML::Object::DOM::Element::Media> is active and has selected a resource, but is not using the network.
1524              
1525             =item NETWORK_LOADING (2)
1526              
1527             The browser is downloading L<HTML::Object::DOM::Element::Media> data.
1528              
1529             =item NETWORK_NO_SOURCE (3)
1530              
1531             No L<HTML::Object::DOM::Element::Media> src found.
1532              
1533             =back
1534              
1535             =head1 AUTHOR
1536              
1537             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
1538              
1539             =head1 SEE ALSO
1540              
1541             L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement>, L<Mozilla documentation on audio element|https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio>, L<Mozilla documentation on video element|https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video>, L<W3C specifications|https://html.spec.whatwg.org/multipage/media.html>
1542              
1543             =head1 COPYRIGHT & LICENSE
1544              
1545             Copyright(c) 2021 DEGUEST Pte. Ltd.
1546              
1547             All rights reserved
1548              
1549             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
1550              
1551             =cut