Need help with using `wxMediaCtrl`.

Do you have a question about makefiles, a compiler or IDE you are using and need to know how to set it up for wxWidgets or why it doesn't compile but other IDE's do ? Post your questions here.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Need help with using `wxMediaCtrl`.

Post by apoorv569 »

I am only about a week in learning C++, I have been learn python for last 2-3 months, I was using Tkinter for making a GUI music player application as a practice project, I recently discovered about wxWidgets, specifically wxPython, so I started using that instead of Tkinter, but I wanted to learn some stuff in future for which python is not really a good language. So I decided to learn C++, and I started using `wxWidgets` with C++, most of the code is carried over from my python version of the same application, I am still not very comfortable with C++, but I understand some things, so I finally made the GUI part of my application working yesterday, and I am trying to handle events, I started with a file dialog widget, so I can load songs in a list box widget, that is working, but today I started working on actually playing the selected item in list box widget, but I cannot seem to make `wxMediaCtrl` work, I don't understand how it works. For now I only have 2 `.cpp` files, one called `app.cpp` and other `frame.cpp`, in the `frame.cpp` file I only have one class called Frame, and the part where I am trying to setup `wxMediaCtrl` looks like this

In my `frame.hpp` header file I have

Code: Select all

#include <wx/mediactrl.h>

class Frame : public wxFrame
and somewhere down I have

Code: Select all

    protected:
       wxMediaCtrl* mediaCtrl;
and in my `frame.cpp` file I have

Code: Select all

    playButton = new wxButton(panel, 1000, wxT("|>"), wxDefaultPosition, wxDefaultSize, 0);
    playButton->Connect(1000, wxEVT_MEDIA_PLAY, (wxObjectEventFunction) (wxEventFunction) (wxMediaEventFunction) &Frame::Play);
and somewhere down I have

Code: Select all

mediaCtrl = new wxMediaCtrl(panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxEmptyString);
and somewhere even down the file I have this function

Code: Select all

void Frame::Play(wxMediaEvent& event)
{
//    stopped = false;

    int song_index = playlistBox->GetSelection();
    wxString song_str = playlistBox->GetString(song_index);

    std::string song;
    wxString wxsong;
    song = std::string(wxsong);

    song = "/home/apoorv/Music/mod/%s", "song_str";

//    std::cout << song << std::endl;

    mediaCtrl->Load(song);
    mediaCtrl->Play();

    event.Skip();

//    timer->Start(1000);
}
but when I try to compile it, it gives me error during linking

Code: Select all

/usr/include/wx-3.0/wx/mediactrl.h:137: undefined reference to `vtable for wxMediaCtrl'
/usr/bin/ld: /usr/include/wx-3.0/wx/mediactrl.h:138: undefined reference to `wxMediaCtrl::Create(wxWindow*, int, wxString const&, wxPoint const&, wxSize const&, long, wxString const&, wxValidator const&, wxString const&)'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
./build.sh: line 12: ./musicApp: No such file or directory
I am using Arch Linux, I have installed wxgtk3 package from pacman, for wxWidgets, and I am using Meson for configuring and compiling. I can provide a link for full code if needed.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Need help with using `wxMediaCtrl`.

Post by doublemax »

The error indicates that you didn't link the "media" library do your project.

How does your build command look like?
Can you build the "mediaplayer" sample that comes with wxWidgets?
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: Need help with using `wxMediaCtrl`.

Post by apoorv569 »

I tried building example here - https://github.com/wxWidgets/wxWidgets/ ... player.cpp

I tried using `gcc`

Code: Select all

❯ g++ wx.cpp
In file included from wx.cpp:40:
/usr/include/wx-3.0/wx/wxprec.h:12:10: fatal error: wx/defs.h: No such file or directory
   12 | #include "wx/defs.h"
      |          ^~~~~~~~~~~
compilation terminated.
then I copied my meson file and edited it to build this, then it gave this error

Code: Select all

