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 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 = 6;
  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. }
  66. exports.isPlaying = function() {
  67. return child != null;
  68. }
  69. exports.play = function(path, subFile, cb) {
  70. exports.stop();
  71. var args = [
  72. path,
  73. "--no-cache-pause",
  74. "--no-resume-playback",
  75. "--input-unix-socket", ipcServer
  76. ];
  77. if (subFile) {
  78. args.push("--sub-file");
  79. args.push(subFile);
  80. }
  81. var lchild = spawn("mpv", args, { stdio: "inherit" });
  82. child = lchild;
  83. lchild.running = true;
  84. lchild.once("close", () => {
  85. if (lchild.running) exports.stop();
  86. });
  87. lchild.on("error", err => console.error(err.toString()));
  88. lchild.state = {};
  89. lchild.msgqueue = Queue();
  90. lchild.initTimeout = setTimeout(() => {
  91. // Create socket
  92. lchild.sock = net.connect(ipcServer, () => {
  93. // Add output from mpv to the queue
  94. lchild.sock.on("data", d => {
  95. d.toString().split("\n").forEach(str => {
  96. if (str == "") return;
  97. var obj = JSON.parse(str);
  98. if (obj.event) return;
  99. lchild.msgqueue.push(obj);
  100. });
  101. });
  102. lchild.sock.on("error", err => console.trace(err));
  103. cmd(["set_property", "fullscreen", "yes"]);
  104. cb();
  105. });
  106. }, 1000);
  107. }
  108. exports.stop = function() {
  109. if (child) {
  110. child.running = false;
  111. child.kill("SIGKILL");
  112. clearTimeout(child.initTimeout);
  113. child = null;
  114. exports.onstop();
  115. }
  116. try {
  117. fs.unlinkSync(ipcServer);
  118. } catch (err) {}
  119. }
  120. exports.init = function(app) {
  121. function evt(p, cb) {
  122. app.post(exports.httpPath+"/"+p, (req, res) => cb(req, res));
  123. }
  124. evt("exit", (req, res) => { res.end(); exports.stop() });
  125. evt("state", (req, res) => {
  126. getState((state) => {
  127. res.json(state);
  128. });
  129. });
  130. evt("set/:key/:val", (req, res) => {
  131. cmd(["set_property", req.params.key, req.params.val]);
  132. res.end();
  133. });
  134. }