libmpv

Post your Gambas programming questions here.
User avatar
BruceSteers
Posts: 1521
Joined: Thursday 23rd July 2020 5:20pm
Location: Isle of Wight
Contact:

libmpv

Post by BruceSteers »

Has anyone done anything with mpv / libmpv ?

I've figured out how to get mpv to load into any panel via shell with the following code..
'
Public p As Process
Public hWindow As Window

Public Sub Form_Show()

hWindow = New Window(Panel1)  ' Instance a window inside the panel i want the mpv player
hWindow.Expand = True
hWindow.Show

' launch mpv with the new window id
p = Shell "mpv --wid=" & Str(hWindow.Id) & " " & Quote(FileToPlay)

End

Public Sub Form_Close()
 
  If p Then p.Kill
  
End
But with shell i do not think i can control the player

wondered if anyone had tried mpv (or mplayer) library calls or knows how to interface with a player via commandline?

TIA :)
If at first you don't succeed , try doing something differently.
BruceS
User avatar
stevedee
Posts: 518
Joined: Monday 20th March 2017 6:06pm

Re: libmpv

Post by stevedee »

Interesting question Bruce, so I just had to play with your code.

As Process is a stream I thought I could get this to work...
Public p As Process
Public hWindow As Window

Const FileToPlay As String = "/home/steve/Gambas/mPlayer/AheadByACentury.mp3"
Const PAUSE As String = "p"
 
Public Sub Form_Show()
 
hWindow = New Window(Panel1)  ' Instance a window inside the panel i want the mpv player
hWindow.Expand = True
hWindow.Show
 
' launch mpv with the new window id
p = Shell "mpv --wid=" & Str(hWindow.Id) & " " & Quote(FileToPlay)
 
End
 
Public Sub Form_Close()
  
  If p Then p.Kill
   
End

Public Sub Button1_Click()

  p.Begin()
  Write #p, PAUSE, Len(PAUSE)
  p.Send()
  
End

Public Sub Timer1_Timer()

  Me.Text = "state: " & p.State

End
...but something is not right, and I've run out of time. I'll try to pick it up again tomorrow!
vuott
Posts: 262
Joined: Wednesday 5th April 2017 6:07pm
Location: European Union

Re: libmpv

Post by vuott »

Here an essential code, that uses some external functions of the "libmpv" library, for a command line application:
Library "libc:6"

Private Const LC_NUMERIC As Integer = 1

' char *setlocale (int __category, const char *__locale)
' Set and/or return the current locale.
Private Extern setlocale(__category As Integer, __locale As String) As Pointer


Library "libmpv:1.107.0"
 
Public Struct mpv_event
  event_id As Integer
  error_ As Integer
  reply_userdata As Long
  data As Pointer
End Struct

Private Const MPV_FORMAT_INT64 As Integer = 4
Private Const MPV_EVENT_END_FILE As Integer = 7
 
' mpv_handle *mpv_create(void)
' Create a new mpv instance.
Private Extern mpv_create() As Pointer
 
' int mpv_initialize(mpv_handle *ctx)
' Initialize an uninitialized mpv instance.
Private Extern mpv_initialize(ctx As Pointer) As Integer
 
' int mpv_command(mpv_handle *ctx, const char **args)
' Send a command to the player.
Private Extern mpv_command(ctx As Pointer, args As String[]) As Integer
 
' int mpv_set_property(mpv_handle *ctx, const char *name, mpv_format format, void *data)
' Set a property.
Private Extern mpv_set_property(ctx As Pointer, name As String, format_ As Integer, data As Pointer) As Integer

' mpv_event *mpv_wait_event(mpv_handle *ctx, double timeout)
' Wait for the next event, or until the timeout expires.
Private Extern mpv_wait_event(ctx As Pointer, timeout As Float) As Mpv_event
 
' void mpv_terminate_destroy(mpv_handle *ctx)
' Disconnect and destroy the mpv_handle.
Private Extern mpv_terminate_destroy(ctx As Pointer)
 
 
Public Sub Main()

  Dim cmd As String[] = ["loadfile", Null, Null]
  Dim mpv As Pointer
  Dim err As Integer
  Dim v As Long
  Dim tm As Date
  Dim ev As Mpv_event

  cmd[1] = "/path/of/multimedia/file"   ' To load an multimedia file

  setlocale(LC_NUMERIC, "C")

  mpv = mpv_create()
  If mpv == 0 Then Error.Raise("Error !")
  
  err = mpv_initialize(mpv)
  If err < 0 Then
    Terminus(mpv)
    Error.Raise("Error !")
  Endif
  
  err = mpv_command(mpv, cmd)
  If err < 0 Then
    Terminus(mpv)
    Error.Raise("Error !")
  Endif
  
 ' Set Volume:
 ' 0 = mute;
 ' 100 = no changes;
 ' >100 volume increase.
  v = 50
  mpv_set_property(mpv, "volume", MPV_FORMAT_INT64, VarPtr(v))
 
  tm = Now
  
  Repeat
    Write "\r\e[31m" & Str(Time(0, 0, 0, DateDiff(tm, Now, gb.Millisecond)))
    Flush
    ev = mpv_wait_event(mpv, 1)
  Until ev.event_id == MPV_EVENT_END_FILE   ' The loop ends when the playing ends
  
  Terminus(mpv)
  
