2012-12-25 57 views
2

我试图创建这个类的两个实例,它最终将使用Win32的mciSendString功能播放音乐文件。但是为了测试它,因为这是我第一次尝试使用std :: thread,我写了一个测试(void)方法,输出类ID,我期望打印一系列1和2,如12122111112212121212 ...std ::类实例的线程

我收到以下错误,测试(void)方法确实存在?

错误1个错误C2064:术语不计算为函数取0参数

#include <iostream> 
#include <thread> 

typedef enum MusicStatus { 
    MUSIC_PLAYING = 0, 
    MUSIC_PAUSED, 
    MUSIC_STOPPED, 
    MUSIC_IDLE 
} MusicStatus, *pMusicStatus; 

class MusicPlayer 
{ 
public: 

    MusicPlayer(void) { 
     m_bIsPlaying = false; 
     m_bIsPaused = false; 
    } 

    bool isPaused(void) { 
     return m_bIsPaused; 
    } 

    bool isPlaying(void) { 
     return m_bIsPlaying; 
    } 

    MusicStatus getState(void) { 
     if (!m_bIsPlaying && !m_bIsPaused && !m_bIsStopped) 
      return MUSIC_IDLE; 
     if (m_bIsPlaying) 
      return MUSIC_PLAYING; 
     if (m_bIsPaused) 
      return MUSIC_PAUSED; 
     if (m_bIsStopped) 
      return MUSIC_STOPPED; 
     return MUSIC_STOPPED; 
    } 

    void test(void) { 
     for (int m = 0; m < 100; m++) { 
      std::cout << this->n; 
     } 
    } 

    int n; 

private: 

    bool m_bIsPlaying, m_bIsPaused, m_bIsStopped; 

}; 


int main(int argc, char* argv[]) 
{ 
    MusicPlayer A; 
    MusicPlayer B; 
    A.n = 1; 
    B.n = 2; 

    std::thread t1(A); 
    std::thread t2(B); 

    t1.join(); 
    t2.join(); 

    A.test(); 
    B.test(); 

    system("PAUSE"); 
    return 0; 
} 

更新:我已经做了一些调整,现在我遇到的参数列表,错误的问题:MusicPlayer: :play_sound函数调用缺少参数列表

#include <iostream> 

#pragma comment(lib, "Strmiids.lib") 

#include <thread> 
#include <dshow.h> 
#include "Lib/NSL.h" 

typedef enum MusicStatus { 
    MUSIC_PLAYING = 0, 
    MUSIC_PAUSED, 
    MUSIC_STOPPED, 
    MUSIC_IDLE 
} MusicStatus, *pMusicStatus; 

class MusicPlayer 
{ 
public: 

    MusicPlayer() { 
     m_bIsPlaying = false; 
     m_bIsPaused = false; 
     m_bIsStopped = false; 
    } 

    bool isPaused() { 
     return m_bIsPaused; 
    } 

    bool isPlaying() { 
     return m_bIsPlaying; 
    } 

    MusicStatus getState() { 
     if (!m_bIsPlaying && !m_bIsPaused && !m_bIsStopped) 
      return MUSIC_IDLE; 
     if (m_bIsPlaying) 
      return MUSIC_PLAYING; 
     if (m_bIsPaused) 
      return MUSIC_PAUSED; 
     if (m_bIsStopped) 
      return MUSIC_STOPPED; 
     return MUSIC_STOPPED; 
    } 

    void playAudio(std::string strFilePath) { 
     m_strFilePath = strFilePath; 
     std::thread audioThread(play_sound); 
     audioThread.join(); 
    } 

private: 

    bool m_bIsPlaying, m_bIsPaused, m_bIsStopped; 
    std::string m_strFilePath; 

    void play_sound() { 
     IGraphBuilder *pGraph = NULL; 
     IMediaControl *pControl = NULL; 
     IMediaEvent *pEvent = NULL; 

     // Initialize the COM library. 
     HRESULT hr = CoInitialize(NULL); 
     if (FAILED(hr)) 
     { 
      printf("ERROR - Could not initialize COM library"); 
      return; 
     } 

     // Create the filter graph manager and query for interfaces. 
     hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
          IID_IGraphBuilder, (void **)&pGraph); 
     if (FAILED(hr)) 
     { 
      printf("ERROR - Could not create the Filter Graph Manager."); 
      return; 
     } 

     hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl); 
     hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); 

     // Build the graph. IMPORTANT: Change this string to a file on your system. 
     hr = pGraph->RenderFile(s2ws(m_strFilePath).c_str(), NULL); 
     if (SUCCEEDED(hr)) 
     { 
      // Run the graph. 
      hr = pControl->Run(); 
      if (SUCCEEDED(hr)) 
      { 
       // Wait for completion. 
       long evCode; 
       pEvent->WaitForCompletion(INFINITE, &evCode); 

       // Note: Do not use INFINITE in a real application, because it 
       // can block indefinitely. 
      } 
     } 
     pControl->Release(); 
     pEvent->Release(); 
     pGraph->Release(); 
     CoUninitialize(); 
    } 

}; 

