2012-12-25 54 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();}; 
當然