External C-Libary and Events

Post your Gambas programming questions here.
Post Reply
JumpyVB
Posts: 75
Joined: Friday 11th September 2020 9:09am

External C-Libary and Events

Post by JumpyVB »

Forum member Vuott introduced me to libvlc. I quite like it and managed to succesfully add a function (specifically libvlc_media_player_set_time) to the extern interface. But how can I hook with the events provided by the library such as libvlc_MediaPlayerTimeChangedhttps://videolan.videolan.me/vlc/group_ ... 0e8d3c9259? I would like to avoid use of the repeat until loop.

Here's the sample code:
Private inst As Pointer
Private mp As Pointer
Private m As Pointer Library "libvlc:5.6.0"

' enum libvlc_state_t
Private Enum libvlc_NothingSpecial = 0, libvlc_Opening, libvlc_Buffering, libvlc_Playing, libvlc_Paused, libvlc_Stopped, libvlc_Ended, libvlc_Error
' enum libvlc_video_orient_t
Private Enum libvlc_video_orient_top_left = 0, libvlc_video_orient_top_right, libvlc_video_orient_bottom_left, libvlc_video_orient_bottom_right, libvlc_video_orient_left_top, libvlc_video_orient_left_bottom, libvlc_video_orient_right_top, libvlc_video_orient_right_bottom

' Create And initialize a libvlc instance.
Private Extern libvlc_new(argc As Integer, argv As String[]) As Pointer
' Create a media for a certain file path.
Private Extern libvlc_media_new_path(p_instance As Pointer, path As String) As Pointer
' Create a Media Player object from a Media.
Private Extern libvlc_media_player_new_from_media(p_md As Pointer) As Pointer
' Set an X Window System drawable where the media player should render its video output.
Private Extern libvlc_media_player_set_xwindow(p_mi As Pointer, drawable As Integer)
' Play the video file.
Private Extern libvlc_media_player_play(p_mi As Pointer) As Integer
' Stop the video file
Private Extern libvlc_media_player_stop(p_mi As Pointer)
' Get the current movie length (in ms).
Private Extern libvlc_media_player_get_length(p_mi As Pointer, l_ex As Pointer) As Integer
' Get the current movie time (in ms).
Private Extern libvlc_media_player_get_time(p_mi As Pointer) As Integer
' Get current movie state.
Private Extern libvlc_media_player_get_state(p_mi As Pointer) As Integer
' Toggle breaks.
Private Extern libvlc_media_player_pause(p_mi As Pointer)
' Release a media_player after use Decrement the reference count of a media player object.
Private Extern libvlc_media_player_release(p_mi As Pointer)
' Decrement the reference count of a media descriptor object.
Private Extern libvlc_media_release(p_md As Pointer)
' Decrement the reference count of a libvlc instance, and destroy it if it reaches zero.
Private Extern libvlc_release(p_instance As Pointer)
'Set the movie time (in ms)
Private Extern libvlc_media_player_set_time(p_mi As Pointer, i_time As Long, b_fast As Boolean) As Integer

Public Sub ButtonPlay_Click()
' Initialize the VLC library
  inst = libvlc_new(0, Null)
' Create a new multimedia object.
  m = libvlc_media_new_path(inst, "/home/user/Videos/first_vid.mp4")
' Create a media player
  mp = libvlc_media_player_new_from_media(m)
' To show the video in the "DrawingArea", we get his identifier
  Dim id As Integer = DrawingArea1.Id
' We pass the identifier of the window, in which the video must be shown
  libvlc_media_player_set_xwindow(mp, id)
' Starts the execution of the video file by the media player :
  libvlc_media_player_play(mp)

 ' Repeat
 '   TextLabel1.Text = "Durata: " & Str(Time(0, 0, 0, libvlc_media_player_get_length(mp, 0)))
 '   TextLabel2.Text = "<font color=red>" & Str(Time(0, 0, 0, libvlc_media_player_get_time(mp))) & "</font>"
 '   Wait 0.01
 ' Until libvlc_media_player_get_state(mp) > libvlc_Paused
 '
 ' Chiude()

