Prechádzať zdrojové kódy

Added media metadata support for Music on Android Chrome

TC pushbot 5 4 rokov pred
rodič
commit
9dbb911cd2
2 zmenil súbory, kde vykonal 123 pridanie a 37 odobranie
  1. 37 13
      web/Music/index.html
  2. 86 24
      web/Music/native.js

+ 37 - 13
web/Music/index.html

@@ -10,7 +10,10 @@
 	<script src="../script/tocas/tocas.js"></script>
 	<script src="../script/jquery.min.js"></script>
 	<script src="../script/ao_module.js"></script>
-	<link rel="manifest" href="manifest.json">
+	<!-- Handle native playback on Chrome Andoird-->
+	<script src="native.js"></script>
+
+	<link rel="manifest" crossorigin="use-credentials" href="manifest.json">
 	<title>AirMusic</title>
 </head>
 <body>
@@ -223,7 +226,6 @@
     </div>
     <audio id="mainAudioPlayer" style="display:none;" src=""></audio>
    
-
 	<div id="dropdownSonglist" class="dropdownMusicList" style="display:none;">
 			<div class="dropdownMusicListMiniMenu">
 				<i class="icons" style="margin-right:8px;">
@@ -365,6 +367,7 @@
 	var totalMusicCount = 0;
 	var currentPlaying = false;
 	var audioElement = $("#mainAudioPlayer");
+	var audioElementObject = document.getElementById("mainAudioPlayer"); //Directly expose the audio object
 	var playingFileDetail = []; //[id, filepath]
 	var displayList = []; //This is the list where the current UI is displaying.
 	var playingList = []; //This is the list where the player last clicked on an item to play
@@ -375,9 +378,16 @@
 	var timerRemaining = 0;
 	var playlistAddPendingFile = ""; //The filepath of the file that is pending to be added to playlist
 	var timerEndMode = "fade"; //Fade or End, Provide volume fadeout or end immediately while times up
-	var ua = "";
+	var ua =  navigator.userAgent.toLowerCase();
 	var isAndroid = ua.indexOf("android") > -1; //&& ua.indexOf("mobile");
-    
+	var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
+
+	//Embed native mediaSession for Android 
+	if (isChrome){
+		initNativeMediaPlayer();
+	}
+
+
 	//Update implementatio nof user agent detection
 	if (typeof InstallTrigger !== 'undefined'){
 		ua = "firefox";
@@ -953,13 +963,13 @@
 	}
 	
 	function updatePlaybackDisplayTime(currentTime,duration){
-	    var progress = Math.round(currentTime);
-	    var remainTime = Math.round(duration - currentTime);
+	    let progress = Math.round(currentTime);
+	    let remainTime = Math.round(duration - currentTime);
 	    $("#progressTime").text(secondsToHms(progress));
 	    if (!isNaN(remainTime)){
 	        $("#remainTime").text("-" + secondsToHms(remainTime));
 	    }
-	    
+
 	}
 	
 	function nextSongHandler(){
@@ -1096,6 +1106,7 @@
 			//This might be a file from dropdown list. use listid instead
 			id = $(object).parent().attr('listid');
 		}
+
 	    updateMiniPlayerUI(displayName,info,id);
 	    updateMainPlayerUI(displayName,info,id);
 	    loadAndPlayAudioFile(filepath, !startPaused);
@@ -1136,9 +1147,22 @@
 			if (data.error !== undefined){
 				console.log(data.error)
 				$("#albumnArtImage").attr("src","img/default.png");
+				if (isAndroid && navigator.mediaSession.metadata){
+					navigator.mediaSession.metadata.artwork = [
+						{ src: "img/default.png",   sizes: '512x512',   type: 'image/png' }
+					]
+				}
 			}else{
 				$("#albumnArtImage").attr("src","data:image/jpg;base64," + data);
+				if (isAndroid && navigator.mediaSession.metadata){
+					navigator.mediaSession.metadata.artwork = [
+						{ src: "data:image/jpg;base64," + data,   sizes: '480x480',   type: 'image/jpg' }
+					]
+				}
 			}
+
+			
+
 			resizeQuickAdjust();
 		});
 	}
@@ -1296,7 +1320,7 @@
 	        currentPlaying = false;
 	    }
 	}
-	
+
 	function loadAndPlayAudioFile(sourceURL,playAfterLoad = true){
 		var audio = audioElement;
 		sourceURL = "../" + sourceURL; //Convert absolute dir to relative
@@ -1314,7 +1338,6 @@
 		}
 		
 		loadThumbnail(sourceURL);
-        
 	}
 	
 	function updateMiniPlayerUI(displayName, fileinfo,id){
@@ -1327,6 +1350,10 @@
 	    $("#mainPlayerSongTitle").text(songname);
 	    $("#mainPlayerSongDesc").text(fileinfo);
 	    $("#mainPlayerMiniTab").text(id + "/" + totalMusicCount);
+		if (isAndroid && 'mediaSession' in navigator){
+			var infoRewrite = fileinfo.split(" / ")
+			updateTitle(songname, infoRewrite[1] + " (" + infoRewrite[0] + ")", id + "/" + totalMusicCount);
+		}
 	}
 
 	
