@@ -360,17 +360,18 @@ function MonitorStream(monitorData) {
360
360
old_stream . remove ( ) ;
361
361
stream_container . appendChild ( stream ) ;
362
362
this . webrtc = stream ; // track separately do to api differences between video tag and video-stream
363
- this . set_stream_volume ( this . muted ? 0.0 : this . volume / 100 ) ;
364
363
if ( - 1 != this . player . indexOf ( '_' ) ) {
365
364
stream . mode = this . player . substring ( this . player . indexOf ( '_' ) + 1 ) ;
366
365
}
366
+ document . querySelector ( 'video' ) . addEventListener ( 'play' , ( e ) => {
367
+ this . createVolumeSlider ( ) ;
368
+ } , this ) ;
367
369
368
370
clearInterval ( this . statusCmdTimer ) ; // Fix for issues in Chromium when quickly hiding/showing a page. Doesn't clear statusCmdTimer when minimizing a page https://stackoverflow.com/questions/9501813/clearinterval-not-working
369
371
this . statusCmdTimer = setInterval ( this . statusCmdQuery . bind ( this ) , statusRefreshTimeout ) ;
370
372
this . started = true ;
371
373
this . streamListenerBind ( ) ;
372
374
373
- $j ( '#volumeControls' ) . show ( ) ;
374
375
if ( typeof observerMontage !== 'undefined' ) observerMontage . observe ( stream ) ;
375
376
this . activePlayer = 'go2rtc' ;
376
377
return ;
@@ -381,6 +382,9 @@ function MonitorStream(monitorData) {
381
382
382
383
if ( this . janusEnabled && ( ( ! this . player ) || ( - 1 !== this . player . indexOf ( 'janus' ) ) ) ) {
383
384
let server ;
385
+ document . querySelector ( 'video' ) . addEventListener ( 'play' , ( e ) => {
386
+ this . createVolumeSlider ( ) ;
387
+ } , this ) ;
384
388
if ( ZM_JANUS_PATH ) {
385
389
server = ZM_JANUS_PATH ;
386
390
} else if ( this . server_id && Servers [ this . server_id ] ) {
@@ -426,6 +430,9 @@ function MonitorStream(monitorData) {
426
430
const useSSL = ( url . protocol == 'https' ) ;
427
431
428
432
const rtsp2webModUrl = url ;
433
+ document . querySelector ( 'video' ) . addEventListener ( 'play' , ( e ) => {
434
+ this . createVolumeSlider ( ) ;
435
+ } , this ) ;
429
436
rtsp2webModUrl . username = '' ;
430
437
rtsp2webModUrl . password = '' ;
431
438
//.urlParts.length > 1 ? urlParts[1] : urlParts[0]; // drop the username and password for viewing
@@ -465,7 +472,6 @@ function MonitorStream(monitorData) {
465
472
this . statusCmdTimer = setInterval ( this . statusCmdQuery . bind ( this ) , statusRefreshTimeout ) ;
466
473
this . started = true ;
467
474
this . streamListenerBind ( ) ;
468
- $j ( '#volumeControls' ) . show ( ) ;
469
475
this . updateStreamInfo ( 'RTSP2Web ' + this . RTSP2WebType ) ;
470
476
return ;
471
477
} else {
@@ -762,63 +768,146 @@ function MonitorStream(monitorData) {
762
768
this . onplay = func ;
763
769
} ;
764
770
765
- this . volume_slider = null ;
766
- this . volume = 0.0 ; // Half
767
-
768
- this . setup_volume = function ( slider ) {
769
- this . volume_slider = slider ;
770
- this . volume_slider . addEventListener ( 'click' , ( e ) => {
771
- const x = e . pageX - this . volume_slider . getBoundingClientRect ( ) . left ; // or e.offsetX (less support, though)
772
- const clickedValue = parseInt ( x * this . volume_slider . max / this . volume_slider . offsetWidth ) ;
773
- this . volume_slider . value = clickedValue ;
774
- this . set_volume ( clickedValue ) ;
775
- this . muted = clickedValue ? false : true ;
776
- setCookie ( 'zmWatchMuted' , this . muted ) ;
777
- this . mute_btn . firstElementChild . innerHTML = ( this . muted ? 'volume_off' : 'volume_up' ) ;
778
- } ) ;
779
- this . volume = this . volume_slider . value ;
771
+ this . getVolumeSlider = function ( mid ) {
772
+ // On Watch page slider has no ID, on Montage page it has ID
773
+ return ( document . getElementById ( 'volumeSlider' ) ) ? document . getElementById ( 'volumeSlider' ) : document . getElementById ( 'volumeSlider' + mid ) ;
780
774
} ;
781
775
782
- /* Takes volume as 0->100 */
783
- this . set_volume = function ( volume ) {
784
- this . volume = volume ;
785
- this . set_stream_volume ( volume / 100 ) ;
786
- setCookie ( 'zmWatchVolume' , this . volume ) ;
776
+ this . getIconMute = function ( mid ) {
777
+ // On Watch page icon has no ID, on Montage page it has ID
778
+ return ( document . getElementById ( 'controlMute' ) ) ? document . getElementById ( 'controlMute' ) : document . getElementById ( 'controlMute' + mid ) ;
787
779
} ;
788
780
789
- /* Takes volume as percentage */
790
- this . set_stream_volume = function ( volume ) {
791
- if ( this . webrtc && this . webrtc . volume ) {
792
- this . webrtc . volume ( volume ) ;
793
- } else {
794
- const stream = this . getElement ( ) ;
795
- stream . volume = volume ;
781
+ this . getAudioStraem = function ( mid ) {
782
+ /*
783
+ Go2RTC uses <video-stream id='liveStreamXX'><video></video></video-stream>,
784
+ RTSP2Web uses <video id='liveStreamXX'></video>
785
+ This.getElement() may need to be changed, but the implications of such a change need to be analyzed
786
+ */
787
+ return ( document . querySelector ( '#liveStream' + mid + ' video' ) || document . getElementById ( 'liveStream' + mid ) ) ;
788
+ } ;
789
+
790
+ this . listenerVolumechange = function ( el ) {
791
+ // System audio level change
792
+ const mid = this . id ;
793
+ const audioStream = el . target ;
794
+ const volumeSlider = this . getVolumeSlider ( mid ) ;
795
+ const iconMute = this . getIconMute ( mid ) ;
796
+ if ( volumeSlider . allowSetValue ) {
797
+ if ( audioStream . muted === true ) {
798
+ iconMute . innerHTML = 'volume_off' ;
799
+ volumeSlider . classList . add ( 'noUi-mute' ) ;
800
+ } else {
801
+ iconMute . innerHTML = 'volume_up' ;
802
+ volumeSlider . classList . remove ( 'noUi-mute' ) ;
803
+ }
804
+ volumeSlider . noUiSlider . set ( audioStream . volume * 100 ) ;
796
805
}
806
+ setCookie ( 'zmWatchMuted' , audioStream . muted ) ;
807
+ setCookie ( 'zmWatchVolume' , parseInt ( audioStream . volume * 100 ) ) ;
808
+ volumeSlider . setAttribute ( 'data-muted' , audioStream . muted ) ;
809
+ volumeSlider . setAttribute ( 'data-volume' , parseInt ( audioStream . volume * 100 ) ) ;
797
810
} ;
798
811
799
- this . mute_btn = null ;
800
- this . muted = false ;
812
+ this . createVolumeSlider = function ( ) {
813
+ const mid = this . id ;
814
+ const volumeSlider = this . getVolumeSlider ( mid ) ;
815
+ const iconMute = this . getIconMute ( mid ) ;
816
+ const audioStream = this . getAudioStraem ( mid ) ;
817
+ if ( ! volumeSlider ) return ;
818
+ const defaultVolume = ( volumeSlider . getAttribute ( "data-volume" ) || 50 ) ;
819
+ if ( volumeSlider . noUiSlider ) volumeSlider . noUiSlider . destroy ( ) ;
820
+
821
+ $j ( '#volumeControls' ) . show ( ) ;
822
+ noUiSlider . create ( volumeSlider , {
823
+ start : [ ( defaultVolume ) ? defaultVolume : audioStream . volume * 100 ] ,
824
+ step : 1 ,
825
+ //behaviour: 'unconstrained',
826
+ behaviour : 'tap' ,
827
+ connect : [ true , false ] ,
828
+ range : {
829
+ 'min' : 0 ,
830
+ 'max' : 100
831
+ } ,
832
+ /*tooltips: [
833
+ //true,
834
+ { to: function(value) { return value.toFixed(0) + '%'; } }
835
+ ],*/
836
+ } ) ;
837
+ volumeSlider . allowSetValue = true ;
838
+ volumeSlider . noUiSlider . on ( 'update' , function onUpdateUiSlider ( values , handle ) {
839
+ if ( audioStream ) {
840
+ audioStream . volume = values [ 0 ] / 100 ;
841
+ if ( values [ 0 ] > 0 && ! audioStream . muted ) {
842
+ iconMute . innerHTML = 'volume_up' ;
843
+ volumeSlider . classList . remove ( 'noUi-mute' ) ;
844
+ } else {
845
+ iconMute . innerHTML = 'volume_off' ;
846
+ volumeSlider . classList . add ( 'noUi-mute' ) ;
847
+ }
848
+ }
849
+ //console.log("Audio volume slider event: 'update'");
850
+ } ) ;
851
+ volumeSlider . noUiSlider . on ( 'end' , function onEndUiSlider ( values , handle ) {
852
+ volumeSlider . allowSetValue = true ;
853
+ //console.log("Audio volume slider event: 'end'");
854
+ } ) ;
855
+ volumeSlider . noUiSlider . on ( 'start' , function onStartUiSlider ( values , handle ) {
856
+ volumeSlider . allowSetValue = false ; // Let's prohibit changing the Value using the "Set" method, otherwise there will be lags and collapse when directly moving the slider with the mouse...
857
+ //console.log("Audio volume slider event: 'start'");
858
+ } ) ;
859
+ volumeSlider . noUiSlider . on ( 'set' , function onSetUiSlider ( values , handle ) {
860
+ //console.log("Audio volume slider event: 'set'");
861
+ } ) ;
862
+ volumeSlider . noUiSlider . on ( 'slide' , function onSlideUiSlider ( values , handle ) {
863
+ if ( audioStream . volume > 0 && audioStream . muted ) {
864
+ iconMute . innerHTML = 'volume_up' ;
865
+ audioStream . muted = false ;
866
+ }
867
+ //console.log("Audio volume slider event: 'slide'");
868
+ } ) ;
801
869
802
- this . setup_mute = function ( mute_btn ) {
803
- this . mute_btn = mute_btn ;
804
- this . mute_btn . onclick = ( ) => {
805
- this . muted = ! this . muted ;
806
- setCookie ( 'zmWatchMuted' , this . muted ) ;
807
- this . mute_btn . firstElementChild . innerHTML = ( this . muted ? 'volume_off' : 'volume_up' ) ;
870
+ if ( volumeSlider . getAttribute ( "data-muted" ) !== "true" ) {
871
+ this . controlMute ( 'off' ) ;
872
+ } else {
873
+ this . controlMute ( 'on' ) ;
874
+ }
808
875
809
- if ( this . muted === false ) {
810
- this . set_stream_volume ( this . volume / 100 ) ; // lastvolume
811
- if ( this . volume_slider ) this . volume_slider . value = this . volume ;
876
+ if ( audioStream ) {
877
+ audioStream . addEventListener ( 'volumechange' , ( event ) => {
878
+ this . listenerVolumechange ( event ) ;
879
+ } ) ;
880
+ }
881
+ } ;
882
+
883
+ /*
884
+ * mode: switch, on, off
885
+ */
886
+ this . controlMute = function ( mode = 'switch' ) {
887
+ const mid = this . id ;
888
+ const volumeSlider = this . getVolumeSlider ( mid ) ;
889
+ const audioStream = this . getAudioStraem ( mid ) ;
890
+ const iconMute = this . getIconMute ( mid ) ;
891
+ if ( ! audioStream || ! iconMute ) return ;
892
+ if ( mode == 'switch' ) {
893
+ if ( audioStream . muted ) {
894
+ audioStream . muted = false ;
895
+ iconMute . innerHTML = 'volume_up' ;
896
+ volumeSlider . classList . add ( 'noUi-mute' ) ;
897
+ audioStream . volume = volumeSlider . noUiSlider . get ( ) / 100 ;
812
898
} else {
813
- this . set_stream_volume ( 0.0 ) ;
814
- if ( this . volume_slider ) this . volume_slider . value = 0 ;
899
+ audioStream . muted = true ;
900
+ iconMute . innerHTML = 'volume_off' ;
901
+ volumeSlider . classList . remove ( 'noUi-mute' ) ;
815
902
}
816
- } ;
817
- this . muted = ( this . mute_btn . firstElementChild . innerHTML == 'volume_off' ) ;
818
- if ( this . muted ) {
819
- // muted, adjust volume bar
820
- this . set_stream_volume ( 0.0 ) ;
821
- if ( this . volume_slider ) this . volume_slider . value = 0 ;
903
+ } else if ( mode == 'on' ) {
904
+ audioStream . muted = true ;
905
+ iconMute . innerHTML = 'volume_off' ;
906
+ volumeSlider . classList . add ( 'noUi-mute' ) ;
907
+ } else if ( mode == 'off' ) {
908
+ audioStream . muted = false ;
909
+ iconMute . innerHTML = 'volume_up' ;
910
+ volumeSlider . classList . remove ( 'noUi-mute' ) ;
822
911
}
823
912
} ;
824
913
0 commit comments