int main(void) 
{ 
    MusicPlayer A; 
    A.playAudio("music.mp3"); 
    system("pause"); 
    return 0; 
} 

回答

1

好吧我解决了我的问题,它出现std :: thread是理想的在后台播放mp3文件感谢std :: thread。注意:audioThread(& MusicPlayer :: play_sound,this);

#include <iostream> 

#pragma comment(lib, "Strmiids.lib") 

#include <thread> 
#include <dshow.h> 
#include "Lib/NSL.h" 

typedef enum MusicStatus { 
    MUSIC_PLAYING = 0, 
    MUSIC_PAUSED, 
    MUSIC_STOPPED, 
    MUSIC_IDLE 
} MusicStatus, *pMusicStatus; 

class MusicPlayer 
{ 
public: 

    MusicPlayer() { 

     m_bIsPlaying = false; 
     m_bIsPaused = false; 
     m_bIsStopped = false; 
     m_pControl = NULL; 
     m_pEvent = NULL; 
     m_pGraph = NULL; 
     m_pEventEx = NULL; 
     m_pBasicAudio = NULL; 
     m_pMediaSeeking = NULL; 

     // Initialize the COM library 
     m_hr = CoInitialize(NULL); 
     if (FAILED(m_hr)) { // Could not initialize COM library"); 
      return; 
     } 

     // Create the filter graph manager and query for interfaces. 
     m_hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGraph); 

     if (FAILED(m_hr)) { // Could not create the Filter Graph Manager 
      return; 
     } 

     m_hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **)&m_pControl); 
     m_hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **)&m_pEvent); 
     m_hr = m_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&m_pEventEx); 
     m_hr = m_pGraph->QueryInterface(IID_IBasicAudio, (void**)&m_pBasicAudio); 
     m_hr = m_pGraph->QueryInterface(IID_IMediaSeeking, (void**)&m_pMediaSeeking); 
    } 

    ~MusicPlayer() { 
     m_pControl->Release(); 
     m_pEvent->Release(); 
     m_pEventEx->Release(); 
     m_pGraph->Release(); 
     m_pBasicAudio->Release(); 
     m_pMediaSeeking->Release(); 
     CoUninitialize(); 
    } 

    bool isPaused() { 
     return m_bIsPaused; 
    } 

    bool isPlaying() { 
     return m_bIsPlaying; 
    } 

    MusicStatus getState() { 
     if (!m_bIsPlaying && !m_bIsPaused && !m_bIsStopped) 
      return MUSIC_IDLE; 
     if (m_bIsPlaying) 
      return MUSIC_PLAYING; 
     if (m_bIsPaused) 
      return MUSIC_PAUSED; 
     if (m_bIsStopped) 
      return MUSIC_STOPPED; 
     return MUSIC_STOPPED; 
    } 

    void playAudio(std::string strFilePath) { 
     m_strFilePath = strFilePath; 
     set_state(MUSIC_PLAYING); 
     std::thread audioThread(&MusicPlayer::play_sound, this); 
     audioThread.join(); 
    } 

    bool stopAudio() { 
     if (getState() == MUSIC_PLAYING && m_pControl) { 
      m_hr = m_pControl->Stop(); 
      if (SUCCEEDED(m_hr)) { 
       set_state(MUSIC_STOPPED); 
       return true; 
      } 
     } 
     return false; 
    } 

    bool pauseAudio() { 
     if (getState() == MUSIC_PLAYING && m_pControl) { 
      return SUCCEEDED(m_pControl->Pause()); 
     } 
     return false; 
    } 

    long volume() { 
     if (m_bIsPlaying && m_pBasicAudio) { 
      long lVolume = -1; 
      m_hr = m_pBasicAudio->get_Volume(&lVolume); 
      if (SUCCEEDED(m_hr)) 
       return lVolume; 
     } 
     return -1; 
    } 

    bool setVolume(long lVolume) { 
     if (m_bIsPlaying && m_pBasicAudio) { 
      m_hr = m_pBasicAudio->put_Volume(lVolume); 
      return SUCCEEDED(m_hr); 
     } 
     return false; 
    } 

    long durationInSeconds() { 
     return m_ulTrackDuration/10000000; 
    } 

    __int64 currentPosition() { 
     if (getState() == MUSIC_PLAYING && m_pMediaSeeking) { 
      __int64 curPosition = -1; 
      m_hr = m_pMediaSeeking->GetCurrentPosition(&curPosition); 
      if (SUCCEEDED(m_hr)) 
       return curPosition; 
     } 
     return -1; 
    } 

    bool setPosition(__int64* pCurrentPos, __int64* pStop, bool bAbsolutePositioning) { 
     if (getState() == MUSIC_PLAYING && m_pMediaSeeking) { 
      DWORD flags = 0; 
      if (bAbsolutePositioning) 
       flags = AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame; 
      else 
       flags = AM_SEEKING_RelativePositioning | AM_SEEKING_SeekToKeyFrame; 
      m_hr = m_pMediaSeeking->SetPositions(pCurrentPos, flags, pStop, flags); 
      if (SUCCEEDED(m_hr)) 
       return true; 
     } 
     return false; 
    } 