End

Public Sub ButtonSeek_Click()
  libvlc_media_player_set_time(mp, 2000, False)
End
Public Sub ToggleButtonPause_Click()
  libvlc_media_player_pause(mp)
End
Public Sub ButtonStop_Click()
  libvlc_media_player_stop(mp)
End
Private Procedure Chiude()
  'Closes the VLC library
  libvlc_media_player_release(mp)
  libvlc_media_release(m)
  libvlc_release(inst)
End
vuott
Posts: 262
Joined: Wednesday 5th April 2017 6:07pm
Location: European Union

Re: External C-Libary and Events

Post by vuott »

JumpyVB wrote: Monday 24th April 2023 6:16pm how can I hook with the events provided by the library such as libvlc_MediaPlayerTimeChanged[/b]
The elements of the "libvlc_event_e " Enumeration appear to be intertwined :? with the "libvlc_event_attach() " function, the "libvlc_event_t " Enumeration, and a "callback" loop and its specific functions.
I have no experience with that in VLC.
Bad bargain ! :|

...or maybe you could use a Timer.
Europaeus sum !

Amare memorentes atque deflentes ad mortem silenter labimur.
JumpyVB
Posts: 75
Joined: Friday 11th September 2020 9:09am

Re: External C-Libary and Events

Post by JumpyVB »

vuott wrote: Monday 24th April 2023 9:01pmThe elements of the "libvlc_event_e " Enumeration appear to be intertwined :? with the "libvlc_event_attach() " function, the "libvlc_event_t " Enumeration, and a "callback" loop and its specific functions. I have no experience with that in VLC. Or maybe you could use a Timer.
Yeas a timer could do the trick. Thank you for the idea.

Also I will consider investigating further (externing events for the libvlc) myself. Making use of c libraries from Gambas has been on my todo list (despite c language seems very daunting). But do you have previous experience of interfacing some other c library with events? If you can confirm it could be possible I would know it's not a lost cause? A link to a gambas example with any extern events would help tremendously.

PS: My home videos are working fine now in libvlc as opposed to gstreamer. I am experiencing none of that non responsivenes at the end of the video.
vuott
Posts: 262
Joined: Wednesday 5th April 2017 6:07pm
Location: European Union

Re: External C-Libary and Events

Post by vuott »

JumpyVB wrote: Tuesday 25th April 2023 2:45am But do you have previous experience of interfacing some other c library with events?
Usually Events in C programs are handled with loops or "callbacks" calls.
For handling "callback" calls, using external resources in Gambas, you can have a look at this section "Function Callbacks" in the following official Wiki page:

https://gambaswiki.org/wiki/lang/extdecl
Europaeus sum !

Amare memorentes atque deflentes ad mortem silenter labimur.
JumpyVB
Posts: 75
Joined: Friday 11th September 2020 9:09am

Re: External C-Libary and Events

Post by JumpyVB »

I will gradually post stuff that makes this better. I will start with this:
Private Extern XInitThreads() As Integer In "libX11"
Call this function before "libvlc_new(0, Null)" to get rid of error "Xlib not initialized for threads".

Source for the information was found here: https://forum.videolan.org/viewtopic.php?t=136443
JumpyVB
Posts: 75
Joined: Friday 11th September 2020 9:09am

Re: External C-Libary and Events

Post by JumpyVB »

I think I'm getting close to having events working with this code:
' Gambas class file

Private Extern XInitThreads() As Integer In "libX11"

