Search code examples
c++multithreadingclassubuntulibvlc

Correctly write a class and use pthread with vlc library and c++


My application (C++, WxWidgets, Ubuntu) have to play different mp3 files depending on user actions. At the moment, I use vlc library and I always call a new function to reproduce the audio file, but this requires too much code and I think it's not so professional. Since I do not want to stop the flow of the application while the mp3 is playing, I use threads.

I tried to write a class for the mp3, but I think it is not correct since I get this error:

    /home/isola/Documents/Isola02/secondpanel.cpp:68:102: error: invalid use of void expression
  pthread_create(&thread, NULL, mp3->play_mp3("/home/user/Project/audio/scegli-rifiuto.mp3"), NULL);

This is the code of my class:

rePlay.cpp

#include "rePlay.h"
#include <vlc/vlc.h>

rePlay::rePlay()
{
    //ctor
}

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

void rePlay::play_mp3(const char* path){
  // 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(){
  // stop playing
    libvlc_media_player_stop(mp);
    // free the media_player
    libvlc_media_player_release(mp);
    libvlc_release(inst);
}

and the header rePlay.h

#ifndef REPLAY_H
#define 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:
};

#endif // REPLAY_H

My idea is to call:

pthread_t thread;
rePlay *mp3;

mp3->new rePlay(); pthread_create(&thread, NULL, mp3->play_mp3("/home/user/Project/audio/scegli-rifiuto.mp3"), NULL);

by passing the path of the file each time I want to reproduce a mp3 and then to call:

pthread_create(&thread, NULL, mp3->stop_mp3, NULL);

when I want to stop it.

At the moment, I get this error from the compiler regarding the pthread_create, but I think there should be other problems since I do not know if the play_mp3() and stop_mp3() could work.

Can you help me, please?

EDIT1: the class works if I do not use pthread_create function

EDIT2: If I use I get the same error:

std::thread first (mp3->play_mp3("/home/robodyne/Project/audio/scegli-rifiuto.mp3"));

error:

/home/isola/Documents/Isola02/secondpanel.cpp:85:85: error: invalid use of void expression
  std::thread first (mp3->play_mp3("/home/robodyne/Project/audio/scegli-rifiuto.mp3"));

EDIT3: Why if I declare rePlay *mp3_apertura_porta; in another class named firstpanel as public, then I get this error:

 /home/isola/Documents/Isola02/firstpanel.cpp: In member function ‘void firstpanel::check_cf(wxTimerEvent&)’:
/home/isola/Documents/Isola02/firstpanel.cpp:160:44: error: capture of non-variable ‘firstpanel::mp3_apertura_porta’ 
         std::thread second = std::thread([&mp3_apertura_porta]() noexcept {
                                            ^~~~~~~~~~~~~~~~~~
In file included from /home/isola/Documents/Isola02/firstpanel.cpp:1:0:
/home/isola/Documents/Isola02/firstpanel.h:20:12: note: ‘rePlay* firstpanel::mp3_apertura_porta’ declared here
    rePlay *mp3_apertura_porta;
            ^~~~~~~~~~~~~~~~~~
/home/isola/Documents/Isola02/firstpanel.cpp: In lambda function:
/home/isola/Documents/Isola02/firstpanel.cpp:161:9: error: ‘this’ was not captured for this lambda function
         mp3_apertura_porta->play_mp3("/home/robodyne/Project/audio/scegli-rifiuto.mp3"); });

when I call

 rePlay *mp3_apertura_porta = new rePlay();
    std::thread first = std::thread([&mp3_apertura_porta]() noexcept {
            mp3_apertura_porta->play_mp3("/home/isola/Documents/Isola02/audio/errore-ripetere-la-strisciata.mp3"); });
            first.join();

in firstpanel.cpp ?


Solution

  • Your syntax for starting the thread in EDIT2 is incorrect. Here's one way to do it with a lambda:

    std::thread first = std::thread([&mp3]() noexcept {
        try {
            mp3->play_mp3("/home/robodyne/Project/audio/scegli-rifiuto.mp3");
        } catch(...) {
        }
    });
    
    //...
    
    first.join();
    

    Another option you could use if you are not comfortable with lambdas is similar to what you would use with pthreads:

    // run MP3::play_mp3 on object mp3
    
    std::thread second(&MP3::play_mp3, mp3,
                       "/home/robodyne/Project/audio/scegli-rifiuto.mp3");
    
    // ...
    
    second.join();