❯ meson compile -j 1
Found runner: ['/usr/bin/ninja']
ninja: Entering directory `.'
[1/2] Compiling C++ object wx.p/wx.cpp.o
FAILED: wx.p/wx.cpp.o
g++ -Iwx.p -I. -I.. -I/usr/lib/wx/include/gtk2-unicode-3.0 -I/usr/include/wx-3.0 -fdiagnostics-color=always -pipe -Wall -Winvalid-pch -Wnon-virtual-dtor -g -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread -MD -MQ wx.p/wx.cpp.o -MF wx.p/wx.cpp.o.d -o wx.p/wx.cpp.o -c ../wx.cpp
../wx.cpp:77:14: fatal error: ../sample.xpm: No such file or directory
   77 |     #include "../sample.xpm"
      |              ^~~~~~~~~~~~~~~
compilation terminated.
ninja: build stopped: subcommand failed.

And for my own project I have a `meson.build` file that looks like this

Code: Select all

project('Music Player', 'cpp')

src = [

  'src/app.cpp',
  'src/frame.cpp',

  ]

wx = dependency('wxwidgets')

executable('musicApp', src,
  dependencies : [wx])
and I have a script that builds the project and runs it, it looks like this

Code: Select all

#! /bin/bash

# cd where the script is
cd "$(dirname "$0")"

# rm -r build
CXX=g++ meson build
cd build
meson compile -j 1

# run the program
./musicApp
Here is a link to my full project if it helps. - https://gitlab.com/apoorv569/cpp-projec ... c%20Player
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Need help with using `wxMediaCtrl`.

Post by doublemax »

I don't work under Linux myself, and i've never heard of meson files, so i can't help with this.

Try to get the wxWidgets sources and build the libraries yourself. Then building the samples with the provided makefiles should be easy.
https://wiki.wxwidgets.org/Compiling_an ... requisites

During the "configure" step check for messages regarding "gstreamer". If that's not found, the mediactrl support will be disabled.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7479
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Need help with using `wxMediaCtrl`.

Post by ONEEYEMAN »

Hi,
apoorv569 wrote: Tue Oct 20, 2020 6:47 pm I tried building example here - https://github.com/wxWidgets/wxWidgets/ ... player.cpp

I tried using `gcc`

Code: Select all

❯ g++ wx.cpp
In file included from wx.cpp:40:
/usr/include/wx-3.0/wx/wxprec.h:12:10: fatal error: wx/defs.h: No such file or directory
   12 | #include "wx/defs.h"
      |          ^~~~~~~~~~~
compilation terminated.
Are you using wxWidgets installed frpm the official repository or you build the library yourself?
If you build it yourself, the Makefile should be created for you inside wxWidgets/<builddir>/samples/mediactrl.
If not - try this:

Code: Select all

g++ mediactrl.cpp `wx-config --cxxflags --libs std,media` -o media
apoorv569 wrote: Tue Oct 20, 2020 6:47 pm then I copied my meson file and edited it to build this, then it gave this error

Code: Select all

❯ meson compile -j 1
Found runner: ['/usr/bin/ninja']
ninja: Entering directory `.'
[1/2] Compiling C++ object wx.p/wx.cpp.o
FAILED: wx.p/wx.cpp.o
g++ -Iwx.p -I. -I.. -I/usr/lib/wx/include/gtk2-unicode-3.0 -I/usr/include/wx-3.0 -fdiagnostics-color=always -pipe -Wall -Winvalid-pch -Wnon-virtual-dtor -g -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread -MD -MQ wx.p/wx.cpp.o -MF wx.p/wx.cpp.o.d -o wx.p/wx.cpp.o -c ../wx.cpp
../wx.cpp:77:14: fatal error: ../sample.xpm: No such file or directory
   77 |     #include "../sample.xpm"
      |              ^~~~~~~~~~~~~~~
compilation terminated.
ninja: build stopped: subcommand failed.

And for my own project I have a `meson.build` file that looks like this

Code: Select all

project('Music Player', 'cpp')

src = [

  'src/app.cpp',
  'src/frame.cpp',

  ]

wx = dependency('wxwidgets')

executable('musicApp', src,
  dependencies : [wx])
and I have a script that builds the project and runs it, it looks like this

Code: Select all

#! /bin/bash

