У меня есть приложение на 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. Этого не произойдет, если я использую его с моим приложением.