Private inst As Pointer
Private mp As Pointer
Private m As Pointer Library "libvlc:5.6.0"
Private Extern libvlc_new(argc As Integer, argv As String[]) As Pointer
Private Extern libvlc_media_new_path(p_instance As Pointer, path As String) As Pointer
Private Extern libvlc_media_player_new_from_media(p_md As Pointer) As Pointer
Private Extern libvlc_media_player_set_xwindow(p_mi As Pointer, drawable As Integer)
Private Extern libvlc_media_player_play(p_mi As Pointer) As Integer
Private Extern libvlc_media_player_stop(p_mi As Pointer)
Private Extern libvlc_media_player_get_length(p_mi As Pointer, l_ex As Pointer) As Integer
Private Extern libvlc_media_player_get_time(p_mi As Pointer) As Integer
Private Extern libvlc_media_player_get_state(p_mi As Pointer) As Integer
Private Extern libvlc_media_player_pause(p_mi As Pointer)
Private Extern libvlc_media_player_release(p_mi As Pointer)
Private Extern libvlc_media_release(p_md As Pointer)
Private Extern libvlc_release(p_instance As Pointer)
Private Extern libvlc_media_player_set_time(p_mi As Pointer, i_time As Long, b_fast As Boolean) As Integer

'# Events
Private event_manager As Pointer
'# Get the Event Manager from which the media player send event.
Private Extern libvlc_media_player_event_manager(p_mi As Pointer) As Pointer
'# Register for an event notification.
Private Extern libvlc_event_attach(p_event_manager As Pointer, i_event_type As Integer, f_callback As Pointer, user_data As Pointer) As Integer
'# enum libvlc_event_e [https://github.com/videolan/libvlcsharp/blob/3.x/src/LibVLCSharp/Shared/LibVLCEvents.cs]
Private Enum MediaMetaChanged = 0, MediaSubItemAdded = 1, MediaDurationChanged = 2, MediaParsedChanged = 3, MediaFreed = 4, MediaStateChanged = 5, MediaSubItemTreeAdded = 6, MediaPlayerMediaChanged = 256, MediaPlayerNothingSpecial = 257, MediaPlayerOpening = 258, MediaPlayerBuffering = 259, MediaPlayerPlaying = 260, MediaPlayerPaused = 261, MediaPlayerStopped = 262, MediaPlayerForward = 263, MediaPlayerBackward = 264, MediaPlayerEndReached = 265, MediaPlayerEncounteredError = 266, MediaPlayerTimeChanged = 267, MediaPlayerPositionChanged = 268, MediaPlayerSeekableChanged = 269, MediaPlayerPausableChanged = 270, MediaPlayerTitleChanged = 271, MediaPlayerSnapshotTaken = 272, MediaPlayerLengthChanged = 273, MediaPlayerVout = 274, MediaPlayerScrambledChanged = 275, MediaPlayerESAdded = 276, MediaPlayerESDeleted = 277, MediaPlayerESSelected = 278, MediaPlayerCorked = 279, MediaPlayerUncorked = 280, MediaPlayerMuted = 281, MediaPlayerUnmuted = 282, MediaPlayerAudioVolume = 283, MediaPlayerAudioDevice = 284, MediaPlayerChapterChanged = 285, MediaListItemAdded = 512, MediaListWillAddItem = 513, MediaListItemDeleted = 514, MediaListWillDeleteItem = 515, MediaListEndReached = 516, MediaListViewItemAdded = 768, MediaListViewWillAddItem = 769, MediaListViewItemDeleted = 770, MediaListViewWillDeleteItem = 771, MediaListPlayerPlayed = 1024, MediaListPlayerNextItemSet = 1025, MediaListPlayerStopped = 1026
'# typedef void( * libvlc_callback_t)(const struct libvlc_event_t * p_event, void * p_data)
Public Struct Libvlc_event_t
  type As Integer
  p_obj As Pointer
End Struct
Public Sub callback(p_event As Libvlc_event_t, p_data As Pointer)
  Me.Text = "Event fired"
End

