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

Check if window size changed and resize it #1037

Merged
merged 3 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions src/modules/sdl2/consumer_sdl2.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ static int consumer_play_video(consumer_sdl self, mlt_frame frame)
int video_off = mlt_properties_get_int(properties, "video_off");
int preview_off = mlt_properties_get_int(properties, "preview_off");
int display_off = video_off | preview_off;
uintptr_t window_id = mlt_properties_get_int(self->properties, "window_id");

if (self->running && !display_off) {
if (!self->sdl_window) {
Expand All @@ -585,13 +586,24 @@ static int consumer_play_video(consumer_sdl self, mlt_frame frame)
mlt_frame_get_image(frame, &image, &vfmt, &width, &height, 0);

if (self->running) {
// Determine window's new display aspect ratio
int x = mlt_properties_get_int(properties, "window_width");
if (x && x != self->window_width)
self->window_width = x;
x = mlt_properties_get_int(properties, "window_height");
if (x && x != self->window_height)
self->window_height = x;
// Determine window's new display aspect ratio, and resize if it's an existing window
int w = mlt_properties_get_int(properties, "window_width");
int h = mlt_properties_get_int(properties, "window_height");
int width_changed = (w && w != self->window_width);
int height_changed = (h && h != self->window_height);

if (width_changed || height_changed) {
if (width_changed) {
self->window_width = w;
}
if (height_changed) {
self->window_height = h;
}
if (window_id) {
SDL_SetWindowSize(self->sdl_window, self->window_width, self->window_height);
}
}

double this_aspect = (double) self->window_width / self->window_height;

// Get the display aspect ratio
Expand Down
142 changes: 142 additions & 0 deletions src/swig/python/play_gtk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import gi
import sys
import mlt7 as mlt

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GObject, GLib

VIDEO = 'video.mp4'

class VideoPlayer(Gtk.Window):
def __init__(self):
super().__init__(title="MLT Video Player")
self.set_default_size(800, 600)
self.connect("destroy", self.on_destroy)

# Initialize the mlt system
mlt.Factory().init()

# Create a default profile
self.profile = mlt.Profile()

# Create a producer for the video
self.producer = mlt.Producer(self.profile, VIDEO)
if self.producer.is_valid():
self.profile.from_producer(self.producer)
self.producer = mlt.Producer(self.profile, VIDEO)

# Create the consumer for rendering using SDL2
self.consumer = mlt.Consumer(self.profile, "sdl2")

# GTK Layout
self.layout = Gtk.VBox(spacing=6)
self.add(self.layout)

# Create the drawing area for the video
self.drawing_area = Gtk.DrawingArea()
self.drawing_area.set_size_request(800, 450)
self.drawing_area.connect("size-allocate",self.drawing_area_resized)
self.layout.pack_start(self.drawing_area, True, True, 0)
self.drawing_area.realize()
print(int(self.drawing_area.get_window().get_xid()))
self.consumer.set('window_id', str(self.drawing_area.get_window().get_xid()))

if not self.consumer.is_valid():
print("Failed to open the sdl2 consumer")
sys.exit(1)

# Create a multitrack playlist and set it to the tractor
self.playlist = mlt.Playlist(self.profile)
self.playlist.append(self.producer)

self.tractor = mlt.Tractor()
self.tractor.set_track(self.playlist, 0)

# Connect the producer to the consumer
self.consumer.connect(self.tractor)

# Control Buttons
controls_box = Gtk.HBox(spacing=6)
self.layout.pack_start(controls_box, False, False, 0)

# Play button
self.play_button = Gtk.Button.new_with_label("Play")
self.play_button.connect("clicked", self.play_video)
controls_box.pack_start(self.play_button, False, False, 0)

# Pause button
self.pause_button = Gtk.Button.new_with_label("Pause")
self.pause_button.connect("clicked", self.pause_video)
controls_box.pack_start(self.pause_button, False, False, 0)

# Stop button
self.stop_button = Gtk.Button.new_with_label("Stop")
self.stop_button.connect("clicked", self.stop_video)
controls_box.pack_start(self.stop_button, False, False, 0)

# Slider
self.timeline_slider = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, 0, 1000, 1)
self.timeline_slider.set_draw_value(False)
self.slider_handler_id = self.timeline_slider.connect("value-changed", self.on_slider_changed)
self.timeline_slider.connect("button-release-event", self.on_slider_button_release)
controls_box.pack_start(self.timeline_slider, True, True, 0)

# Timer to update the slider
self.update_timer = GLib.timeout_add(1000 // 24, self.update_slider)

# Start the consumer
self.consumer.start()
self.pause_video()

def drawing_area_resized(self, widget, _):
self.consumer.set('window_width', widget.get_allocated_width())
self.consumer.set('window_height', widget.get_allocated_height())

def update_slider(self):
position = self.consumer.position()
playtime = self.tractor.get_playtime()
if playtime > 0:
value = int((position / playtime) * 1000)
self.timeline_slider.handler_block(self.slider_handler_id)
self.timeline_slider.set_value(value)
self.timeline_slider.handler_unblock(self.slider_handler_id)
return True

def play_video(self, button):
self.tractor.set_speed(1)
self.consumer.set('volume', 1)

def pause_video(self, button=None):
if not self.consumer.is_stopped():
self.tractor.set_speed(0)
self.consumer.set('volume', 0)

def stop_video(self, button):
self.tractor.seek(0)
self.tractor.set_speed(0)
self.timeline_slider.set_value(0)

def on_slider_changed(self, slider):
value = slider.get_value()
self.consumer.set('volume', 0)
playtime = self.tractor.get_playtime()
self.tractor.seek(int((value / 1000.0) * playtime))

def on_slider_button_release(self, slider, _):
if not self.tractor.get_speed() == 0:
self.consumer.set('volume', 1)

def on_destroy(self, widget):
self.consumer.stop()
mlt.Factory().close()
Gtk.main_quit()

if __name__ == "__main__":
# Initialize GTK
GObject.threads_init()
Gtk.init(sys.argv)

# Create and run the video player
player = VideoPlayer()
player.show_all()
Gtk.main()
143 changes: 143 additions & 0 deletions src/swig/python/play_pyqt6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import mlt7 as mlt
import sys

from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QSlider, QStyle
from PyQt6.QtCore import Qt, QTimer

VIDEO = 'video.mp4'


class VideoPlayer(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("MLT Video Player")

layout = QVBoxLayout()

class video_viewer(QWidget):
"""The main window (QWidget) class"""
def __init__(self):
super().__init__()
self.setMinimumSize(380, 260)

def resizeEvent(self, event):
self.window().consumer.set('window_width', self.width())
self.window().consumer.set('window_height', self.height())
event.accept()

self.video_viewer = video_viewer()
layout.addWidget(self.video_viewer, 1)

buttons_layout = QHBoxLayout()

self.play_button = QPushButton()
self.play_button.setFlat(True)
self.play_button.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_MediaPlay))
self.play_button.clicked.connect(self.play_video)
buttons_layout.addWidget(self.play_button)

self.pause_button = QPushButton()
self.pause_button.setFlat(True)
self.pause_button.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_MediaPause))
self.pause_button.clicked.connect(self.pause_video)
buttons_layout.addWidget(self.pause_button)

self.stop_button = QPushButton()
self.stop_button.setFlat(True)
self.stop_button.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_MediaStop))
self.stop_button.clicked.connect(self.stop_video)
buttons_layout.addWidget(self.stop_button)

self.timeline_slider = QSlider(Qt.Orientation.Horizontal)
self.timeline_slider.setRange(0, 1000)
self.timeline_slider.sliderPressed.connect(self.stop_update_slider)
self.timeline_slider.sliderMoved.connect(self.timeline_slider_changed)
self.timeline_slider.sliderReleased.connect(self.set_volume_back_to_normal)
buttons_layout.addWidget(self.timeline_slider)

layout.addLayout(buttons_layout)

self.setLayout(layout)

self.timer = QTimer(self)
self.timer.timeout.connect(self.update_slider)

# Start the mlt system
mlt.Factory().init()

# Establish a default (usually "dv_pal") profile
self.profile = mlt.Profile()

# Create the producer
self.producer = mlt.Producer(self.profile, VIDEO)

if self.producer.is_valid():
# Derive a profile based on the producer
self.profile.from_producer(self.producer)
# Reload the producer using the derived profile
self.producer = mlt.Producer(self.profile, VIDEO)

# Create the consumer
self.consumer = mlt.Consumer(self.profile, "sdl2")
self.consumer.set('window_id', str(int(self.video_viewer.winId()))) # PyQt6 requires str or int for set('window_id')

if not self.consumer.is_valid():
print("Failed to open the sdl2 consumer")
sys.exit(1)

# Setup a multitrack
self.playlist = mlt.Playlist(self.profile)
self.playlist.append(self.producer)

self.tractor = mlt.Tractor()
self.tractor.set_track(self.playlist, 0)

# Connect the producer to the consumer
self.consumer.connect(self.tractor)

# Start the consumer
self.consumer.start()
self.pause_video()

def update_slider(self):
self.timeline_slider.setValue(int((self.consumer.position() / self.tractor.get_playtime()) * 1000))

def play_video(self):
self.tractor.set_speed(1)
self.consumer.set('volume', 1)
self.timer.start(int(1000 / 24))

def pause_video(self):
if not self.consumer.is_stopped():
self.tractor.set_speed(0)
self.consumer.set('volume', 0)

def stop_video(self):
self.tractor.seek(0)
self.tractor.set_speed(0)
self.timeline_slider.setValue(0)
self.timer.stop()

def timeline_slider_changed(self, value):
self.consumer.set('volume', 0)
self.tractor.seek(int((value / 1000.0) * self.tractor.get_playtime()))

def stop_update_slider(self):
self.timer.stop()

def set_volume_back_to_normal(self):
if not self.tractor.get_speed() == 0:
self.consumer.set('volume', 1)
self.timer.start(int(1000 / 24))

def closeEvent(self, event):
self.consumer.stop()
event.accept()

if __name__ == "__main__":
app = QApplication(sys.argv)

player = VideoPlayer()
player.show()

sys.exit(app.exec())
Loading