index.html 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. <html>
  2. <head>
  3. <meta name="apple-mobile-web-app-capable" content="yes" />
  4. <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
  5. <link rel="stylesheet" href="../script/tocas/tocas.css">
  6. <link rel="stylesheet" href="../script/semantic/semantic.css">
  7. <script src="jquery.min.js"></script>
  8. <script src="../script/semantic/semantic.js"></script>
  9. <script src="../script/ao_module.js"></script>
  10. <title>FFmpeg Factory</title>
  11. <style>
  12. .FFmpegStatus{
  13. padding:8px;
  14. border-bottom:1px solid #999999;
  15. }
  16. body{
  17. padding-top:0px !important;
  18. background-color:white;
  19. overflow:hidden;
  20. }
  21. @supports (backdrop-filter: none) {
  22. body {
  23. background: rgba(255, 255, 255, 0.9);
  24. backdrop-filter: blur(8px);
  25. }
  26. }
  27. .topMenu{
  28. padding-top:0px !important;
  29. border-bottom: 1px solid #999999;
  30. height: 40px;
  31. overflow-x: auto;
  32. overflow-y: hidden;
  33. }
  34. .selectableMenuItems{
  35. padding: 8px;
  36. display:inline-block !important;
  37. cursor:pointer;
  38. border-bottom:2px solid transparent;
  39. }
  40. .selectableMenuItems.enabled:hover{
  41. background-color:#f0f0f0;
  42. }
  43. .convertionList{
  44. width:100%;
  45. height: 100%;
  46. padding-left:8px;
  47. border-right: 1px solid #cfcfcf;
  48. overflow-y:auto;
  49. }
  50. .selectable{
  51. cursor:pointer;
  52. padding-left: 22px !important;
  53. border:1px solid transparent;
  54. }
  55. .selectable.item{
  56. padding:8x !important;
  57. }
  58. .selectable:hover{
  59. background-color:#f0f0f0;
  60. }
  61. .content{
  62. overflow-y: auto;
  63. }
  64. .filelist{
  65. padding: 12px !important;
  66. padding-bottom:0px !important;
  67. margin-right:20px;
  68. border: 1px solid transparent !important;
  69. cursor: pointer;
  70. }
  71. .filelist:hover{
  72. background-color:#f0fbff;
  73. border:1px solid #48b8e5 !important;
  74. }
  75. .selectedFile{
  76. background-color:#e0f7ff;
  77. border:1px solid #48b8e5 !important;
  78. }
  79. .selectedConvertTarget{
  80. background-color:#f0f0f0;
  81. border:1px solid #999999 !important;
  82. }
  83. .status{
  84. display:inline;
  85. }
  86. .selectableMenuItems.disabled{
  87. color: #a3a3a3;
  88. cursor: not-allowed !important;
  89. }
  90. .converting{
  91. background-color:#d3e4ff;
  92. }
  93. .done{
  94. background-color:#d1ffd3;
  95. }
  96. .failed{
  97. background-color: #ffd1d1;
  98. }
  99. #settingMenu{
  100. position:fixed;
  101. left:30px;
  102. right:30px;
  103. top:30px;
  104. max-height:80%;
  105. }
  106. .mainArea{
  107. margin-top:0px !important;
  108. }
  109. .ts.progress{
  110. margin-bottom:18px !important;
  111. }
  112. .ts.blue.progress .bar{
  113. background-color: #2185d0 !important;
  114. }
  115. #convertPendingList{
  116. overflow-y: scroll;
  117. }
  118. </style>
  119. </head>
  120. <body>
  121. <div id="headerNav" class="ui secondary attached mini menu">
  122. <a class="item" href="../"><i class="caret left icon"></i></a>
  123. <div class="item">
  124. <img class="ui avatar image" src="./img/small_icon.png">
  125. <span>FFmpeg Factory</span>
  126. </div>
  127. </div>
  128. <div class="topMenu">
  129. <div id="addFileBtn" class="selectableMenuItems enabled" onClick="openFileSelection(this);"><i class="plus icon"></i>Add Files</div>
  130. <div class="selectableMenuItems enabled" onClick="openFileLocation(this);"><i class="folder open icon"></i>Browse File Location</div>
  131. <div class="selectableMenuItems enabled" onClick="startQueue(this);"><i class="play icon"></i>Start Queue</div>
  132. <div class="selectableMenuItems enabled" onClick="stopQueue(this);"><i class="stop icon"></i>Stop Queue</div>
  133. <!-- <div class="selectableMenuItems enabled" onClick="viewCommand(this);"><i class="code icon"></i>View Command</div> -->
  134. <div class="selectableMenuItems enabled" onClick="showSettingMenu(this);"><i class="setting icon"></i>Settings</div>
  135. </div>
  136. <div class="ui stackable grid mainArea">
  137. <div class="four wide column sidebar">
  138. <div class="convertionList" >
  139. <div class="ui fluid accordion">
  140. <div class="title">
  141. <i class="dropdown icon"></i>
  142. <i class="play icon"></i>
  143. Video
  144. </div>
  145. <div class="content fileFormatSelector">
  146. <div id="v2v" class="ui relaxed divided list">
  147. </div>
  148. </div>
  149. <div class="title">
  150. <i class="dropdown icon"></i>
  151. <i class="music icon"></i>
  152. Music
  153. </div>
  154. <div class="content fileFormatSelector">
  155. <div id="v2a" class="ui relaxed divided list">
  156. </div>
  157. </div>
  158. <div class="title">
  159. <i class="dropdown icon"></i>
  160. <i class="file image icon"></i>
  161. Pictures
  162. </div>
  163. <div class="content fileFormatSelector">
  164. <div id="i2i" class="ui relaxed divided list">
  165. </div>
  166. </div>
  167. <div class="title">
  168. <i class="dropdown icon"></i>
  169. <i class="exchange icon"></i>
  170. Others
  171. </div>
  172. <div class="content fileFormatSelector">
  173. <div id="other" class="ui relaxed divided list">
  174. </div>
  175. </div>
  176. </div>
  177. <br>
  178. </div>
  179. </div>
  180. <div class="twelve wide column" ondrop="drop(event)" ondragover="allowdrag(event)" style="padding-right:22px;">
  181. <div id="actionOK" class="ui positive message transition" style="display:none;">
  182. <div class="header">
  183. You are eligible for a reward
  184. </div>
  185. <p class="message"></p>
  186. </div>
  187. <div id="emptylist" class="ui secondary blue segment">
  188. <i class="hashtag icon"></i> No Pending Tasks. Press the <i class="add icon"></i> button to add new conversion tasks.
  189. </div>
  190. <div id="convertPendingList" class="ui relaxed divided list" style="margin-top:0px !important;">
  191. </div>
  192. <div id="askSelectDimmer" class="ui dimmer" style="margin-top:14px; margin-left:-14px;">
  193. <div class="content">
  194. <h4 class="ui inverted icon header">
  195. <i class="arrow left icon"></i>
  196. Select a Target Conversion Format <br>
  197. On the list over there
  198. </h4>
  199. </div>
  200. </div>
  201. </div>
  202. </div>
  203. <div id="settingDimmer" class="ui dimmer"></div>
  204. <div id="settingMenu" style="z-index:1001;">
  205. <div class="ui raised segment">
  206. <div class="ui header">
  207. <i class="setting icon"></i>Conversion Settings
  208. <div class="sub header">Please adjust the following settings according to your Host devices specification.</div>
  209. </div>
  210. <div class="ui list">
  211. <div class="item"><i class="caret right icon"></i>Simultaneous Conversion File Counts</div>
  212. <div class="item">
  213. <select id="simFileCount" class="ui basic tiny dropdown" onChange="updateSimFiles(this);">
  214. <option>1</option>
  215. <option>2</option>
  216. <option>3</option>
  217. <option>4</option>
  218. <option>8</option>
  219. <option>16</option>
  220. </select>
  221. </div>
  222. <div class="item" style="font-size: 90%;"><small>Do not use "ALL" options unless your host is a dual CPU Xeon Server</small></div>
  223. <div class="item"><i class="caret right icon"></i>Allow Codec Copy Options (FFmpeg Expert Only)</div>
  224. <div class="item" onChange="">
  225. <select id="allowCodecCopy" class="ui basic tiny dropdown" onChange="updateAllowCodecCopy(this);">
  226. <option>false</option>
  227. <option>true</option>
  228. </select>
  229. </div>
  230. <div class="item" style="font-size: 90%;"><small>Codec Copy Error might crash the system. Please use with your own risk.</small></div>
  231. </div>
  232. <br><br>
  233. <ins><i class="save icon"></i>All changes will be saved automatically in server database.</ins>
  234. <br> <br>
  235. <button class="ui blue button" onClick="hideSettingMenu();">Close</button>
  236. </div>
  237. </div>
  238. <br><br><br><br>
  239. <script>
  240. //Global variables
  241. var convertPendingFiles = []; //Files pending to be converted
  242. var selectFormatPending = false; //Files selected and waiting to select a target format
  243. var targetConversionFormat = ""; //The target conversion format
  244. var selectedCommand = ""; //The target selected command template
  245. var selectedMediaType = "";
  246. //Conversion related settings
  247. var simFileCount = 1;
  248. var allowCodecCopy = false;
  249. var queueStarted = false;
  250. isMobile = function() {
  251. let check = false;
  252. (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
  253. return check;
  254. };
  255. if (ao_module_virtualDesktop){
  256. $("#headerNav").hide();
  257. }
  258. $(document).ready(function(){
  259. //Check if mobile. If yes, change the UI to responsive
  260. if (isMobile()){
  261. //Create a sidebar button
  262. $(".topMenu").prepend(`
  263. <div title="Toggle Sidebar" class="ui icon button" onclick="toggleSidebar(); "><i class="content icon" style="pointer-events: none;" ></i></div>
  264. `);
  265. //Hide the sidebar
  266. $(".sidebar").hide();
  267. //Simplify the toolbar
  268. $(".selectableMenuItems").each(function(){
  269. var originalText = $(this).text();
  270. console.log(originalText);
  271. $(this).html($(this).html().replace(originalText, ""));
  272. $(this).attr("title", originalText);
  273. $(this).attr("class", "ui basic icon button")
  274. $(this).css({
  275. "padding-top": "12px"
  276. });
  277. });
  278. }
  279. $("#settingMenu").hide();
  280. $('.ui.dropdown').dropdown();
  281. //Initialize the conversion types
  282. //<div class="item selectable"><i class="file video outline icon"></i></div>
  283. $.ajax({
  284. url: "config/v2v.json",
  285. method: "GET",
  286. dataType: "json",
  287. success: function(data){
  288. for (var [key, value] of Object.entries(data)) {
  289. value = encodeURIComponent(value);
  290. $("#v2v").append(`<div class="item selectable" mediatype="video" conv="${key}" command="${value}" onclick="selectThis(this, event);" ondblclick="selectViaFormat(this);"><i class="file video outline icon"></i> ${key}</div>`);
  291. }
  292. $('.ui.accordion').accordion();
  293. initUserSettings();
  294. }
  295. });
  296. $.ajax({
  297. url: "config/v2a.json",
  298. method: "GET",
  299. dataType: "json",
  300. success: function(data){
  301. for (var [key, value] of Object.entries(data)) {
  302. value = encodeURIComponent(value);
  303. $("#v2a").append(`<div class="item selectable" mediatype="music" conv="${key}" command="${value}" onclick="selectThis(this, event);" ondblclick="selectViaFormat(this);"><i class="file video outline icon"></i> ${key}</div>`);
  304. }
  305. $('.ui.accordion').accordion();
  306. initUserSettings();
  307. }
  308. });
  309. $.ajax({
  310. url: "config/i2i.json",
  311. method: "GET",
  312. dataType: "json",
  313. success: function(data){
  314. for (var [key, value] of Object.entries(data)) {
  315. value = encodeURIComponent(value);
  316. $("#i2i").append(`<div class="item selectable" mediatype="image" conv="${key}" command="${value}" onclick="selectThis(this, event);" ondblclick="selectViaFormat(this);"><i class="file video outline icon"></i> ${key}</div>`);
  317. }
  318. $('.ui.accordion').accordion();
  319. }
  320. });
  321. $.ajax({
  322. url: "config/other.json",
  323. method: "GET",
  324. dataType: "json",
  325. success: function(data){
  326. for (var [key, value] of Object.entries(data)) {
  327. value = encodeURIComponent(value);
  328. $("#other").append(`<div class="item selectable" mediatype="other" conv="${key}" command="${value}" onclick="selectThis(this, event);" ondblclick="selectViaFormat(this);"><i class="file video outline icon"></i> ${key}</div>`);
  329. }
  330. $('.ui.accordion').accordion();
  331. }
  332. });
  333. });
  334. //Open files to convert
  335. function openFileSelection(obj){
  336. if ($(obj).hasClass("disabled") == false){
  337. //Require format selection after select
  338. selectFormatPending = true;
  339. ao_module_openFileSelector(fileSelected, "user:/Desktop", "file",true);
  340. }
  341. }
  342. function toggleSidebar(){
  343. $(".sidebar").toggle();
  344. }
  345. //Catch drop events on ths main area
  346. function drop(event){
  347. event.preventDefault();
  348. var files = ao_module_utils.getDropFileInfo(event);
  349. if(files.length == 0){
  350. return;
  351. }
  352. selectFormatPending = true;
  353. fileSelected(files);
  354. }
  355. function allowdrag(ev) {
  356. ev.preventDefault();
  357. return true;
  358. }
  359. //Update the number of simultanous file conversion
  360. function updateSimFiles(obj){
  361. var fileNumber = obj.value;
  362. saveStorage("simconv",fileNumber);
  363. simFileCount = fileNumber;
  364. }
  365. function updateAllowCodecCopy(obj){
  366. var newValue = obj.value;
  367. allowCodecCopy = (newValue == "true");
  368. saveStorage("codecCopy",newValue);
  369. updateCodeCopyDisableList();
  370. }
  371. function initUserSettings(){
  372. readStorage("simconv", function(data){
  373. if (data != ""){
  374. simFileCount = parseInt(data);
  375. $('#simFileCount').dropdown('set selected', data);
  376. }
  377. });
  378. readStorage("codecCopy", function(data){
  379. if (data != ""){
  380. allowCodecCopy = (data == "true");
  381. $('#allowCodecCopy').dropdown('set selected', data);
  382. }
  383. updateCodeCopyDisableList();
  384. });
  385. }
  386. function updateCodeCopyDisableList(){
  387. //console.log(allowCodecCopy);
  388. if (allowCodecCopy == false){
  389. $(".item.selectable").each(function(){
  390. if ($(this).text().includes("codec copy")){
  391. $(this).addClass("disabled");
  392. }
  393. });
  394. }else{
  395. $(".item.selectable.disabled").each(function(){
  396. $(this).removeClass("disabled");
  397. });
  398. }
  399. }
  400. function saveStorage(key, value, callback = undefined){
  401. ao_module_agirun("FFmpeg Factory/backend/writeConfig.js", {
  402. key: key,
  403. value: value
  404. }, callback)
  405. }
  406. function readStorage(key, callback = undefined){
  407. ao_module_agirun("FFmpeg Factory/backend/readConfig.js", {key: key}, callback)
  408. }
  409. function selectThisTask(obj){
  410. $(".selectedFile").removeClass("selectedFile");
  411. $(obj).addClass("selectedFile")
  412. }
  413. //File selected using openFileSelected
  414. function fileSelected(data){
  415. convertPendingFiles = data;
  416. if (selectFormatPending == true){
  417. //Format not yet selected. Ask user to choose a target format
  418. $("#askSelectDimmer").addClass('active');
  419. $(".selectableMenuItems").addClass("disabled")
  420. if (isMobile()){
  421. $(".sidebar").show();
  422. }
  423. }else{
  424. //format alraedy selected. Append to conversion list
  425. for (var i =0; i < data.length; i++){
  426. var thisFile = convertPendingFiles[i];
  427. addTaskToList(thisFile.filename, thisFile.filepath, targetConversionFormat, selectedCommand, selectedMediaType);
  428. }
  429. targetConversionFormat="";
  430. selectedCommand="";
  431. selectedMediaType="";
  432. }
  433. }
  434. function showSettingMenu(){
  435. $("#settingDimmer").addClass("active");
  436. $("#settingMenu").transition('scale');
  437. }
  438. function hideSettingMenu(){
  439. $("#settingDimmer").removeClass("active");
  440. $("#settingMenu").transition('scale');
  441. }
  442. //Remove task from the task list
  443. function removeTask(obj){
  444. var taskObject = $(obj).parent().parent().parent();
  445. //msgbox("Task Removed", $(taskObject).attr("filepath"));
  446. $(taskObject).remove();
  447. //Check if there are anything left. If no, add a message
  448. if ($(".filelist.item").length == 0){
  449. $("#emptylist").show();
  450. }
  451. }
  452. function msgbox(title, message){
  453. $("#actionOK").stop().finish().slideDown("fast").delay(3000).slideUp("fast");
  454. $("#actionOK").find(".header").text(title);
  455. $("#actionOK").find(".message").text(message);
  456. }
  457. function addTaskToList(filename, filepath, targetFormat, command, mtype){
  458. $("#emptylist").hide();
  459. //Get the file extension of the filename
  460. var srcFormat = filename.split(".").pop();
  461. srcFormat = srcFormat.toUpperCase();
  462. console.log(filename, filepath, targetFormat, command, mtype);
  463. $("#convertPendingList").append(`<div class="item filelist ready" mtype="${mtype}" filepath="${filepath}" command="${command}" onclick="selectThisTask(this);">
  464. <i class="large file outline middle aligned icon"></i>
  465. <div class="content">
  466. <div class="header">${filename} [${srcFormat} <i class="right arrow icon"></i>${targetFormat}]</div>
  467. <div class="description" style="margin-top:8px;"><a onclick="startTask(this, event);" class="startTaskButton"><i class="exchange icon"></i> Start Convert</a> / <a onclick="removeTask(this);"><i class="trash icon"></i> Remove</a>
  468. </div>
  469. </div>
  470. <div class="ts black active tiny progress" style="margin-top:8px;">
  471. <div class="bar" style="width:0%; min-width:0px;"></div>
  472. </div>
  473. </div>`);
  474. }
  475. function selectViaFormat(obj){
  476. targetConversionFormat = $(obj).attr("conv");
  477. selectedCommand = $(obj).attr("command");
  478. selectedMediaType = $(obj).attr("mediatype");
  479. ao_module_openFileSelector(fileSelected, "user:/Desktop", "file",true);
  480. }
  481. function selectThis(obj){
  482. //A format has been selected
  483. if (selectFormatPending){
  484. //Unset the blocking
  485. $("#askSelectDimmer").removeClass('active');
  486. $(".selectableMenuItems").removeClass("disabled")
  487. //Hide the sidebar if on mobile mode
  488. if (isMobile()){
  489. $('.sidebar').hide();
  490. }
  491. //Get the target format and command
  492. var format = $(obj).attr("conv");
  493. var command = $(obj).attr("command");
  494. var mtype = $(obj).attr("mediatype");
  495. //Append the files item to list
  496. for (var i =0; i < convertPendingFiles.length; i++){
  497. var thisFile = convertPendingFiles[i];
  498. addTaskToList(thisFile.filename, thisFile.filepath, format, command, mtype);
  499. }
  500. selectFormatPending = false;
  501. }
  502. }
  503. function openFileLocation(){
  504. if ($(".selectedFile").length > 0){
  505. var filepath = $(".selectedFile").attr("filepath");
  506. filepath = filepath.split("/");
  507. filepath.pop();
  508. filepath = filepath.join("/")
  509. ao_module_openPath(filepath);
  510. }
  511. }
  512. //Handle window resize events
  513. resizeWindowEvents()
  514. $(window).on("resize",function(){
  515. resizeWindowEvents();
  516. })
  517. function resizeWindowEvents(){
  518. $(".sidebar").css("height",window.innerHeight - $(".topMenu").height());
  519. $("#convertPendingList").css("height", window.innerHeight - 60);
  520. }
  521. //Bind the queue listening events
  522. setInterval(function(){
  523. if (queueStarted){
  524. //Check next queue
  525. if (isNaN(simFileCount)){
  526. simFileCount = 1;
  527. }
  528. if ($(".filelist.converting").length < simFileCount){
  529. //Convert next item
  530. console.log("Next Object")
  531. if ($(".filelist.ready").length > 0){
  532. $($(".filelist.ready")[0]).find(".startTaskButton")[0].click();
  533. }else{
  534. //Conversion finished
  535. console.log("Conversion finished");
  536. queueStarted = false;
  537. }
  538. }
  539. }
  540. }, 1000);
  541. function startQueue(){
  542. //Start the queue with the given task number on the fly
  543. queueStarted = true;
  544. }
  545. function stopQueue(){
  546. queueStarted = false;
  547. }
  548. function startTask(taskObject, event){
  549. event.preventDefault();
  550. event.stopImmediatePropagation();
  551. //Travel back to the task object itself
  552. taskObject = $(taskObject).parent().parent().parent();
  553. //Try to validate conversion type
  554. var mediaType = {
  555. "music": ["m4a","flac","mp3","wav","ogg","aac","wma"],
  556. "video": ["mp4","avi","webm","mkv","wmv","mov","m4v","rmvb"],
  557. "image": ["png","jpg","jpeg","gif","tif","tiff"]
  558. }
  559. var srcExt = $(taskObject).attr("filepath").split(".").pop();
  560. var targetType = $(taskObject).attr("mtype");
  561. var srcType = "unknown";
  562. //Check which type of media is src
  563. if (mediaType["music"].includes(srcExt)){
  564. srcType = "music";
  565. }else if (mediaType["video"].includes(srcExt)){
  566. srcType = "video";
  567. }else if (mediaType["image"].includes(srcExt)){
  568. srcType = "image";
  569. }
  570. //Allow video -> (video or audio), music -> music and image -> image
  571. var requireConversionConfirm = true;
  572. if (srcType == "video" && targetType == "video"){
  573. requireConversionConfirm = false
  574. }else if (srcType == "video" && targetType == "music"){
  575. requireConversionConfirm = false
  576. }else if (srcType == "music" && targetType == "music"){
  577. requireConversionConfirm = false
  578. }else if (srcType == "image" && targetType == "image"){
  579. requireConversionConfirm = false
  580. }else if (targetType == "other"){
  581. //Just trust the user, they know what they are doing
  582. requireConversionConfirm = false
  583. }
  584. if (requireConversionConfirm){
  585. if (!confirm("We are not sure if the conversion media type is valid. Continue anyway?")){
  586. return
  587. }
  588. }
  589. //OK! Convert this file
  590. var filepath = $(taskObject).attr("filepath");
  591. var command = $(taskObject).attr("command");
  592. //Update the progress bar
  593. $(taskObject).find(".tiny.progress").attr("class","ts blue queried indeterminate tiny progress");
  594. $(taskObject).find(".bar").css("width","100%");
  595. $(taskObject).removeClass("ready").addClass("converting");
  596. //Hide the control buttons
  597. $(taskObject).find(".description").html("<span><i class='loading spinner icon'></i> Converting...</span>");
  598. ao_module_agirun("FFmpeg Factory/backend/convert.js",{
  599. filepath: filepath,
  600. command: command
  601. },function(data){
  602. if (data.error !== undefined){
  603. //Conversion failed
  604. console.log(data.error);
  605. $(taskObject).find(".tiny.progress").attr("class","ui red tiny progress");
  606. $(taskObject).find(".bar").css("width","100%");
  607. $(taskObject).removeClass("converting").addClass("failed");
  608. $(taskObject).find(".description").html(`<span><i class='remove icon'></i> ${data.error}</span> / <a onclick="removeTask(this);"><i class="trash icon"></i> Remove From List</a>`);
  609. }else{
  610. $(taskObject).find(".tiny.progress").attr("class","ui green tiny progress");
  611. $(taskObject).find(".bar").css("width","100%");
  612. $(taskObject).removeClass("converting").addClass("done");
  613. $(taskObject).find(".description").html(`<span><i class='checkmark icon'></i> Completed</span>`);
  614. }
  615. $(taskObject).find(".description").html('<a onclick="removeTask(this);"><i class="checkmark icon"></i> Close</a>');
  616. }, function(){
  617. //Failed callback
  618. $(taskObject).find(".tiny.progress").attr("class","ui red tiny progress");
  619. $(taskObject).find(".bar").css("width","100%");
  620. $(taskObject).removeClass("converting").addClass("failed");
  621. $(taskObject).find(".description").html(`<a onclick="removeTask(this);"><i class="remove icon"></i> Remove</a>`);
  622. });
  623. }
  624. </script>
  625. </body>
  626. </html>