Public Sub ButtonPlay_Click()
  XInitThreads() '# https://forum.videolan.org/viewtopic.php?t=136443
  inst = libvlc_new(0, Null)
  m = libvlc_media_new_path(inst, "/home/user/Videos/first_vid.mp4")
  mp = libvlc_media_player_new_from_media(m)
  event_manager = libvlc_media_player_event_manager(mp)
  libvlc_event_attach(event_manager, MediaPlayerPaused, callback, Null)
  Dim id As Integer = DrawingArea1.Id
  libvlc_media_player_set_xwindow(mp, id)
  libvlc_media_player_play(mp)
End

Public Sub ToggleButtonPause_Click()
  libvlc_media_player_pause(mp)
End
The vlc event manager tries to call the callback-function when video is paused but gambas will crash with a segmentation fault. I think it's this part that needs to be fixed:
Public Struct Libvlc_event_t
  type As Integer
  p_obj As Pointer
End Struct
Public Sub callback(p_event As Libvlc_event_t, p_data As Pointer)
  Me.Text = "Event fired"
End
p_event is some kind of struct https://videolan.videolan.me/vlc/libvlc ... ource.html but I am having trouble defining it in Gambas. But I don't really need the information stored in the struct. Is there a way to fool libvlc to just write that data to oblivion and be able to continue without crashing?
vuott
Posts: 262
Joined: Wednesday 5th April 2017 6:07pm
Location: European Union

Re: External C-Libary and Events

Post by vuott »

:? Opsss...I saw your last two posts only today.
Anyway, I was able to eliminate the error when clicking on the "ToggleButton" to pause the video file.
I made the following changes.

1) The Structure "Libvlc_event_t" of the VLC library contains, as a third member a "Union" that occupies 16 bytes. In the Structure, which you reproduced in Gambas, I simply declared that third member as a "Pointer".
Here it is:
Public Struct Libvlc_event_t
  type As Integer
  p_obj As Pointer
  u As Pointer
End Struct


2) It is also necessary to add the external function "libvlc_event_detach()" in the routine "ToggleButtonPause_Click()", when pausing the execution of the video file (it should be placed after the external function "libvlc_media_player_pause()"); as well as to call up the external function "libvlc_event_attach()". when resuming the execution of the video after pausing.

3) In addition, it was necessary to correctly arrange the command lines within the routine "Public Sub ToggleButtonPause_Click()".

4) Here is the :? new piece of code:
.......
Private Extern libvlc_event_detach(p_event_manager As Pointer, i_event_type As Integer, f_callback As Pointer, user_data As Pointer) As Integer
......


Public Sub callback(p_event As Libvlc_event_t, p_data As Pointer)

End


Public Sub Button1_Click()
  XInitThreads() '# https://forum.videolan.org/viewtopic.php?t=136443
  inst = libvlc_new(0, Null)
  m = libvlc_media_new_path(inst, "/path/of/video/file")
  mp = libvlc_media_player_new_from_media(m)
  event_manager = libvlc_media_player_event_manager(mp)
  libvlc_event_attach(event_manager, MediaPlayerPaused, callback, Null)
  Dim id As Integer = DrawingArea1.Id
  libvlc_media_player_set_xwindow(mp, id)
  libvlc_media_player_play(mp)
End
 
Public Sub ToggleButtonPause_Click()

  If ToggleButtonPause.Value Then 
    libvlc_media_player_pause(mp)
    libvlc_event_detach(event_manager, MediaPlayerPaused, callback, Null)
  Else 
    libvlc_event_attach(event_manager, MediaPlayerPaused, callback, Null)
    libvlc_media_player_play(mp)
  Endif

End


5) Now it works ! :)
Last edited by vuott on Sunday 29th October 2023 10:20pm, edited 1 time in total.
Europaeus sum !

Amare memorentes atque deflentes ad mortem silenter labimur.
JumpyVB
Posts: 75
Joined: Friday 11th September 2020 9:09am

Re: External C-Libary and Events

Post by JumpyVB »

vuott wrote: Thursday 26th October 2023 3:37pmNow it works!
I can confirm. Thank you.
Post Reply