mpv.js
mpv.js copied to clipboard
Handle complex properties + Promise API
currently there is no method for getting a property value like mp.get_property. sure there is mpv.observe but it's not useful for some properties like track-list
the following code demonstrates why:
handleMPVReady (mpv) {
this.mpv = mpv
this.mpv.observe("track-list")
this.mpv.observe("track-list/count")
}
handlePropertyChange(name, value) {
if (name === 'track-list') console.log(value) // noting, where it should be an array
if (name === 'track-list/count') console.log(value) // integer
}
so in order to find out the number of subtitles that are available for the current file and then cycle through them first you have to find the number of tracks then observe each track individually like
this.mpv.observe('track-list/0/type').
my workaround
since #24 is solved. I can load a custom script that uses mp.get_property('track-list') and then spawn PowerShell to write the result into a temporary file. and then with fs.watch and fs.createReadStream feed the result into renderer process.
script.js
mp.set_property('sub-auto', 'fuzzy')
var getTempDir = function () {
var temp = mp.utils.getenv('TEMP') || mp.utils.getenv('TEP')
if (temp) return temp
else return '/tmp'
}
mp.register_event('file-loaded', function () {
var trackList = mp.get_property('track-list')
var cmds = ['powershell', "'" + trackList + "' | Out-File -Encoding 'UTF8' " + getTempDir() + '\\mpvdata.json']
var result = mp.utils.subprocess({
args: cmds
})
})
renderer.js
handleMPVReady (mpv) {
this.mpv = mpv
this.mpv.command('load-script', path.join(__dirname, 'mpv', 'config', 'scripts', 'index.js'))
const observe = mpv.observe.bind(mpv);
['pause', 'time-pos', 'duration', 'eof-reached', 'volume', 'mute'].forEach(observe)
}
handleLoad (e) {
e.target.blur()
const items = remote.dialog.showOpenDialog({filters: [
{name: 'Videos', extensions: ['mkv', 'mp4', 'mov', 'avi']},
{name: 'All files', extensions: ['*']}
]})
if (items) {
this.mpv.command('loadfile', items[0])
this.mpv.property('pause', false)
let trackList = ''
setTimeout(() => {
fs.createReadStream(path.join(os.tmpdir(), 'mpvdata.json'))
.on('data', (chunks) => {
trackList += chunks
})
.on('end', () => {
console.log(trackList)
})
}, 1000)
}
}
it is not an accurate solution because:
- this only works on windows.
- if powershell fails I have to ether close the MPV process. or ignore the functionality that uses
track-listin my program.
HandleMPVPropertyChange should be improved to be able to return complex properties. Also it might be worth to implement
mpv.property('pause').then(pause => /* handle pause value */)
It requires changes to C++ plugin, sadly I don't have enough time currently to work on this project…
I found a nifty workaround that is cross-platform, MPV supports IPC and this means with NET API we can actually set/get properties on the fly.
script.js
mp.set_property('input-ipc-server', '/mpvsocket')
player.jsx
import net from 'net'
import xpipe from 'xpipe'
export class Player extends React.PureComponent {
constructor (props) {
super(props)
// ...
// ...
// ...
setTimeout(() => {
const client = net.connect(xpipe.eq('/mpvsocket'), () => {
console.log('connected to IPC server')
const command = JSON.stringify(
{ 'command': ['observe_property', 1, 'track-list'], 'request_id': 100 }
)
client.write(Buffer.from(command + '\n'))
})
client.on('data', (res) => {
res = res.toString('utf8')
res = res.trim()
res = `[${res}]`
res = res.replace(/(\r\n|\n|\r)/g, ',')
res = JSON.parse(res)
res.forEach((key) => {
if (key.event === 'property-change' && key.name === 'track-list') {
if (key.data !== null) console.log(key.data)
}
})
})
}, 1000)
}
handleMPVReady (mpv) {
this.mpv = mpv
this.mpv.command('load-script', path.join(__dirname, 'script.js'))
// ...
}
}
xpipe will return a cross-platform IPC path. setTimeout is only needed if you want to make a request in componentDidMount or constructor.
this can be a temporary solution until someone improves the C++ plugin.
You don't need script.js anymore,
this.mpv.property('input-ipc-server', '/mpvsocket');
should work. Now need to implement proper handling of complex properties.