Closed radiolondra closed 3 years ago
It should be possible; although you may need to do some poking around for work out the details.
Toga has a 3 layer architecture:
So - the HWND will be a property of the native layer on Windows.
If you start with a Toga Box as the widget you're trying to fill with the video content, then the native implementation on WinForms will be a Panel. You can then use the .Handle
property of winforms.Panel to get to the HWND for the window.
So - if you instantiate box = toga.Box()
, then box._impl.native.Handle
will give you the Handle of the native window (on Winforms, anyway; there will be something analogous on other platforms).
I'm not 100% sure what manipulation you will need to do to turn the value provided by Handle
into something that VLC will accept; if you're lucky, it might just be the value of Handle
. Combine this with some platform-checking code (like you have in your step 4), and you should be done.
The pro-level step would be take that code, and wrap it up as a widget that handles the platform-checking for you. That way you could expose a "VLCView" widget (or similar), and let Toga manage the platform identification. Two examples of this are toga-chart, and the Bitmap widget in the Yorkshire4 code.
If you get this working, let us know - it would be good to capture this knowledge as documentation, (or better yet, as a widget). We probably won't add a VLC widget to the Toga core because of the external library dependency - but I can definitely see a place for it as a standalone widget (like toga-chart).
I wrote a simple test app which works fine indeed (Windows 10):
import toga
import vlc
from toga.style.pack import CENTER, COLUMN, ROW, Pack
class Player(toga.App):
def startup(self):
self.main_window = toga.MainWindow(title=self.name)
self.player_panel = toga.Box(style=Pack(flex=1))
self.player_hwnd = self.player_panel._impl.native.Handle # IntPtr
self.Instance = vlc.Instance()
self.player = self.Instance.media_player_new()
self.player.set_hwnd(str(self.player_hwnd))
self.filename = "https://woolyss.com/f/caminandes-1-llama-drama-av1-opus.webm"
box = toga.Box(
children=[
toga.Box(
children=[
toga.Button('Go', on_press=self.play_video, style=Pack(width=50, padding_left=5)),
],
style=Pack(
direction=ROW,
alignment=CENTER,
padding=5,
)
),
self.player_panel,
],
style=Pack(
direction=COLUMN
)
)
self.main_window.content = box
# Show the main window
self.main_window.show()
def play_video(self, widget):
media = self.Instance.media_new(self.filename)
self.player.set_media(media)
self.player.play() # hit the player button
def main():
return Player('VLC Player Test', 'org.togatest.vlc')
if __name__ == '__main__':
main().main_loop()
This is obviously just the tip of the iceberg... more work and tests are needed to implement the same at least for MacOS and Linux. Peraphs some headaches more to implement this in Android and iOS.
Just a question: does Toga offer a native video player?
Nice work! Hopefully the macOS and Linux versions won't be that much more difficult - the only piece that will be significantly different is what comes after .native
on each platform. Android and iOS support will be very difficult, as you'll need to manage getting the VLC libraries in place.
Toga doesn't currently have a native video player - but that's definitely on our wish list.
I forgot to mention (for who is interested) that, to have the code above working, you need to have VLC installed. You can use VLC portable version too (and put it wherever you want), but you need to have the VLC folder in PATH
and create the following environ variables:
PYTHON_VLC_LIB_PATH - the path and filename of the libvlc library (for example in Windows: C:\vlc\App\vlc\libvlc.dll)
PYTHON_VLC_MODULE_PATH - the path of the VLC executable (for example in Windows: C:\vlc\App\vlc)
In this way, you could distribute the VLC portable folder together with your app. The app setup could create and set the new environment variables and add the distributed VLC folder to the target machine PATH.
Question preamble
Using
python-vlc
andTkinter
I can easily do this job in 5 steps (with VLC installed or needed libs in the right paths):Step 1 Simply create a panel, inside the app's main window, where the VLC player will play the video:
Step 2 Then create the VLC player:
Step 3 set the media I want to play:
Step 4 set the window's id where to render the VLC player output (this is the subject of my question):
Step 5 and finally play the video inside the videopanel:
self.player.play()
Now the Question
The most important step is
Step 4
, where weassign the videopanel id to the vlc player hwnd
. Can I do the same using Toga?