# cd where the script is
cd "$(dirname "$0")"

# rm -r build
CXX=g++ meson build
cd build
meson compile -j 1

# run the program
./musicApp
Here is a link to my full project if it helps. - https://gitlab.com/apoorv569/cpp-projec ... c%20Player
Are you running any kind of IDE?
Or you are building from the Terminal?

Thank you.
Last edited by DavidHart on Tue Oct 20, 2020 8:14 pm, edited 1 time in total.
Reason: Corrected the wx-config call and the order of the g++ arguments
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: Need help with using `wxMediaCtrl`.

Post by apoorv569 »

I am for now using Emacs specifically Doom Emacs, but I have vscodium also installed.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7479
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Need help with using `wxMediaCtrl`.

Post by ONEEYEMAN »

Hi,
Try to compile the sample and see if it works.

I gave an instruction on how to do that for both cases - self-compiled and installed from the repository.

Thank you.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: Need help with using `wxMediaCtrl`.

Post by apoorv569 »

I got it working, meson needed some configuration, I added modules `std` and `media`, and it compiles fine now. Thank you everyone for help :D
stahta01
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 550
Joined: Fri Nov 03, 2006 2:00 pm

Re: Need help with using `wxMediaCtrl`.

Post by stahta01 »

apoorv569 wrote: Tue Oct 20, 2020 11:40 pm I got it working, meson needed some configuration, I added modules `std` and `media`, and it compiles fine now. Thank you everyone for help :D
So, it likely passes the modules to wx-config.

Tim S.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: Need help with using `wxMediaCtrl`.

Post by apoorv569 »

Yes, I found the information here - https://mesonbuild.com/Dependencies.html#wxwidgets

I still need help with `wxMediaCtrl` I have set my code to open file dialog, and insert the file in list box, and I have set play button to play the current selected item in playlist, but it does not play anything, according the documentation, I need to capture the `EVT_MEDIA_LOADED` event, but I'm not sure how to do that. The example/sample `mediaplayer` file, is not really beginner to C++ friendly.

I have connected my play button like this

Code: Select all

    playButton = new wxButton(panel, 1000, wxT("|>"), wxDefaultPosition, wxDefaultSize, 0);
    playButton->Connect(1000, wxEVT_MEDIA_PLAY, (wxObjectEventFunction) (wxEventFunction) (wxMediaEventFunction) &Frame::Play);
and the play function looks like this

Code: Select all

void Frame::Play(wxMediaEvent& event)
{
//    stopped = false;

    int song_index = playlistBox->GetSelection();

    std::string song_str;
    wxString wxsong_s;

    wxsong_s = playlistBox->GetString(song_index);

    song_str = std::string(wxsong_s);

    std::string song;
    wxString wxsong;
    song = std::string(wxsong);

    song = "/home/apoorv/Music/mod/" + song_str;

    std::cout << "wxString: " << song_str << std::endl;
    std::cout << "Song: " << song << std::endl;

    mediaCtrl->Load(song);
    mediaCtrl->Play();

//    event.Skip();

//    timer->Start(1000);
}
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7479
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Need help with using `wxMediaCtrl`.

Post by ONEEYEMAN »

Hi,
You can't handle EVT_MEDIA event in the wxButton.
Try to handle it in the media player you made.

And check the documentation of what event is handled by what class.

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Need help with using `wxMediaCtrl`.

Post by doublemax »

This is the line from the sample:

Code: Select all

this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PLAY, wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPlay));
It catches the event at the wxFrame. Note that this works, because all events that derive from wxCommandEvent propagate upwards in the window hierarchy until they are handled. E.g. this would not work for wxMouseEvents.
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: Need help with using `wxMediaCtrl`.

Post by apoorv569 »

Sorry, I don't understand properly understand how does this `EVT_MEDIA_PLAY` and LOADED and all work. I can't seem to get them working, compiling fails. But I did manage to make it work, by simply binding the button to the play function and simply loading and playing the file using `wxMediaCtrl`. I'm very new to c++, I don't fully understand the code that I am writing either, like I don't know how pointers work and all. But I do have a general idea of what they do. I am not like blindly copy pasting. I am still very much trying to only do stuff that I at least some what understand, I know, learning python for 2 months, I struggled a lot, when the project gets bigger, it gets harder to manage, if you don't understand what/how your code works.

