首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将libvlcpp嵌入到wx(v3)面板/框架中

如何将libvlcpp嵌入到wx(v3)面板/框架中
EN

Stack Overflow用户
提问于 2020-12-21 16:15:53
回答 1查看 172关注 0票数 0

我想使用wx (版本3及以上)和libvlcpp制作简单的跨平台播放器,但我不知道如何在wx中将libvlcpp窗口绑定到面板(即框架内)。

代码语言:javascript
运行
复制
 main_window *frame = new main_window(nullptr,wxID_ANY,wxT("Player"));

VLC::Instance instance = VLC::Instance(0, nullptr);
VLC::Media media = VLC::Media(instance, "/home/projects/vlc_test/ap.mp4", VLC::Media::FromPath);
VLC::MediaPlayer mp = VLC::MediaPlayer(media);
// frame->SetExtraStyle(4);
mp.setHwnd(frame->m_panel_vlc->GetHandle());  // this is not working !!!, btw m_panel_vlc is a public member

while(mp.play()){}

vlc_stop(mp); // a wraper for stopping

frame->Show(true); 

一些输出:

代码语言:javascript
运行
复制
[h264 @ 0x7f6b087ffd00] [0000000002454130] main input error: input control fifo overflow, trashing type=0
thread_get_buffer() failed
[0000000002454130] main input error: input control fifo overflow, trashing type=0
[h264 @ 0x7f6b087ffd00] decode_slice_header error
[h264 @ 0x7f6b087ffd00] no frame!
[0000000002454130] main input error: input control fifo overflow, trashing type=0```
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-22 12:05:55

下面是一个使用vlcpp绘制到wxWidgets窗口的完整示例(至少对于windows是这样)。它基于libvlc example,但我将其改为使用vlcpp,并使用了一些稍微更现代的wxWidgets特性。

代码语言:javascript
运行
复制
#include <wx/wx.h>
#include <wx/filename.h>

#ifdef __WXGTK__
    #include <gdk/gdkx.h>
    #include <gtk/gtk.h>
#endif

#include <vlcpp/vlc.hpp>

#include <climits>

#define TIMELINE_MAX (INT_MAX-9)
#define VOLUME_MAX 100

wxDEFINE_EVENT(vlcEVT_POS,wxThreadEvent);
wxDEFINE_EVENT(vlcEVT_END,wxThreadEvent);

static wxEvtHandler* gs_handler = NULL;

void OnPositionChanged_VLC(float f)
{
    if ( gs_handler )
    {
        wxThreadEvent* event = new wxThreadEvent(vlcEVT_POS);
        event->SetPayload<float>(f);
        wxQueueEvent(gs_handler,event);
    }
}

void OnEndReached_VLC()
{
    if ( gs_handler )
    {
        wxThreadEvent* event = new wxThreadEvent(vlcEVT_END);
        wxQueueEvent(gs_handler,event);
    }
}

class MainWindow : public wxFrame {
public:
    MainWindow(const wxString& title);

private:
    // Event handlers
    void OnPositionChanged(wxThreadEvent& event);
    void OnEndReached(wxThreadEvent& event);

    void OnOpen(wxCommandEvent& event);
    void OnPlayPause(wxCommandEvent& event);
    void OnStop(wxCommandEvent& event);
    void OnPositionChanged_USR(wxCommandEvent& event);
    void OnVolumeChanged(wxCommandEvent& event);
    void OnVolumeClicked(wxMouseEvent& event);
    void OnTimelineClicked(wxMouseEvent& event);
    void OnRendererWinCreated(wxWindowCreateEvent& event);

    // Helper functions.
    void Play();
    void Pause();
    void Stop();
    void SetTimeline(float value);
    void BindTimeline();
    void UnbindTimeline();

    // Video player controls.
    wxButton* m_playPauseButton;
    wxButton* m_stopButton;
    wxSlider* m_timeline;
    wxSlider* m_volumeSlider;
    wxWindow* m_playerWidget;

    // VLC objects
    VLC::Instance m_vlc;
    VLC::MediaPlayer m_player;
};

MainWindow::MainWindow(const wxString& title) : wxFrame(NULL, wxID_ANY, title)
{
    // Setup menubar.
    wxMenuBar* menubar = new wxMenuBar;
    wxMenu*file = new wxMenu;
    file->Append(wxID_OPEN, "&Open");
    menubar->Append(file, "&File");
    SetMenuBar(menubar);
    Bind(wxEVT_MENU, &MainWindow::OnOpen, this, wxID_OPEN, wxID_OPEN);

    // Create the main background panel for the frame.
    wxPanel* bgPanel = new wxPanel(this, wxID_ANY);

    // Create the window the VLC will draw to.
    m_playerWidget = new wxWindow(bgPanel, wxID_ANY);

    // Create the timeline slider.
    m_timeline = new wxSlider(bgPanel, wxID_ANY, 0, 0, TIMELINE_MAX);

    // Create play button, the stop button, and the volume slider.
    m_playPauseButton = new wxButton(bgPanel, wxID_ANY, "Play");
    m_stopButton = new wxButton(bgPanel, wxID_ANY, "Stop");
    m_volumeSlider = new wxSlider(bgPanel, wxID_ANY, VOLUME_MAX, 0, VOLUME_MAX);


    // Set the video window black and disable the timeline and buttons.
    m_playerWidget->SetBackgroundColour(*wxBLACK);
    m_timeline->Enable(false);
    m_playPauseButton->Enable(false);
    m_stopButton->Enable(false);


    // Use sizers to arrange the controls on the frame.
    wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
    vbox->Add(m_playerWidget, wxSizerFlags(1).Expand().Border(wxALL));
    vbox->Add(m_timeline, wxSizerFlags(0).Expand().Border(wxLEFT|wxRIGHT|wxBOTTOM));

    wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
    hbox->Add(m_playPauseButton, wxSizerFlags(0).Border(wxLEFT|wxRIGHT|wxBOTTOM));
    hbox->Add(m_stopButton,wxSizerFlags(0).Border(wxRIGHT|wxBOTTOM));
    hbox->AddStretchSpacer();
    hbox->Add(m_volumeSlider,wxSizerFlags(0).Border(wxRIGHT|wxBOTTOM));
    vbox->Add(hbox,wxSizerFlags(0).Expand());

    bgPanel->SetSizer(vbox);
    Layout();


    // Bind event handlers for the wxWidgets controls.
    m_playPauseButton->Bind(wxEVT_BUTTON, &MainWindow::OnPlayPause, this);
    m_stopButton->Bind(wxEVT_BUTTON, &MainWindow::OnStop, this);
    m_volumeSlider->Bind(wxEVT_SLIDER,&MainWindow::OnVolumeChanged,this);

    BindTimeline();
    m_timeline->Bind(wxEVT_LEFT_UP, &MainWindow::OnTimelineClicked,this);
    m_volumeSlider->Bind(wxEVT_LEFT_UP, &MainWindow::OnVolumeClicked,this);

    // Bind the events that will be thrown from VLC callbacks.
    Bind(vlcEVT_POS, &MainWindow::OnPositionChanged, this);
    Bind(vlcEVT_END, &MainWindow::OnEndReached, this);


    // Set up the VLC objects.
    m_vlc = VLC::Instance(0, nullptr);
    m_player = VLC::MediaPlayer(m_vlc);

#ifdef __WXGTK__
    // On GTK+, we have to wait until the window is actually created before we
    // can tell VLC to use it for output. So wait for the window create event.
    m_playerWidget->Bind(wxEVT_CREATE, &MainWindow::OnRendererWinCreated, this);
#elif defined(__WXMSW__)
    m_player.setHwnd(m_playerWidget->GetHandle());
#endif

    // Get the player's event manager and register to callbacks.
    VLC::MediaPlayerEventManager& eventManager = m_player.eventManager();
    eventManager.onPositionChanged(OnPositionChanged_VLC);
    eventManager.onEndReached(OnEndReached_VLC);

    // Set this frame to a global variable so that it can be used with the
    // VLC callbacks.
    gs_handler = this;
}

void MainWindow::OnRendererWinCreated(wxWindowCreateEvent& event)
{
#ifdef __WXGTK__
    m_player.setXwindow(gdk_x11_window_get_xid(gtk_widget_get_window(m_playerWidget->GetHandle())));

    m_playerWidget->Unbind(wxEVT_CREATE,&MainWindow::OnRendererWinCreated,this);
#endif
}

void MainWindow::OnPositionChanged(wxThreadEvent& event)
{
    float factor = event.GetPayload<float>();
    SetTimeline(factor);
}

void MainWindow::OnEndReached(wxThreadEvent& event)
{
    Stop();
}

void MainWindow::OnOpen(wxCommandEvent& event)
{
    wxFileDialog openFileDialog(this, "Choose File");

    if (openFileDialog.ShowModal() == wxID_CANCEL)
    {
        return;
    }
    else
    {
        wxFileName filename = wxFileName::FileName(openFileDialog.GetPath());
        filename.MakeRelativeTo();
        std::string s2(filename.GetFullPath().utf8_str());

        VLC::Media media(m_vlc, s2, VLC::Media::FromPath);
        m_player.setMedia(media);
        Play();
    }
}

void MainWindow::OnPlayPause(wxCommandEvent& event)
{
    if ( m_player.isPlaying () )
    {
        Pause();
    }
    else
    {
        Play();
    }
}

void MainWindow::OnStop(wxCommandEvent& event)
{
    Stop();
}

void MainWindow::OnPositionChanged_USR(wxCommandEvent& event)
{
    m_player.setPosition((float) event.GetInt() / (float) TIMELINE_MAX);
}

void MainWindow::OnVolumeChanged(wxCommandEvent& event)
{
    m_player.setVolume(m_volumeSlider->GetValue());
}

void MainWindow::OnVolumeClicked(wxMouseEvent& event)
{
    wxSize size = m_volumeSlider->GetSize();
    float position = (float) event.GetX() / (float) size.GetWidth();
    int volume = static_cast<int>(position*VOLUME_MAX);
    m_volumeSlider->SetValue(volume);
    m_player.setVolume(volume);
    event.Skip();
}

void MainWindow::OnTimelineClicked(wxMouseEvent& event)
{
    wxSize size = m_timeline->GetSize();
    float position = (float) event.GetX() / (float) size.GetWidth();
    m_player.setPosition(position);
    SetTimeline(position);
    event.Skip();
}

void MainWindow::Play()
{;
    m_player.play();
    m_playPauseButton->SetLabel("Pause");
    m_playPauseButton->Enable(true);
    m_stopButton->Enable(true);
    m_timeline->Enable(true);
}

void MainWindow::Pause()
{
    m_player.pause();
    m_playPauseButton->SetLabel("Play");
}

void MainWindow::Stop()
{
    Pause();
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
    m_player.stopAsync();
#else
    m_player.stop();
#endif
    m_stopButton->Enable(false);
    SetTimeline(0.0);
    m_timeline->Enable(false);
}

void MainWindow::SetTimeline(float value) {
    if ( value < 0.0 )
    {
        value = 0.0;
    }
    if ( value > 1.0 )
    {
        value = 1.0;
    }

    UnbindTimeline();
    m_timeline->SetValue((int) (value * TIMELINE_MAX));
    BindTimeline();
}

void MainWindow::BindTimeline()
{
    m_timeline->Bind(wxEVT_SLIDER, &MainWindow::OnPositionChanged_USR, this);
}

void MainWindow::UnbindTimeline()
{
    m_timeline->Unbind(wxEVT_SLIDER, &MainWindow::OnPositionChanged_USR, this);
}

class MyApp : public wxApp {
    public:
        virtual bool OnInit();
};

bool MyApp::OnInit() {
    MainWindow* mainWindow = new MainWindow("wxWidgets libVLC demo");
    mainWindow->Show();
    return true;
}

wxIMPLEMENT_APP(MyApp);

在linux mint上使用wxGTK3,它看起来是这样的:

我从来没有用过vlcpp,所以我不是这方面的专家。但它不允许将数据对象传递给回调函数。使用wxWidgets的c接口,您可以使用此数据对象传递一个vlc事件处理程序,然后在回调中使用该事件处理程序将vlc事件传递给libvlc。由于vlcpp不允许传递数据对象,因此我不得不为wxWidgets事件处理程序使用一个丑陋的全局变量。

除非我遗漏了什么,并且有一种方法可以为vlc回调传递数据对象,否则这看起来就像是vlcpp api中的一个重大缺陷。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65389423

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档