media-player-controller
Version:
Spawn media player app and control playback
232 lines (193 loc) • 4.16 kB
JavaScript
const noop = () => {};
var prevPosition;
module.exports =
{
init: function()
{
prevPosition = null;
this.command(['observe_property', 1, 'time-pos']);
this.command(['observe_property', 2, 'volume']);
this.command(['observe_property', 3, 'pause']);
this.command(['observe_property', 4, 'duration']);
this.command(['observe_property', 5, 'eof-reached']);
this.command(['observe_property', 6, 'speed']);
this.command(['observe_property', 7, 'media-title']);
},
_connectType: 'socket',
_getSpawnArgs: function(opts)
{
var presetArgs = [
`--input-ipc-server=${opts.ipcPath}`,
opts.media
];
return [ ...opts.args, ...presetArgs ];
},
command: function(params, cb)
{
cb = cb || noop;
var command = null;
if(!this.writable)
return cb(new Error('No writable IPC socket! Playback control disallowed'));
if(!Array.isArray(params))
return cb(new Error('No command parameters array!'));
try { command = JSON.stringify({ command: params }); }
catch(err) { return cb(err); }
this._debug(command);
this.write(command + '\n', cb);
},
play: function(cb)
{
cb = cb || noop;
this.command(['set_property', 'pause', false], cb);
},
pause: function(cb)
{
cb = cb || noop;
this.command(['set_property', 'pause', true], cb);
},
cyclePause: function(cb)
{
cb = cb || noop;
this.command(['cycle', 'pause'], cb);
},
_load: function(media, cb)
{
cb = cb || noop;
this.command(['loadfile', media, 'replace'], cb);
},
seek: function(position, cb)
{
cb = cb || noop;
this.command(['seek', position, 'exact+absolute'], cb);
},
setVolume: function(value, cb)
{
cb = cb || noop;
this.command(['set_property', 'volume', value * 100], cb);
},
setSpeed: function(value, cb)
{
cb = cb || noop;
this.command(['set_property', 'speed', value], cb);
},
setRepeat: function(isEnabled, cb)
{
cb = cb || noop;
switch(isEnabled)
{
case true:
case 'inf':
case 'yes':
case 'on':
isEnabled = 'inf';
break;
default:
isEnabled = 'no';
break;
}
this.command(['set_property', 'loop', isEnabled], cb);
},
cycleVideo: function(cb)
{
cb = cb || noop;
this.command(['cycle', 'video'], cb);
},
cycleAudio: function(cb)
{
cb = cb || noop;
this.command(['cycle', 'audio'], cb);
},
cycleSubs: function(cb)
{
cb = cb || noop;
this.command(['cycle', 'sub'], cb);
},
addSubs: function(subsPath, cb)
{
cb = cb || noop;
return cb(new Error('Adding subs on MPV not supported yet.'));
},
setFullscreen: function(isEnabled, cb)
{
cb = cb || noop;
switch(isEnabled)
{
case false:
case 'no':
isEnabled = 'no';
break;
default:
isEnabled = 'yes';
break;
}
this.command(['set_property', 'fullscreen', isEnabled], cb);
},
cycleFullscreen: function(cb)
{
cb = cb || noop;
this.command(['cycle', 'fullscreen'], cb);
},
keepOpen: function(value, cb)
{
cb = cb || noop;
switch(value)
{
case true:
case 'yes':
value = 'yes';
break;
case 'always':
value = 'always';
break;
default:
value = 'no';
break;
}
this.command(['set_property', 'keep-open', value], cb);
},
_playerQuit: function(cb)
{
cb = cb || noop;
this.command(['quit', 0], cb);
},
_parseSocketData: function(data)
{
const splitOper = data.includes('\r\n') ? '\r\n' : '\n';
const msgArray = data.split(splitOper);
for(var i = 0; i < msgArray.length - 1; i++)
{
var msg = JSON.parse(msgArray[i]);
if(msg.event !== 'property-change')
continue;
var value = null;
switch(msg.name)
{
case 'volume':
value = msg.data / 100;
break;
case 'time-pos':
if(
msg.data < 0
|| !isNaN(prevPosition)
&& Math.abs(prevPosition - msg.data) < 1
) {
continue;
}
value = Math.floor(msg.data);
prevPosition = value;
break;
case 'duration':
case 'pause':
case 'eof-reached':
case 'speed':
case 'media-title':
value = msg.data;
break;
default:
break;
}
if(value !== null)
this.emit('playback', { name: msg.name, value: value });
}
}
}