@@ -1567,11 +1594,8 @@
 	}
 
 	function setWindowHash(hashValue){
-		
 		hashValue = JSON.stringify(hashValue);
-		if (!isAndroid){
-		    return;
-		}
+
 		if(history.pushState) {
 			window.history.pushState(null, null, '#' + hashValue);
 		}else {

+ 86 - 24
web/Music/native.js

@@ -6,30 +6,92 @@
 */
 
 //Native Media Player
-function updateTitle(){
+function initNativeMediaPlayer(){
+    var skipTime = 10;
     if ('mediaSession' in navigator) {
-        navigator.mediaSession.metadata = new MediaMetadata({
-        title: 'Unforgettable',
-        artist: 'Nat King Cole',
-        album: 'The Ultimate Collection (Remastered)',
-        artwork: [
-            { src: 'https://dummyimage.com/96x96',   sizes: '96x96',   type: 'image/png' },
-            { src: 'https://dummyimage.com/128x128', sizes: '128x128', type: 'image/png' },
-            { src: 'https://dummyimage.com/192x192', sizes: '192x192', type: 'image/png' },
-            { src: 'https://dummyimage.com/256x256', sizes: '256x256', type: 'image/png' },
-            { src: 'https://dummyimage.com/384x384', sizes: '384x384', type: 'image/png' },
-            { src: 'https://dummyimage.com/512x512', sizes: '512x512', type: 'image/png' },
-        ]
-        });
-    
-        navigator.mediaSession.setActionHandler('play', function() { /* Code excerpted. */ });
-        navigator.mediaSession.setActionHandler('pause', function() { /* Code excerpted. */ });
-        navigator.mediaSession.setActionHandler('stop', function() { /* Code excerpted. */ });
-        navigator.mediaSession.setActionHandler('seekbackward', function() { /* Code excerpted. */ });
-        navigator.mediaSession.setActionHandler('seekforward', function() { /* Code excerpted. */ });
-        navigator.mediaSession.setActionHandler('seekto', function() { /* Code excerpted. */ });
-        navigator.mediaSession.setActionHandler('previoustrack', function() { /* Code excerpted. */ });
-        navigator.mediaSession.setActionHandler('nexttrack', function() { /* Code excerpted. */ });
-        navigator.mediaSession.setActionHandler('skipad', function() { /* Code excerpted. */ });
+        navigator.mediaSession.setActionHandler('play', function() {
+            gainAudio();
+            setPlaying(true);
+        });
+        navigator.mediaSession.setActionHandler('pause', function() { 
+            originalVol = audioElement[0].volume;
+            fadeAudio();
+            setPlaying(false);
+        });
+        navigator.mediaSession.setActionHandler('stop', function() {
+            originalVol = audioElement[0].volume;
+            fadeAudio();
+            setPlaying(false);
+            audioElement[0].pause();
+            setTimeout(function(){
+                audioElement[0].volume = defaultVolumeBeforeFadeout;
+            },500);
+        });
+        navigator.mediaSession.setActionHandler('seekbackward', function() {
+            audioElementObject.currentTime = Math.max(audioElementObject.currentTime - skipTime, 0);
+            setTimeout(function(){
+                updatePositionState();
+            }, 500);
+        });
+        navigator.mediaSession.setActionHandler('seekforward', function() {
+            audioElementObject.currentTime = Math.min(audioElementObject.currentTime + skipTime, audioElementObject.duration);
+            setTimeout(function(){
+                updatePositionState();
+            }, 500);
+        });
+        navigator.mediaSession.setActionHandler('seekto', function(evt) {
+            if (evt.fastSeek && ('fastSeek' in audioElementObject)) {
+                audioElementObject.fastSeek(evt.seekTime);
+                return;
+            }
+            audioElementObject.currentTime = evt.seekTime;
+            setTimeout(function(){
+                updatePositionState();
+            }, 500);
+        });
+        navigator.mediaSession.setActionHandler('previoustrack', function() {
+            previousSong();
+        });
+        navigator.mediaSession.setActionHandler('nexttrack', function() {
+            nextSong();
+        });
     }
+}
+
+function updateTitle(title, artist, albumn){
+    if ('mediaSession' in navigator) {
+        if (navigator.mediaSession.metadata){
+            //Media Session created. Update the existsing one instead
+            navigator.mediaSession.metadata.title = title;
+            navigator.mediaSession.metadata.artist = artist;
+            navigator.mediaSession.metadata.album = albumn;
+        }else{
+            //Media Session not created. Creat one
+            navigator.mediaSession.metadata = new MediaMetadata({
+            title: title,
+            artist: artist,
+            album: albumn,
+            /*artwork: [
+                { src: artwork,   sizes: '480x480',   type: 'image/jpg' }
+            ]*/
+            });
+        }
+
+    }
+}
+
+
+function updatePositionState(currentTime, duration) {
+    if (isNaN(currentTime) || isNaN(duration)){
+        return;
+    }
+
+    if ('setPositionState' in navigator.mediaSession) {
+        navigator.mediaSession.setPositionState({
+            duration: audioElement[0].duration,
+            playbackRate: audioElement[0].playbackRate,
+            position: audioElement[0].currentTime
+        });
+    }
+
 }