End

Private Procedure Terminus(po As Pointer)
 
  mpv_terminate_destroy(po)
 
End
Last edited by vuott on Tuesday 25th May 2021 12:11am, edited 7 times in total.
Europaeus sum !

Amare memorentes atque deflentes ad mortem silenter labimur.
User avatar
BruceSteers
Posts: 1521
Joined: Thursday 23rd July 2020 5:20pm
Location: Isle of Wight
Contact:

Re: libmpv

Post by BruceSteers »

Hi Vuott , I also tried Write to the process handler but got invalid file handle :(
I do not think it works like that.
It can use JSON commands via the --input-ipc-server arg but i do not know how to use it without installing socat (and i don't want to) I'm not familiar with ipc servers

That other code looks promising though. thank you I might be able to work with that
It would be nicer to use proper lib calls i think

I'm trying to make a movie player (I initially used the MediaView component but it does not support enough formats)
If at first you don't succeed , try doing something differently.
BruceS
vuott
Posts: 262
Joined: Wednesday 5th April 2017 6:07pm
Location: European Union

Re: libmpv

Post by vuott »

BruceSteers wrote: Monday 24th May 2021 11:22pm ... but it does not support enough formats
Hello BruceSteers,
what other video formats would you like to play?
Europaeus sum !

Amare memorentes atque deflentes ad mortem silenter labimur.
User avatar
BruceSteers
Posts: 1521
Joined: Thursday 23rd July 2020 5:20pm
Location: Isle of Wight
Contact:

Re: libmpv

Post by BruceSteers »

I'm not sure of the formats exactly i just have various mp4 and mkv files that the MediaView control show some okay but not others
audio is okay but video is not right for some.

Here is my simple test app now...

Managed to get the movie to play :)

Thanks for the help :)

Export
Inherits UserControl

Public Const _Similar As String = "MovieBox,MediaView"

Private $hView As Window
Private mpvHandle As Pointer

Library "libc:6"
Private Extern setlocale(__category As Integer, __locale As String) As Pointer

Library "libmpv"

Public Struct mpv_event
  event_id As Integer
  error_ As Integer
  reply_userdata As Long
  data As Pointer
End Struct
 
Extern mpv_create() As Pointer In "libmpv"
Extern mpv_set_option_string(ctx As Pointer, Name As String, Data As String) As Integer In "libmpv"
Extern mpv_initialize(ctx As Pointer) As Integer In "libmpv"
Extern mpv_command(mHandle As Pointer, com As String[]) As Integer In "libmpv"
Private Extern mpv_terminate_destroy(ctx As Pointer) In "libmpv"
Private Extern mpv_wait_event(ctx As Pointer, timeout As Float) As Mpv_event In "libmpv"


Public Sub Kill()
  
  If mpvHandle <> 0 Then mpv_terminate_destroy(mpvHandle)
  
End

Public Sub _new()
  Dim err As Integer

$hView = New Window(Me)
$hView.Expand = True
$hView.show
Wait
setlocale(1, "C")

mpvHandle = mpv_create()
SetOptionString("input-default-bindings", "yes")
SetOptionString("input-vo-keyboard", "yes")
SetOptionString("osc", "yes")
SetOptionString("wid", Str($hView.id))

If mpvHandle == 0 Then Error.Raise("Cannot create mpv handler")
err = mpv_initialize(mpvHandle)

End

Public Sub Command(sCommand As String[]) As Integer
  
Return mpv_command(mpvHandle, sCommand)
  
End

Public Sub SetOptionString(sName As String, sData As String) As Integer
  
Return mpv_set_option_string(mpvHandle, sName, sData)
  
End

Public Sub Load(sURL As String)
  
  mpv_command(mpvHandle, ["loadfile", sURL, Null])
  
End
Last edited by BruceSteers on Tuesday 25th May 2021 6:03pm, edited 1 time in total.
If at first you don't succeed , try doing something differently.
BruceS
vuott
Posts: 262
Joined: Wednesday 5th April 2017 6:07pm
Location: European Union

Re: libmpv

Post by vuott »

A good code.
Just a remark: having declared the "libmpv" library with the keyword "Library", it is useless then to call the same library with the keyword "IN" in each external function declaration.
It's enough:
Library "libmpv"
Europaeus sum !

Amare memorentes atque deflentes ad mortem silenter labimur.
User avatar
BruceSteers
Posts: 1521
Joined: Thursday 23rd July 2020 5:20pm
Location: Isle of Wight
Contact:

Re: libmpv

Post by BruceSteers »

