Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle complex properties + Promise API #26

Open
itshaadi opened this issue May 3, 2018 · 3 comments
Open

Handle complex properties + Promise API #26

itshaadi opened this issue May 3, 2018 · 3 comments

Comments

@itshaadi
Copy link
Contributor

itshaadi commented May 3, 2018

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-list in my program.
@Kagami
Copy link
Owner

Kagami commented May 3, 2018

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…

@itshaadi
Copy link
Contributor Author

itshaadi commented May 10, 2018

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.

@Kagami
Copy link
Owner

Kagami commented Jul 28, 2018

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.

@Kagami Kagami mentioned this issue Dec 30, 2018
@Kagami Kagami changed the title getting property values the right way Handle complex properties + Promise API Dec 30, 2018
@Kagami Kagami mentioned this issue Apr 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants