如何将文件传递到 GJS/GTK4 中的视频小部件

问题描述 投票:0回答:1

我正在尝试向 Gnome 应用程序添加基本视频播放功能。这是我的第一个 Gnome 应用程序,我正在使用 GJS + GTK4

整个应用程序最终将有大约 10 个视频文件(本地 mp4 文件)。我将 GTK 视频组件 (GTKvideo) 包裹在我自己的小部件 (“FbrVideoWidget”) 中。目前,我在应用程序的初始视图上有一个小部件的测试实例。据我所知,小部件呈现(我只看到黑色,我相信这是没有控件或文件的视频播放器)。

问题 当尝试将文件应用到视频播放器实例时,我没有看到任何有关成功/失败的日志警告,并且在记录视频实例时,它仍然看起来像一个空对象(之前和之后)。所以我不知道我是否没有正确访问视频元素或没有正确传递文件。

旁注,在文件尝试之后,我还尝试以编程方式开始播放,这确实产生日志错误:

(org.example.filebrowser:2): Gtk-CRITICAL **: 13:04:54.116: Media stream of type 'GtkNoMediaFile' does not implement GtkMediaStream::play

这对我来说实际上似乎是一个好兆头,因为我将此解释为视频元素实际上已加载,但它没有正确的视频源。

问题鉴于我的要求(播放本地mp4文件),mp4文件应该保存在哪里?

问题 无论文件位于何处,我是否绝对需要在某个地方注册它们?我想这取决于我如何尝试获取应用程序中的文件。

问题 如何通过小部件包装获取本地文件并将其传递到视频播放器中?

我看到了不同的方法,但没有明确的答案。

// Get path to mp4 file in my OS home dir
const filepath = GLib.build_filenamev([GLib.get_home_dir(), value]);
log('filepath is: ', filepath);

// 1 - Apply video file: new_for_uri
this._videoActual.file = Gio.File.new_for_uri(filepath);

// 2 - Apply video file: new_for_path
//this._videoActual.file = Gio.File.new_for_path(filepath);

/// --- or ---

// 3 - Apply video file: set_resource
// Tried accessing a resource defined in data/ui/
// this._videoActual.set_resource('/org/example/filebrowser/ui/file_example_MP4_640_3MG.mp4')

相关代码

我排除了注册表文件。

/src/VideoWidget.js

import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
import Gio from "gi://Gio";
import GLib from 'gi://GLib';

export const VideoWidget = GObject.registerClass({
    GTypeName: 'FbrVideoWidget',
    CssName: 'video',
    Template: 'resource:///org/example/filebrowser/ui/VideoWidget.ui',
    InternalChildren: ['videoActual'],
    Properties: {
        VideoFile: GObject.ParamSpec.string(
            'video-file', // name
            'Video File', // nick
            'The text displayed by the widget', // blurb
            GObject.ParamFlags.READWRITE, // flags
            '' // default value
        ),
    }
}, class extends Gtk.Widget {

    constructor(params={}) {
        super(params);

        log('Video mounted');

    }

    get videoFile() {
        log('get videoFile(): ', this._videoFile);
        return this._videoFile;
    }

    set videoFile(value) {

        // Setting local stuff
        log('set videoFile() value: ', value);
        if (this._videoFile === value) return;
        this._videoFile = value;

        // Getting filepath of requested video file
        const filepath = GLib.build_filenamev([GLib.get_home_dir(), value]);
        log('filepath is: ', filepath);

        // Apply file to video player using new_for_uri
        this._videoActual.file = Gio.File.new_for_uri(filepath);

        // Apply file to video player using new_for_path
        //this._videoActual.file = Gio.File.new_for_path(filepath);

        // Or trying to use declared app resource (declared in `org.example.filebrowser.data.gresource.xml`):
this._videoActual.set_resource('/org/example/filebrowser/ui/file_example_MP4_640_3MG.mp4')

        
        //this._videoActual.set_autoplay(true);

        // LOG ERROR OCCURS HERE
        this._videoActual.media_stream.play();

        this.notify('video-file');
    }

});

/data/ui/VideoWidget.ui

<?xml version="1.0" encoding="UTF-8"?>
<interface>
    <requires lib="gtk" version="4.0"/>
    <template class="FbrVideoWidget">
        <property name="layout-manager">
            <object class="GtkBoxLayout">
                <property name="orientation">vertical</property>
            </object>
        </property>
        <object class="GtkBox">
            <property name="orientation">1</property>
            <property name="halign">3</property>
            <child>
                <object class="GtkVideo" id="videoActual">
                    <property name="file" />
                    <property name="autoplay">true</property>
                    <property name="loop">true</property>
                    <property name="width-request">540</property>
                    <property name="height-request">540</property>
                </object>
            </child>
        </object>
    </template>
</interface>

视频小部件的测试实例(应用程序中的初始视图)

<property name="child">
    <object class="FbrVideoWidget" id="videoTest">
        <property name="video-file">file_example_MP4_640_3MG.mp4</property>
    </object>
</property>

org.example.filebrowser.data.gresource.xml

中声明的应用程序资源
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
    <gresource prefix="/org/example/filebrowser">
        <file>css/style.css</file>
        <file>ui/VideoWidget.ui</file>
        <file>ui/WelcomeWidget.ui</file>
        <file>ui/Window.ui</file>
        <file>ui/file_example_MP4_640_3MG.mp4</file>
    </gresource>
    <gresource prefix="/org/example/filebrowser/icons/scalable/actions">
        <file alias="filebrowser-welcome-symbolic.svg">icons/welcome-symbolic.svg</file>
    </gresource>
</gresources>

screenshot of the video player problem

gtk gtk4 gjs
1个回答
0
投票

好的,第一步是编写稍后将在选项卡中实例化的自定义小部件。这里我们有一个问题,那就是缺少

"parent = "
,还有一件奇怪的事情对我来说似乎没有必要:

<property name="layout-manager">
   <object class="GtkBoxLayout">
       <property name="orientation">vertical</property>
   </object>
</property>

更正后的版本是:

/data/ui/VideoWidget.ui

<interface>
  <requires lib="gtk" version="4.0"/>
  <template class="FbrVideoWidget" parent="GtkBox">
    <property name="orientation">1</property>
    <property name="halign">3</property>
    <child>
      <object class="GtkVideo" id="videoActual">
        <property name="autoplay">true</property>
        <property name="loop">true</property>
        <property name="width-request">540</property>
        <property name="height-request">540</property>
      </object>
    </child>
  </template>
</interface>

我没有使用 GJS 的经验,但除了“属性”部分之外,实例化似乎是正确的,我不知道它是否正确,但似乎没有必要。这给我们留下了:

export const VideoWidget = GObject.registerClass({
    GTypeName: 'FbrVideoWidget',
    CssName: 'video',
    Template: 'resource:///org/example/filebrowser/ui/VideoWidget.ui',
    InternalChildren: ['videoActual'],
}, class FbrVideoWidget extends Gtk.Box...

在这种情况下,要访问视频的“文件”属性,而不是:

this._videoFile = value;

他会是

this._videoActual.file = value;

我对GJS的了解还不够,无法检查其余的,但我相信这两点是主要的。我使用基本的 Python 代码测试了这个 /data/ui/VideoWidget.ui 来加载视频,并且它有效。

© www.soinside.com 2019 - 2024. All rights reserved.