embedded.html 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. <!DOCTYPE html>
  2. <meta name="apple-mobile-web-app-capable" content="yes" />
  3. <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
  4. <html>
  5. <head>
  6. <meta charset="UTF-8">
  7. <meta name="theme-color" content="#232324">
  8. <link rel="stylesheet" href="../script/semantic/semantic.min.css">
  9. <link rel="icon" type="image/png" href="./img/small_icon.png">
  10. <script src="../script/jquery.min.js"></script>
  11. <script src="../script/semantic/semantic.min.js"></script>
  12. <script src="../script/ao_module.js"></script>
  13. <style>
  14. body{
  15. padding:0px !important;
  16. overflow: hidden;
  17. height:100%;
  18. background-color: transparent !important;
  19. }
  20. .coloredBackground{
  21. background: rgb(253,255,254);
  22. background: linear-gradient(321deg, rgba(253,255,254,1) 29%, rgba(240,250,255,1) 100%);
  23. }
  24. html, body { height: 100%; width: 100%; margin: 0; }
  25. .playerInterface{
  26. background-color:rgba(226, 221, 220,0.95);
  27. height:150px !important;
  28. width:100%;
  29. }
  30. #playerUI{
  31. margin-left:0px !important;
  32. margin-right:0px !important;
  33. width:100% !important;
  34. position: relative;
  35. color: #404147;
  36. background-color: #f9f9f9 !important;
  37. overflow: hidden;
  38. }
  39. .parkLeft{
  40. position:absolute !important;
  41. top:70px;
  42. left:5px;
  43. margin-left:-30px;
  44. }
  45. .rotateNinetyDegree{
  46. -webkit-transform: rotate(-90deg);
  47. -moz-transform: rotate(-90deg);
  48. -o-transform: rotate(-90deg);
  49. -ms-transform: rotate(-90deg);
  50. transform: rotate(-90deg);
  51. }
  52. .roundbtn{
  53. border-radius: 40px !important;
  54. box-shadow: 2px 2px 2px 2px #bfbfbf;
  55. }
  56. .playBtn{
  57. color: white !important;
  58. transition: opacity 0.1s;
  59. }
  60. #playpauseBtn{
  61. width: 66px;
  62. height: 66px;
  63. }
  64. .playerControlWrapper .sidebuttons{
  65. background-color: white !important;
  66. }
  67. .playerControlWrapper .white.icon.button:hover{
  68. opacity: 0.6;
  69. }
  70. .playerControlWrapper{
  71. text-align: center;
  72. position:absolute;
  73. margin-top: 3rem;
  74. width:100% !important;
  75. }
  76. .rightPaddedOprButtons{
  77. position:absolute;
  78. right:3px;
  79. top:3px;
  80. }
  81. .modeEnabled{
  82. background-color: #186ed2 !important;
  83. color:white !important;
  84. border: 0px solid transparent !important;
  85. }
  86. #volControlOverlay{
  87. background-color: rgba(255,255,255,0.01);
  88. z-index:999;
  89. position:absolute;
  90. width:14px;
  91. height:120px;
  92. top:17px;
  93. left:28px;
  94. }
  95. .songlabel{
  96. padding-right:3px;
  97. position:absolute;
  98. display:inline-box;
  99. left:5px;
  100. top:5px;
  101. color:#77767b;
  102. height:22px;
  103. text-overflow: ellipsis;
  104. overflow: hidden;
  105. width: 100%;
  106. white-space: nowrap;
  107. font-weight: bold;
  108. }
  109. .durationDisplay{
  110. position:absolute;
  111. right:0px;
  112. bottom:0px;
  113. padding-right:5px;
  114. padding-bottom:5px;
  115. margin: 0px !important;
  116. color: #77767b;
  117. }
  118. .bottomBackground{
  119. background-color: white;
  120. position:relative;
  121. height:58px;
  122. width:100%;
  123. }
  124. .sameDirFileList{
  125. width:100%;
  126. height:calc(100% - 220px) !important;
  127. background-color:rgba(243, 243, 243, 0.95);
  128. overflow-y:auto;
  129. overflow-x:hidden;
  130. }
  131. @supports ((-webkit-backdrop-filter: blur(2em)) or (backdrop-filter: blur(2em))) {
  132. .sameDirFileList {
  133. background-color:rgba(240, 240, 240, 0.5);
  134. -webkit-backdrop-filter: blur(2em);
  135. backdrop-filter: blur(2em);
  136. }
  137. }
  138. .listitem{
  139. border-bottom: 1px solid #404040;
  140. padding: 12px;
  141. color:rgb(43, 43, 43);
  142. font-size:120%;
  143. cursor:pointer;
  144. }
  145. .listitem:hover{
  146. background-color:#eff1f3;
  147. }
  148. .listitem.selected{
  149. background-color:#eff1f3;
  150. }
  151. .noradius{
  152. border-radius: 0px !important;
  153. }
  154. </style>
  155. </head>
  156. <body>
  157. <div id="playerUI" class="playerInterface ui container">
  158. <img id="Albumnart" class="ui fluid image" src="img/nothumb.png" style="position: absolute; top: -75px; opacity: 0.3; pointer-events: none; user-select: none;">
  159. <div class="parkLeft">
  160. <div class="ui primary small progress rotateNinetyDegree" style="width:120px !important; background-color: white;">
  161. <div id="volControl" class="bar" style="min-width: 0%; width: 60%;background-color:#4576c5;"></div>
  162. </div>
  163. </div>
  164. <div id="volControlOverlay"></div>
  165. <div class="playerControlWrapper" align="center">
  166. <button class="ui white huge icon button sidebuttons roundbtn playlistStepBtn" onClick="lastSong();"><i class="step backward icon"></i></button>
  167. <button id="playpauseBtn" style="background-color:#186ed2;" class="ui white massive icon button roundbtn playBtn" onClick="togglePlay(this);"><i class="pause icon"></i></button>
  168. <button class="ui huge white icon button sidebuttons roundbtn playlistStepBtn" onClick="nextSong();"><i class="step forward icon"></i></button>
  169. </div>
  170. <div class="rightPaddedOprButtons">
  171. <button id="repeatModeBtn" class="ui icon button" style="margin-bottom:5px;" onClick="toggleRepeat(this);"><i class="retweet icon"></i></button><br>
  172. <button id="showListBtn" class="ui icon button" onClick="showRelatedFileList();"><i class="content icon"></i></button>
  173. <!-- <button class="ui icon button"><i class="exchange icon"></i></button> -->
  174. </div>
  175. <!-- Adding in some labels for the progress bars and song information-->
  176. <p class="rotateNinetyDegree" style="position:absolute;top:65px;left:8px; font-weight: lighter;"><i class="small minus icon"></i> Volume <i class="small plus icon"></i></p>
  177. <p class="durationDisplay">0:00 / 0:00</p>
  178. </div>
  179. <div id="progressControl" class="ui attached small progress" style="height: 0.8rem; background: rgba(255,255,255,0.8);">
  180. <div id="playbackProgress" class="bar" style="min-width: 0%; width: 0%;background-color: #4576c5; "></div>
  181. </div>
  182. <div class="bottomBackground" >
  183. <!-- Song Title at the bottom black area-->
  184. <div id="songtitle" class="songlabel">Loading Song Information...</div>
  185. <div id="fileSize" style="position:absolute;bottom:5px;left:5px;color:#77767b;">N/A</div>
  186. <div style="position:absolute;right:3px;bottom:3px;color:#77767b;"><i class='leaf icon'></i>AirMusic</div>
  187. </div>
  188. <!-- The sections below are for mobile interfaces -->
  189. <div id="nearbyFilelist" class="sameDirFileList">
  190. <div class="listitem" onClick="playThis(this);">N/A</div>
  191. </div>
  192. <!-- autoplay -->
  193. <audio id="mainPlayer" style="display:none;" preload="auto" autoplay></audio>
  194. <div style="display:none;">
  195. <div id="meta_dirSongList"></div>
  196. <div id="meta_playingSong"></div>
  197. </div>
  198. <script>
  199. //Define global variables
  200. var player = $("#mainPlayer")[0];
  201. var mediaExchanging = false;
  202. var listShown = true;
  203. if (ao_module_virtualDesktop){
  204. listShown = false;
  205. }else{
  206. $("#showListBtn").hide();
  207. }
  208. player.volume = getCurrentGlobVol();
  209. //Init ao_module window events
  210. ao_module_setFixedWindowSize();
  211. //Do things if it is not run under desktop mode
  212. if (!ao_module_virtualDesktop){
  213. $("#nearbyFilelist").addClass("coloredBackground");
  214. }
  215. //Ignore all other input files.
  216. var playingFileInfo = ao_module_loadInputFiles()[0];
  217. //Get the song title and meta data from server
  218. var songInfo = [];
  219. var songList = [];
  220. ao_module_agirun("Music/functions/getMeta.js", {
  221. file: encodeURIComponent(playingFileInfo.filepath)
  222. }, function(data){
  223. songList = data;
  224. for (var i = 0; i < data.length; i++){
  225. if (data[i][0] == playingFileInfo.filename){
  226. songInfo = data[i];
  227. //Set the audio element src
  228. player.src = "../media?file=" + encodeURIComponent(data[i][1]);
  229. //Update window title
  230. ao_module_setWindowTitle(data[i][0]);
  231. updatePlayerThemeAndBackground(data[i][1]);
  232. }
  233. }
  234. if (data.length == 0){
  235. //Error occured
  236. player.src = "../media?file=" + encodeURIComponent(playingFileInfo.filepath);
  237. }
  238. //Load song title into the display area
  239. updateDisplayInformation(songInfo[0],songInfo[3]);
  240. //Create the playlist for all the files in the same directory
  241. createPlayList();
  242. //Initiate the current playSong in the songList
  243. updatePlayingSongSelection();
  244. });
  245. /*
  246. $.get("../Music/getMeta?file=" + encodeURIComponent(playingFileInfo.filepath),function(data){
  247. //console.log(data);
  248. songList = data;
  249. for (var i = 0; i < data.length; i++){
  250. if (data[i][0] == playingFileInfo.filename){
  251. songInfo = data[i];
  252. //Set the audio element src
  253. player.src = "../media?file=" + encodeURIComponent(data[i][1]);
  254. //Update window title
  255. ao_module_setWindowTitle(data[i][0]);
  256. }
  257. }
  258. //Load song title into the display area
  259. updateDisplayInformation(songInfo[0],songInfo[3]);
  260. //Create the playlist for all the files in the same directory
  261. createPlayList();
  262. //Initiate the current playSong in the songList
  263. updatePlayingSongSelection();
  264. });
  265. */
  266. //Get the song title from meta data
  267. //var songInfo = JSON.parse($("#meta_playingSong").text().trim());
  268. //var songList = JSON.parse($("#meta_dirSongList").text().trim());
  269. //ao_module_setWindowTitle(ao_module_codec.decodeUmFilename(songInfo[0]));
  270. //Define supporting function for trunc.
  271. String.prototype.trunc = String.prototype.trunc ||
  272. function(n){
  273. return (this.length > n) ? this.substr(0, n-1) + '&hellip;' : this;
  274. };
  275. //Setup listen events to global volume
  276. setInterval(function(){
  277. var globvol = getCurrentGlobVol();
  278. updateVolControlDisplay(globvol);
  279. player.volume = globvol;
  280. if (player.paused == true){
  281. //Check if anytime that the button UI is not in sync with the current playing status. Update it if found.
  282. $(".playBtn").html("<i class='play icon'></i>");
  283. }else{
  284. $(".playBtn").html("<i class='pause icon'></i>");
  285. }
  286. },1000);
  287. updateVolControlDisplay(getCurrentGlobVol());
  288. //Add volume bar change event listener
  289. $("#volControlOverlay").on("click",function(e){
  290. var x = e.pageX - $('#volControlOverlay').offset().left;
  291. var y = e.pageY - $('#volControlOverlay').offset().top;
  292. var height = $('#volControlOverlay').height();
  293. var newvol = Math.round(((height - y) / height)*20)/20;
  294. localStorage.setItem("global_volume",newvol);
  295. player.volume = newvol;
  296. updateVolControlDisplay(newvol);
  297. });
  298. //Also add draging bar for mouse operations
  299. player.onended = function(){
  300. if (!repeatMode){
  301. $(".playBtn").html("<i class='play icon'></i>");
  302. }
  303. }
  304. var dragging = false;
  305. $("#volControlOverlay").on("mousedown",function(){
  306. dragging = true;
  307. });
  308. $("#volControlOverlay").on("mousemove",function(e){
  309. if (dragging){
  310. var y = e.pageY - $('#volControlOverlay').offset().top;
  311. var height = $('#volControlOverlay').height();
  312. var newvol = Math.round(((height - y) / height)*100)/100;
  313. //console.log(newvol);
  314. localStorage.setItem("global_volume",newvol);
  315. player.volume = newvol;
  316. updateVolControlDisplay(newvol);
  317. }
  318. });
  319. $("#volControlOverlay").on("mouseup",function(){
  320. if (dragging){
  321. dragging = false;
  322. }
  323. });
  324. $("body").on("mouseup",function(){
  325. if (dragging){
  326. dragging = false;
  327. }
  328. });
  329. //Audio element custom UI listeners
  330. document.getElementById("progressControl").addEventListener("click",function(e){
  331. //Click on the progress control bar, update the audio playing location
  332. var x = e.pageX - $('#progressControl').offset().left;
  333. var w = $("#progressControl").width();
  334. var alength = player.duration;
  335. var targetPos = (x / w * alength);
  336. player.currentTime = targetPos;
  337. });
  338. player.addEventListener("timeupdate", function(){
  339. var currentTime = player.currentTime;
  340. var duration = player.duration;
  341. var progressPercentage = currentTime / duration * 100 + "%";
  342. $("#playbackProgress").css("width",progressPercentage);
  343. if (!mediaExchanging){
  344. updateDurationDisplay(currentTime,duration);
  345. }
  346. });
  347. //Load repeat mode from storage
  348. var repeatMode = false;
  349. repeatMode = loadStorage("repeatModeEmbedded");
  350. if (repeatMode != ""){
  351. repeatMode = (repeatMode == "true");
  352. }
  353. if (repeatMode){
  354. $("#repeatModeBtn").addClass("modeEnabled");
  355. player.loop = true;
  356. }
  357. //End of startup seuqence
  358. function updatePlayingSongSelection(){
  359. $(".listitem.selected").removeClass("selected");
  360. $(".listitem").each(function(){
  361. if ($(this).attr("filename") == songInfo[0]){
  362. $(this).addClass("selected");
  363. }
  364. });
  365. }
  366. function showRelatedFileList(){
  367. if (ao_module_virtualDesktop){
  368. if (listShown){
  369. ao_module_setWindowSize(360,240);
  370. listShown = false;
  371. }else{
  372. ao_module_setWindowSize(360,520);
  373. listShown = true;
  374. }
  375. }
  376. }
  377. function lastSong(){
  378. //Switch to the next song in list
  379. player.pause();
  380. mediaExchanging = true;
  381. $(".durationDisplay").html('<i class="clock icon"></i> Loading Media');
  382. var nextSong = -1; //There is no next song in the current directory
  383. for (var i =0; i < songList.length; i++){
  384. if (songList[i][0] == songInfo[0]){
  385. //Filename are the same
  386. if (i-1 < 0){
  387. //This is the last song in list
  388. nextSong = songList[songList.length - 1]
  389. }else{
  390. //Play previous song
  391. nextSong = songList[i-1]
  392. }
  393. }
  394. }
  395. if (nextSong == -1){
  396. //There is no more similar file with similar extensions or there are no other supported files in the same directory.
  397. player.currentTime = 0;
  398. updateDisplayInformation(ao_module_codec.decodeUmFilename(songInfo[0]),songInfo[3]);
  399. player.play();
  400. setTimeout(function(){
  401. mediaExchanging = false;
  402. },300);
  403. return;
  404. }
  405. loadSongFromSongInfo(nextSong);
  406. player.play();
  407. setTimeout(function(){
  408. mediaExchanging = false;
  409. },300);
  410. updatePlayingSongSelection();
  411. }
  412. function uuidv4() {
  413. return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
  414. (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  415. );
  416. }
  417. function createPlayList(){
  418. $(".sameDirFileList").html("");
  419. for (var i = 0; i < songList.length; i++){
  420. //console.log(box);
  421. let thisFileItemID = "thumb_" + uuidv4();
  422. $(".sameDirFileList").append(`<div class="listitem" filename="${songList[i][0]}" onClick="playThis(this);">
  423. <div class="ui unstackable grid">
  424. <div class="three wide column" align="right">
  425. <img id="${thisFileItemID}" class="ui image noradius" style="height: 2rem;" src="img/eq.svg">
  426. </div>
  427. <div class="thirteen wide column">
  428. ${ao_module_codec.decodeUmFilename(songList[i][0])} (${songList[i][3]})
  429. </div>
  430. </div>
  431. </div>`);
  432. ao_module_agirun("Music/functions/getThumbnail.js", {
  433. file: songList[i][1],
  434. }, function(data){
  435. if (data.error !== undefined){
  436. }else{
  437. $("#" + thisFileItemID).attr("src","data:image/jpg;base64," + data);
  438. }
  439. });
  440. }
  441. }
  442. function playThis(object){
  443. var songName = $(object).attr("filename");
  444. $(".listitem.selected").removeClass("selected");
  445. $(object).addClass("selected");
  446. for (var i =0; i < songList.length; i++){
  447. if (songList[i][0] == songName){
  448. //This is the song that the user request to play.
  449. player.pause();
  450. mediaExchanging = true;
  451. $(".durationDisplay").html('<i class="clock icon"></i> Loading Media');
  452. loadSongFromSongInfo(songList[i]);
  453. player.play();
  454. setTimeout(function(){
  455. mediaExchanging = false;
  456. },300);
  457. break;
  458. }
  459. }
  460. }
  461. function nextSong(){
  462. //Switch to the next song in list
  463. player.pause();
  464. mediaExchanging = true;
  465. $(".durationDisplay").html('<i class="clock icon"></i> Loading Media');
  466. var nextSong = -1; //There is no next song in the current directory
  467. for (var i =0; i < songList.length; i++){
  468. if (songList[i][0] == songInfo[0]){
  469. //Filename are the same
  470. if (i+1 >= songList.length){
  471. //This is the last song in list
  472. nextSong = songList[0]
  473. }else{
  474. //Play next song
  475. nextSong = songList[i+1]
  476. }
  477. }
  478. }
  479. if (nextSong == -1){
  480. //There is no more similar file with similar extensions or there are no other supported files in the same directory.
  481. player.currentTime = 0;
  482. updateDisplayInformation(ao_module_codec.decodeUmFilename(songInfo[0]), songInfo[3]);
  483. player.play();
  484. setTimeout(function(){
  485. mediaExchanging = false;
  486. },300);
  487. return;
  488. }
  489. loadSongFromSongInfo(nextSong);
  490. player.play();
  491. setTimeout(function(){
  492. mediaExchanging = false;
  493. },300);
  494. updatePlayingSongSelection();
  495. }
  496. function blobToDataURL(blob, callback) {
  497. var a = new FileReader();
  498. a.onload = function(e) {callback(e.target.result);}
  499. a.readAsDataURL(blob);
  500. }
  501. function loadSongFromSongInfo(playSongInfo){
  502. var songName = ao_module_codec.decodeUmFilename(playSongInfo[0]);
  503. var songPath = playSongInfo[1];
  504. var fileSize = playSongInfo[3];
  505. $(player).attr('src',"/media?file=" + encodeURIComponent(songPath));
  506. ao_module_setWindowTitle(songName);
  507. songInfo = playSongInfo;
  508. updateDisplayInformation(ao_module_codec.decodeUmFilename(songInfo[0]),songInfo[3]);
  509. updatePlayerThemeAndBackground(songPath);
  510. }
  511. //Update the player background and theme color
  512. function updatePlayerThemeAndBackground(songPath){
  513. ao_module_agirun("Music/functions/getThumbnail.js", {
  514. file: songPath,
  515. }, function(data){
  516. if (data.error == undefined){
  517. let imageSrc = "data:image/jpg;base64," + data;
  518. $("#Albumnart").attr("src",imageSrc);
  519. //Get theme color and update the player theme color
  520. let themeColor = getAverageRGB($("#Albumnart")[0]);
  521. updateThemeColor(themeColor);
  522. }else{
  523. //No thumbnail. Restore to default theme color
  524. updateThemeColor({r:24, g: 110, b: 210});
  525. $("#Albumnart").attr("src","img/nothumb.png");
  526. }
  527. }
  528. );
  529. }
  530. //Update the theme color, require something like { r: 231, g: 159, b: 140 }
  531. function updateThemeColor(newRGBColor){
  532. let colorText = `rgb(${newRGBColor.r} ,${newRGBColor.g} ,${newRGBColor.b})`
  533. $("#playbackProgress").css("background-color", colorText);
  534. $("#playpauseBtn").css("background-color", colorText);
  535. $("#volControl").css("background-color", colorText);
  536. $(".modeEnabled")[0].style.setProperty( "background-color", colorText, 'important' );
  537. //$(".sameDirFileList").css("background-color", `rgba(${newRGBColor.r}, ${newRGBColor.g}, ${newRGBColor.b}, 0.1)`);
  538. }
  539. function updateDisplayInformation(songname, filesize){
  540. $("#songtitle").html("<i class='music icon'></i>" + songname)
  541. $("#fileSize").html("<i class='file outline icon'></i> " + filesize);
  542. }
  543. function updateDurationDisplay(pos,dur){
  544. pos = secondsToHMS(pos);
  545. dur = secondsToHMS(dur);
  546. $(".durationDisplay").html(pos.trim() + " / " + dur.trim());
  547. }
  548. function secondsToHMS(sec){
  549. let totalSeconds = sec;
  550. let hours = Math.floor(totalSeconds / 3600);
  551. totalSeconds %= 3600;
  552. let minutes = Math.floor(totalSeconds / 60);
  553. let seconds = totalSeconds % 60;
  554. if (hours > 0){
  555. hours = String(hours).padStart(2, "0");
  556. }else{
  557. hours = 0;
  558. }
  559. seconds = Math.round(seconds);
  560. minutes = String(minutes).padStart(2, "0");
  561. seconds = String(seconds).padStart(2, "0");
  562. if (hours != 0){
  563. return hours + ":" + minutes + ":" + seconds;
  564. }else{
  565. return minutes + ":" + seconds;
  566. }
  567. }
  568. function togglePlay(object){
  569. if (player.paused == true){
  570. player.play();
  571. $(object).html("<i class='pause icon'></i>");
  572. }else{
  573. player.pause();
  574. $(object).html("<i class='play icon'></i>");
  575. }
  576. }
  577. function toggleRepeat(object){
  578. if ($(object).hasClass("modeEnabled")){
  579. $(object).removeClass("modeEnabled");
  580. repeatMode = false;
  581. setStorage("repeatModeEmbedded","false");
  582. player.loop = false;
  583. }else{
  584. $(object).addClass("modeEnabled");
  585. repeatMode = true;
  586. setStorage("repeatModeEmbedded","true");player.loop = true;
  587. }
  588. }
  589. function updateVolControlDisplay(percentage){
  590. var adjWidth = percentage * 100 + "%";
  591. $("#volControl").css("width",adjWidth);
  592. $("#volControl").attr("vol",percentage);
  593. }
  594. function getCurrentGlobVol(){
  595. //console.log(localStorage.getItem("global_volume"));
  596. if (localStorage.getItem("global_volume") === null || localStorage.getItem("global_volume") == ""){
  597. return 0;
  598. }
  599. return parseFloat(localStorage.getItem("global_volume"));
  600. }
  601. function setStorage(configName,configValue){
  602. $.ajax({
  603. type: 'GET',
  604. url: "/system/file_system/preference",
  605. data: {key: "Music/" + configName,value:configValue},
  606. success: function(data){},
  607. async:true
  608. });
  609. return true;
  610. }
  611. function loadStorage(configName){
  612. var result = "";
  613. $.ajax({
  614. type: 'GET',
  615. url: "/system/file_system/preference",
  616. data: {key: "Music/" + configName},
  617. success: function(data){
  618. if (data.error !== undefined){
  619. result = "";
  620. }else{
  621. result = data;
  622. }
  623. },
  624. error: function(data){result = "";},
  625. async:false,
  626. timeout: 3000
  627. });
  628. return result;
  629. }
  630. function getAverageRGB(imgEl) {
  631. var blockSize = 5,
  632. defaultRGB = {r:0,g:0,b:0},
  633. canvas = document.createElement('canvas'),
  634. context = canvas.getContext && canvas.getContext('2d'),
  635. data, width, height,
  636. i = -4,
  637. length,
  638. rgb = {r:0,g:0,b:0},
  639. count = 0;
  640. if (!context) {
  641. return defaultRGB;
  642. }
  643. height = canvas.height = imgEl.naturalHeight || imgEl.offsetHeight || imgEl.height;
  644. width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;
  645. context.drawImage(imgEl, 0, 0);
  646. try {
  647. data = context.getImageData(0, 0, width, height);
  648. } catch(e) {
  649. /* security error, img on diff domain */
  650. return defaultRGB;
  651. }
  652. length = data.data.length;
  653. while ( (i += blockSize * 4) < length ) {
  654. ++count;
  655. rgb.r += data.data[i];
  656. rgb.g += data.data[i+1];
  657. rgb.b += data.data[i+2];
  658. }
  659. // ~~ used to floor values
  660. rgb.r = ~~(rgb.r/count);
  661. rgb.g = ~~(rgb.g/count);
  662. rgb.b = ~~(rgb.b/count);
  663. return rgb;
  664. }
  665. </script>
  666. </body>
  667. </html>