Обрабатывать потоки между классами с помощью C ++, libvlc и Ubuntu - PullRequest
0 голосов
/ 24 октября 2019

У меня есть приложение на C ++ с графическим интерфейсом, которое должно воспроизводить некоторые mp3 в зависимости от взаимодействия с пользователем. Мне нужно воспроизвести mp3, не блокируя поток программы. Чтобы сохранить код, я решил написать класс для обработки воспроизведения mp3 и воспроизвести его в новом потоке, но у меня возникают проблемы, когда мне нужно остановить воспроизведение.

Я знаю, что libvlc уже имеет некоторую функцию блокировки, но поток программы останавливается, когда проигрывается mp3.

MP3 запускается правильно, но если я пытаюсь вызвать stop_mp3 ()функция, я получаю ошибку сброса ядра. Ошибка генерируется, когда я вызываю функцию stop из secondpanel.cpp.

// replay.h
#include <vlc/vlc.h>

class rePlay
{
    public:
        rePlay();
        virtual ~rePlay();
        void play_mp3(const char*);
        void stop_mp3();
    protected:
        libvlc_instance_t *inst;
        libvlc_media_player_t *mp;
        libvlc_media_t *m;
    private:
};

// rePlay.cpp

#include "rePlay.h"
#include <vlc/vlc.h>
#include <mutex>
std::mutex mp3_mutex;
rePlay::rePlay()
{
    //ctor
}

rePlay::~rePlay()
{
    //dtor
}

void rePlay::play_mp3(const char* path){

    mp3_mutex.lock();
  // load the vlc engine
    inst = libvlc_new(0, NULL);
    printf("apro il file %d\n", inst);
    // create a new item
    m = libvlc_media_new_path(inst, path);
    // create a media play playing environment
    mp = libvlc_media_player_new_from_media(m);
    // no need to keep the media now
    libvlc_media_release(m);
    // play the media_player
    libvlc_media_player_play(mp);
    printf("Done.\n");
}

void rePlay::stop_mp3(){
    mp3_mutex.unlock();
  // stop playing
    libvlc_media_player_stop(mp);
    // free the media_player
    libvlc_media_player_release(mp);
    libvlc_release(inst);
}

// firstpanel.h

class firstpanel: public wxPanel
{
    public:
        firstpanel(wxWindow* parent, Isola02Frame*, wxWindowID id=wxID_ANY,const wxPoint& pos=wxDefaultPosition,const wxSize& size=wxDefaultSize);
        virtual ~firstpanel();
        void checkValue(wxCommandEvent& event);
        void check_cf(wxTimerEvent& event);
   rePlay *mp3_apertura_porta = new rePlay();    // <-- I DECLARED THE pointer here
        //(*Declarations(firstpanel)
        wxStaticText* assistenza;
        wxStaticText* first_panel;
        wxStaticText* identificazione;
        wxTextCtrl* tessera;
        //*)
...
}

// firstpanel.cpp
 std::thread second = std::thread([this]() noexcept {
        this->mp3_apertura_porta->play_mp3("/home/robodyne/Project/audio/scegli-rifiuto.mp3"); });
        second.join();

// secondpanel.cpp

void secondpanel::OnBitmapButton2Click(wxCommandEvent& event)
{
 firstpanel *ptr;
 ptr->mp3_apertura_porta->stop_mp3();
}

EDIT1: Благодаря @Ted Lyngmo я использовал библиотеку libvlcpp, которая как-то асинхронна и работает нормально. Единственная проблема заключается в том, что я не знаю, как вызвать mp.stopAsync() из stop_mp3 (), чтобы остановить аудиофайл, потому что переменная mp не является глобальной.

#include "rePlay.h"
#include <vlc/vlc.h>
#include <mutex>
#include <unistd.h>
#include "vlcpp/vlc.hpp"

std::mutex mp3_mutex;

rePlay::rePlay()
{
    //ctor
}

rePlay::~rePlay()
{
    //dtor
}

void rePlay::play_mp3(const char* path){

    auto instance = VLC::Instance(0, nullptr);
    auto media = VLC::Media(instance, path, VLC::Media::FromPath);
    auto mp = VLC::MediaPlayer(media);
    auto mp.play();

#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)

#else
    mp.stop();
#endif
}

void rePlay::stop_mp3(){
     mp.stopAsync();  <-- variable mp is not global!
}

EDIT2: Я думаю, что libvlcpp не 'хорошо работает с приложениями с графическим интерфейсом. Если я запускаю его в консольном приложении, я могу выполнять другие операции параллельно, но когда я выполняю его в приложении WxWidgets, он блокирует поток.

Это консольное консольное приложение:

    #include "vlcpp/vlc.hpp"
#include <thread>
#include <iostream>

int main(int ac, char** av)
{
    if (ac < 2)
    {
        std::cerr << "usage: " << av[0] << " <file to play>" << std::endl;
        return 1;
    }
    auto instance = VLC::Instance(0, nullptr);
    auto media = VLC::Media(instance, av[1], VLC::Media::FromPath);
    auto mp = VLC::MediaPlayer(media);
    mp.play();
    for (int i=0; i < 10000000; i++){

    printf("%d\n", i);
    }
    std::this_thread::sleep_for( std::chrono::seconds( 10 ) );
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
    mp.stopAsync();
#else
    mp.stop();
#endif
}

цикл for () работает параллельно во время воспроизведения mp3. Этого не произойдет, если я использую его с моим приложением.

...