You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

player.js 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. var spawn = require("child_process").spawn;
  2. var fs = require("fs");
  3. var net = require("net");
  4. var Queue = require("../queue");
  5. exports.httpPath = "/playback";
  6. var child = null;
  7. var ipcServer = process.cwd()+"/mpv-ipc-socket";
  8. function cmd(params, cb) {
  9. if (child == null || child.sock == null)
  10. return;
  11. child.sock.write(JSON.stringify({
  12. command: params
  13. })+"\n");
  14. child.msgqueue.dequeue(obj => {
  15. if (cb)
  16. cb(obj);
  17. });
  18. }
  19. function getState(cb) {
  20. if (child == null) {
  21. cb({
  22. playing: false,
  23. paused: false,
  24. muted: false,
  25. duration: 0,
  26. time_pos: 0,
  27. volume: 0,
  28. volume_max: 0
  29. });
  30. return;
  31. }
  32. var state = {
  33. playing: true
  34. };
  35. var cbs = 7;
  36. function next() {
  37. cbs -= 1;
  38. if (cbs === 0)
  39. cb(state);
  40. }
  41. cmd(["get_property", "pause"], res => {
  42. state.paused = res.data;
  43. next();
  44. });
  45. cmd(["get_property", "mute"], res => {
  46. state.muted = res.data;
  47. next();
  48. });
  49. cmd(["get_property", "duration"], res => {
  50. state.duration = res.data;
  51. next();
  52. });
  53. cmd(["get_property", "time-pos"], res => {
  54. state.time_pos = res.data;
  55. next();
  56. });
  57. cmd(["get_property", "volume"], res => {
  58. state.volume = res.data;
  59. next();
  60. });
  61. cmd(["get_property", "volume-max"], res => {
  62. state.volume_max = res.data;
  63. next();
  64. });
  65. cmd(["get_property", "sub-delay"], res => {
  66. state.sub_delay = res.data;
  67. next();
  68. });
  69. }
  70. exports.isPlaying = function() {
  71. return child != null;
  72. }
  73. exports.play = function(path, subFile, cb) {
  74. exports.stop();
  75. var args = [
  76. path,
  77. "--no-cache-pause",
  78. "--no-resume-playback",
  79. "--input-ipc-server", ipcServer
  80. ];
  81. if (subFile) {
  82. args.push("--sub-file");
  83. args.push(subFile);
  84. }
  85. var lchild = spawn("mpv", args, { stdio: ["inherit", "inherit", "ignore"] });
  86. child = lchild;
  87. lchild.running = true;
  88. lchild.once("close", () => {
  89. if (lchild.running) exports.stop();
  90. });
  91. lchild.on("error", err => console.error(err.toString()));
  92. lchild.state = {};
  93. lchild.msgqueue = Queue();
  94. lchild.initTimeout = setTimeout(() => {
  95. // Create socket
  96. lchild.sock = net.connect(ipcServer, () => {
  97. // Add output from mpv to the queue
  98. lchild.sock.on("data", d => {
  99. d.toString().split("\n").forEach(str => {
  100. if (str == "") return;
  101. var obj = JSON.parse(str);
  102. if (obj.event) return;
  103. lchild.msgqueue.push(obj);
  104. });
  105. });
  106. lchild.sock.on("error", err => console.trace(err));
  107. cmd(["set_property", "fullscreen", "yes"]);
  108. cb();
  109. });
  110. }, 1000);
  111. }
  112. exports.stop = function() {
  113. if (child) {
  114. child.running = false;
  115. child.kill("SIGKILL");
  116. clearTimeout(child.initTimeout);
  117. child = null;
  118. exports.onstop();
  119. }
  120. try {
  121. fs.unlinkSync(ipcServer);
  122. } catch (err) {}
  123. }
  124. exports.init = function(app) {
  125. function evt(p, cb) {
  126. app.post(exports.httpPath+"/"+p, (req, res) => cb(req, res));
  127. }
  128. evt("exit", (req, res) => { res.end(); exports.stop() });
  129. evt("state", (req, res) => {
  130. getState((state) => {
  131. res.json(state);
  132. });
  133. });
  134. evt("set/:key/:val", (req, res) => {
  135. cmd(["set_property", req.params.key, req.params.val]);
  136. res.end();
  137. });
  138. }