vuott wrote: Tuesday 25th May 2021 2:14am A good code.
Just a remark: having declared the "libmpv" library with the keyword "Library", it is useless then to call the same library with the keyword "IN" in each external function declaration.
It's enough:
Library "libmpv"
haha , cheers Vuott i did not know that . (I'm still an external library newbie)

here it is a little cleaned up and error messages now enabled..
I plan to make it fully functional and handle like any other media player control
A viable alternative to MediaView
I have mpv_command() and mpv_option_string() as public functions so it is technically fully functional
(i just have yet to learn all the commands/options to use it properly)

' Gambas class file

Export
Inherits UserControl

Public Const _Similar As String = "MovieBox"

Private $hView As Window
Private mpvHandle As Pointer

Library "libc:6"
Private Extern setlocale(__category As Integer, __locale As String) As Pointer

Public Struct mpv_event
  event_id As Integer
  error_ As Integer
  reply_userdata As Long
  data As Pointer
End Struct
 
Library "libmpv"

Private Extern mpv_create() As Pointer
Private Extern mpv_set_option_string(ctx As Pointer, Name As String, Data As String) As Integer
Private Extern mpv_initialize(ctx As Pointer) As Integer
Private Extern mpv_command(mHandle As Pointer, com As String[]) As Integer
Private Extern mpv_terminate_destroy(ctx As Pointer)
Private Extern mpv_wait_event(ctx As Pointer, timeout As Float) As Mpv_event
Private Extern mpv_error_string(iVal As Integer) As String

Public Sub _free()
  
  If mpvHandle <> 0 Then mpv_terminate_destroy(mpvHandle)

End

Public Sub Kill()
  
  If mpvHandle <> 0 Then mpv_terminate_destroy(mpvHandle)

End

Public Sub _new()
  Dim err As Integer

$hView = New Window(Me)
'$hView.Expand = True
$hView.show
Wait
setlocale(1, "C")

mpvHandle = mpv_create()

' enable default controls
SetOptionString("input-default-bindings", "yes")
SetOptionString("input-vo-keyboard", "yes")
SetOptionString("osc", "yes")
SetOptionString("idle", "yes")

' attach to window
SetOptionString("wid", Str($hView.id))

If mpvHandle == 0 Then Error.Raise("Cannot create mpv handler")
err = mpv_initialize(mpvHandle)
  If err <> 0 Then Message.Error("Error " & mpv_error_string(err))
End

Public Sub Command(sCommand As String[]) As Integer
  
Dim err As Integer = mpv_command(mpvHandle, sCommand)
    If err <> 0 Then Message.Error("Error " & mpv_error_string(err))
End

Public Sub SetOptionString(sName As String, sData As String) As Integer
  
Dim err As Integer = mpv_set_option_string(mpvHandle, sName, sData)
    If err <> 0 Then Message.Error("Error " & mpv_error_string(err))

End

Public Sub Load(sURL As String)
  
  Command(["loadfile", sURL, Null])
  
End
If at first you don't succeed , try doing something differently.
BruceS
User avatar
BruceSteers
Posts: 1521
Joined: Thursday 23rd July 2020 5:20pm
Location: Isle of Wight
Contact:

Re: libmpv

Post by BruceSteers »

Well here is what i have so far.

1 Event...
'' Raise 'Stopped' event when video finishes
Event Stopped

The following Properties..
'' get or set the percent of the file played so far
Property Percent As Integer
'' show or hide the On Screen display/controls
Property Show_OSD As Boolean
'' get or set the position of the file (in seconds) played so far
Property Position As Integer
'' Duration of the file in seconds
Property Read Length As Integer
'' get or set the file path
Property URL As String
'' State of the player (IDLE,PLAYING,PAUSED)
Property State As Integer

The Following Public commands...
'' Quit the player and destroy the handler
Public Sub Kill()
'' pass a 'command' Null terminated array to the player
Public Sub Command(sCommand As String[]) As Integer
'' pass an 'option' argument to the player
Public Sub SetOptionString(Name As String, Data As String) As Integer
'' pass a 'property' argument to the player
Public Sub SetPropertyString(Name As String, Data As String) As Integer
'' get the value of a named property
Public Sub GetPropertyString(Name As String) As String
'' Load and play a media file
Public Sub Load(Optional URL As String)
'' Pause playback or resume using yes or no as argumemt.
'' if no argument is given pause state is toggled
Public Sub Pause(Optional YesNo As String)

Still lots to do but thought some might like to see the progress I've made so far :)
(note there's a bug in gtk3 makes the window not initialise properly but it is okay with qt/gtk2)
If at first you don't succeed , try doing something differently.
BruceS
User avatar
BruceSteers
Posts: 1521
Joined: Thursday 23rd July 2020 5:20pm
Location: Isle of Wight
Contact:

Re: libmpv

Post by BruceSteers »

Todo...

Figure out better datatyping.
Currently i'm using strings for all commands/options but will work out how the datatypes work and pass non-string args where possible.

Compare it to MediaView and emulate all the same functions/properties

Any suggestions welcome.
If at first you don't succeed , try doing something differently.
BruceS
Post Reply