private: 

    bool m_bIsPlaying, m_bIsPaused, m_bIsStopped; 
    std::string m_strFilePath; 

    HRESULT m_hr; 
    IGraphBuilder *m_pGraph; 
    IMediaControl *m_pControl; 
    IMediaEvent *m_pEvent; 
    IMediaEventEx *m_pEventEx; 
    IBasicAudio *m_pBasicAudio; 
    IMediaSeeking *m_pMediaSeeking; 

    // 10,000,000 per second 
    __int64 m_ulTrackDuration; 

    void set_state(MusicStatus m) { 
     switch(m) { 
     case MUSIC_STOPPED: 
      m_bIsStopped = true; 
      m_bIsPlaying = m_bIsPaused = false; 
      break; 
     case MUSIC_PAUSED: 
      m_bIsPaused = true; 
      m_bIsPlaying = m_bIsStopped = false; 
      break; 
     case MUSIC_PLAYING: 
      m_bIsPlaying = true; 
      m_bIsPaused = m_bIsStopped = false; 
      break; 
     case MUSIC_IDLE: 
      m_bIsPaused = m_bIsPlaying = m_bIsStopped = false; 
      break; 
     } 
    } 

    void play_sound() { 
     m_hr = m_pGraph->RenderFile(s2ws(m_strFilePath).c_str(), NULL); 
     if (SUCCEEDED(m_hr)) 
     { 
      m_hr = m_pControl->Run(); 
      if (SUCCEEDED(m_hr)) { 
       if (m_pMediaSeeking) { 
        m_pMediaSeeking->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME); 
        m_pMediaSeeking->GetDuration(&m_ulTrackDuration); 
       } 
      } 
     } 

    } 

}; 

int main(void) 
{ 
    MusicPlayer A; 
    A.playAudio("music.mp3"); 
    std::cout << A.durationInSeconds(); 
    system("pause"); 
    return 0; 
} 
1

使用std::thread为您MusicPlayer类的成员,并尽快分配线程功能,它改变的状态MUSIC_PLAYING启动后台线程。

+0

,谢谢。 – johnsonwi

1

小问题:具有零个参数

MusicPlayer(void) 
bool isPaused(void) 
bool isPlaying(void) 

功能被定义为:

MusicPlayer() 
bool isPaused() 
bool isPlaying() 

主要问题。

线程对象的构造函数需要一个函子。因为你没有传递任何参数,所以函数必须也取零参数。这意味着您传递给线程的对象必须如下所示进行调用:

MusicPlayer A; 
std::thread t1(A); 

// This means that the object A is callable like a function. 
A(); 

// For this to work the class MusicPlayer must define the opropriate function operator: 

class MusicPlayer 
{ 
    public: 
     void operator()() { /* Code run inside thread */ } 
}; 
+0

小问题?我被告知使用void来表示没有参数加快编译时间。也许这是一个神话。 – johnsonwi

+0

@johnsonwi:没有参数是C++的方式。在那里使用void仅仅是为了与C兼容http://stackoverflow.com/a/7412299/14065 –

3

您无法运行对象!你可以 run是一个特定对象的成员函数:std::thread需要被告知该线程的入口函数。它使用第一个构造函数参数作为函数对象,并使用所有其他参数作为如何调用该函数的参数。由于你的班级没有函数调用操作符,因此std::thread不知道要调用哪个函数。

有一个方法可以解决此问题:

  1. 你为你MusicPlayer类型作为线程的入口函数提供一个函数调用operator()()
  2. 您使用成员函数作为第一个参数和实际对象一起作为传递的参数,例如std::thread t1(&MusicPlayer::test, &A)
  3. 使用易于绑定的函数对象作为参数std::thread,例如,std::thread t1(std::bind(&MusicPlayer::test, std::ref(A))
+0

我一直在使用Qt,我希望有一些功能,我可以扩展线程,并有一些功能像exec()直到exit()被调用。 – johnsonwi

+0

我假设我将不得不写一些样板while循环 – johnsonwi

+0

@johnsonwi:我建议你看看以下两个链接:1. http://blog.qt.digia.com/blog/2010/06/17/你做错了/ 2. http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ – bjoernz

0

你可以尝试像

std::thread audioThread(([this](){MusicPlayer::play_sound();}; 
当然