I binded my button like this

Code: Select all

    playButton = new wxButton(panel, 1000, wxT("|>"), wxDefaultPosition, wxDefaultSize, 0);
    playButton->Bind(wxEVT_BUTTON, &Frame::Play, this);
and my play functions looks like this.

Code: Select all

void Frame::Play(wxCommandEvent& event)
{
//    stopped = false;

    int song_index = playlistBox->GetSelection();

    std::string song_str;
    wxString wxsong_s;

    wxsong_s = playlistBox->GetString(song_index);

    song_str = std::string(wxsong_s);

    std::string song;
    wxString wxsong;
    song = std::string(wxsong);

    song = "/home/apoorv/Music/mod/" + song_str;

    std::cout << "wxString: " << song_str << std::endl;
    std::cout << "Song: " << song << std::endl;

    mediaCtrl->Load(song);
    mediaCtrl->Play();

//    event.Skip();

//    timer->Start(1000);
}
I think it works for me as of now. As I only need to be able to play pause stop and do general stuff with music. I do need to implement seeking capability with a seek bar, and volume control with a volume slider. Does this seek bar and volume functionality needs use of `EVT_MEDIA_XXX`?
User avatar
doublemax@work
Super wx Problem Solver
Super wx Problem Solver
Posts: 474
Joined: Wed Jul 29, 2020 6:06 pm
Location: NRW, Germany

Re: Need help with using `wxMediaCtrl`.

Post by doublemax@work »

I'm sorry, i copied the wrong line. This one is the crucial one:

Code: Select all

Bind(wxEVT_MEDIA_LOADED, &wxMediaPlayerFrame::OnMediaLoaded, this,  wxID_MEDIACTRL);

Code: Select all

    mediaCtrl->Load(song);
    mediaCtrl->Play();
There is no guaranee that this will always work. Please try again using the wxEVT_MEDIA_LOADED event. If you can't get it to work, please post / attach your whole code.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: Need help with using `wxMediaCtrl`.

Post by apoorv569 »

doublemax@work wrote: Wed Oct 21, 2020 11:41 am I'm sorry, i copied the wrong line. This one is the crucial one:

Code: Select all

Bind(wxEVT_MEDIA_LOADED, &wxMediaPlayerFrame::OnMediaLoaded, this,  wxID_MEDIACTRL);

Code: Select all

    mediaCtrl->Load(song);
    mediaCtrl->Play();
There is no guaranee that this will always work. Please try again using the wxEVT_MEDIA_LOADED event. If you can't get it to work, please post / attach your whole code.
I see it uses some function called `OnMediaLoaded`, I don't know what to put there. It also has some ID `wxID_MEDIACTRL`. I get errors when I paste this line you shared, use of undeclared identifier.

I am facing another problem today, I was trying to make volume slider adjust volume according to the level of slider. I made this function,

Code: Select all

void Frame::Volume(wxScrollEvent& event)
{
    int getVolume = mediaCtrl->GetVolume() * 100;

    std::cout << "wxMediaCtrl Vol: " << getVolume << std::endl;
    std::cout << "Slider Vol: " << volumeSlider->GetValue() << std::endl;

    mediaCtrl->SetVolume(volumeSlider->GetValue() / 100);
}
and I made a slider and binded it like this

Code: Select all

    volumeSlider = new wxSlider(panel, wxID_ANY, 100, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);
    volumeSlider->Bind(wxEVT_SCROLL, &Frame::Volume, this);
I get error when compiling

Code: Select all

../src/frame.cpp:48:24: error: ‘wxEVT_SCROLL’ was not declared in this scope; did you mean ‘EVT_SCROLL’?
   48 |     volumeSlider->Bind(wxEVT_SCROLL, &Frame::Volume, this);
      |                        ^~~~~~~~~~~~
      |                        EVT_SCROLL
You can check out the full project here - https://gitlab.com/apoorv569/cpp-projec ... c%20Player
Post Reply