diff --git a/slave/go.mod b/slave/go.mod new file mode 100644 index 0000000..3c6d7b1 --- /dev/null +++ b/slave/go.mod @@ -0,0 +1,8 @@ +module slave + +go 1.18 + +require ( + github.com/adrg/libvlc-go/v3 v3.1.5 + github.com/gotk3/gotk3 v0.6.1 +) diff --git a/slave/go.sum b/slave/go.sum new file mode 100644 index 0000000..f94ffbd --- /dev/null +++ b/slave/go.sum @@ -0,0 +1,4 @@ +github.com/adrg/libvlc-go/v3 v3.1.5 h1:TGO0dvubmLCSE4ocOtJYMBlPYALm8aGMkCuDZ6cXnM0= +github.com/adrg/libvlc-go/v3 v3.1.5/go.mod h1:xJK0YD8cyMDejnrTFQinStE6RYCV1nlfS8KmqTpszSc= +github.com/gotk3/gotk3 v0.6.1 h1:GJ400a0ecEEWrzjBvzBzH+pB/esEMIGdB9zPSmBdoeo= +github.com/gotk3/gotk3 v0.6.1/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q= diff --git a/slave/main.go b/slave/main.go new file mode 100644 index 0000000..ae95abd --- /dev/null +++ b/slave/main.go @@ -0,0 +1,147 @@ +package main + +import ( + "log" + "os" + + vlc "github.com/adrg/libvlc-go/v3" + "github.com/gotk3/gotk3/cairo" + "github.com/gotk3/gotk3/glib" + "github.com/gotk3/gotk3/gtk" +) + +const appID = "com.github.libvlc-go.gtk3-media-player-example" + +func builderGetObject(builder *gtk.Builder, name string) glib.IObject { + obj, _ := builder.GetObject(name) + return obj +} + +func assertErr(err error) { + if err != nil { + log.Panic(err) + } +} + +func assertConv(ok bool) { + if !ok { + log.Panic("invalid widget conversion") + } +} + +func playerReleaseMedia(player *vlc.Player) { + player.Stop() + if media, _ := player.Media(); media != nil { + media.Release() + } +} + +func main() { + // Initialize libVLC module. + err := vlc.Init("--quiet", "--no-xlib") + assertErr(err) + + // Create a new player. + player, err := vlc.NewPlayer() + assertErr(err) + + // Create new GTK application. + app, err := gtk.ApplicationNew(appID, glib.APPLICATION_FLAGS_NONE) + assertErr(err) + + app.Connect("activate", func() { + // Load application layout. + builder, err := gtk.BuilderNewFromFile("layout.glade") + assertErr(err) + + // Get application window. + appWin, ok := builderGetObject(builder, "appWindow").(*gtk.ApplicationWindow) + assertConv(ok) + + // Get play button. + playButton, ok := builderGetObject(builder, "playButton").(*gtk.Button) + assertConv(ok) + + // Add builder signal handlers. + signals := map[string]interface{}{ + "onRealizePlayerArea": func(playerArea *gtk.DrawingArea) { + // Set window for the player. + playerWindow, err := playerArea.GetWindow() + assertErr(err) + err = setPlayerWindow(player, playerWindow) + assertErr(err) + }, + "onDrawPlayerArea": func(playerArea *gtk.DrawingArea, cr *cairo.Context) { + cr.SetSourceRGB(0, 0, 0) + cr.Paint() + }, + "onActivateOpenFile": func() { + fileDialog, err := gtk.FileChooserDialogNewWith2Buttons( + "Choose file...", + appWin, gtk.FILE_CHOOSER_ACTION_OPEN, + "Cancel", gtk.RESPONSE_DELETE_EVENT, + "Open", gtk.RESPONSE_ACCEPT) + assertErr(err) + defer fileDialog.Destroy() + + fileFilter, err := gtk.FileFilterNew() + assertErr(err) + fileFilter.SetName("Media files") + fileFilter.AddPattern("*.mp4") + fileFilter.AddPattern("*.mp3") + fileDialog.AddFilter(fileFilter) + + if result := fileDialog.Run(); result == gtk.RESPONSE_ACCEPT { + // Release current media, if any. + playerReleaseMedia(player) + + // Get selected filename. + filename := fileDialog.GetFilename() + + // Load media and start playback. + if _, err := player.LoadMediaFromPath(filename); err != nil { + log.Printf("Cannot load selected media: %s\n", err) + return + } + + player.Play() + playButton.SetLabel("gtk-media-pause") + } + }, + "onActivateQuit": func() { + app.Quit() + }, + "onClickPlayButton": func(playButton *gtk.Button) { + if media, _ := player.Media(); media == nil { + return + } + + if player.IsPlaying() { + player.SetPause(true) + playButton.SetLabel("gtk-media-play") + } else { + player.Play() + playButton.SetLabel("gtk-media-pause") + } + }, + "onClickStopButton": func(stopButton *gtk.Button) { + player.Stop() + playButton.SetLabel("gtk-media-play") + }, + } + builder.ConnectSignals(signals) + + appWin.ShowAll() + app.AddWindow(appWin) + }) + + // Cleanup on exit. + app.Connect("shutdown", func() { + playerReleaseMedia(player) + player.Release() + vlc.Release() + }) + + // Launch the application. + os.Exit(app.Run(os.Args)) +} \ No newline at end of file diff --git a/slave/main.py b/slave/main.py new file mode 100644 index 0000000..b3a78be --- /dev/null +++ b/slave/main.py @@ -0,0 +1,42 @@ + +# importing vlc module +from email import message +from pydoc import cli +from statistics import median +import vlc +from time import sleep +import paho.mqtt.client as mqtt +from video import Video +import multiprocessing + + +class App: + def __init__(self, client): + self.client = client + self.video = Video(4000, 1000) + + def on_connect(self, client, userdata, flags, rc): + print("Connected with result code "+str(rc)) + self.client.subscribe("video") + + + def on_message(self, client, userdata, msg): + print(msg.topic+" "+str(msg.payload)) + if msg.payload == b'start': + print("Start") + self.video.setVideo("slave/sample-mp4-file.mp4") + self.x = multiprocessing.Process(target = self.video.start) + self.x.start() + + elif msg.payload == b'stop': + print("Stop") + self.x.terminate() + +client = mqtt.Client() +app = App(client) +client.on_connect = app.on_connect +client.on_message = app.on_message + +client.connect("10.173.54.35", 1883, 60) + +client.loop_forever() \ No newline at end of file diff --git a/slave/sample-mp4-file.mp4 b/slave/sample-mp4-file.mp4 new file mode 100644 index 0000000..24b738c Binary files /dev/null and b/slave/sample-mp4-file.mp4 differ diff --git a/slave/video.py b/slave/video.py new file mode 100644 index 0000000..102a4b9 --- /dev/null +++ b/slave/video.py @@ -0,0 +1,66 @@ +from random import randint +import cv2 +import numpy as np +import os +import multiprocessing +import time + +class Video: + def __init__(self, x, y): + self.x = x + self.y = y + + def setVideo(self, path): + self.path = path + + def start(self): + self.run = True + self.cap = cv2.VideoCapture(self.path) + # Check if camera opened successfully + if (self.cap.isOpened()== False): + print("Error opening video file") + + totalframecount= int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT)) + + print("The total number of frames in this video is ", totalframecount) + + # self.cap.set(cv2.CAP_PROP_POS_FRAMES, randint(0, totalframecount* 0.9)) + + # Read until video is completed + while(self.cap.isOpened() and self.run): + + # Capture frame-by-frame + ret, frame = self.cap.read() + if ret == True: + + # Display the resulting frame + + cv2.namedWindow("window", cv2.WND_PROP_FULLSCREEN) + cv2.moveWindow("window", self.x, self.y) + cv2.setWindowProperty("window",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN) + + cv2.imshow("window", frame) + + # Break the loop + else: + break + + def stop(self): + self.run = False + self.cap.release() + + # Closes all the frames + cv2.destroyAllWindows() + +if __name__ == "__main__": + video = Video(0, 0) + video.setVideo("slave/sample-mp4-file.mp4") + x = multiprocessing.Process(target = video.start) + x.start() + time.sleep(1) + x.terminate() + time.sleep(1) + x = multiprocessing.Process(target = video.start) + x.start() + time.sleep(1) + x.terminate() \ No newline at end of file