2

I'm attempting to create two instances of this class which will eventually play music files using Win32's mciSendString features. However to test it since this is the first time I've attempted to use std::thread, I wrote a test(void) method which outputs the class ID which I'd expect to print me a series of 1's and 2's like 12122111112212121212...

I'm getting the following error, the test(void) method indeed exists?

Error 1 error C2064: term does not evaluate to a function taking 0 arguments

#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;
}

Update: I've made some adjustment, now I'm having an issue with argument list, error: MusicPlayer::play_sound function call missing argument list

#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;
}
4

5 に答える 5

5

オブジェクトを実行できません! 実行できるのは、特定のオブジェクトのメンバー関数std::threadです。スレッドのエントリ関数に通知する必要があります。最初のコンストラクター引数を関数オブジェクトとして使用し、他のすべての引数を関数の呼び出し方法のパラメーターとして使用します。クラスには関数呼び出し演算子がないため、std::threadどの関数を呼び出すかわかりません。

この問題を解決するには、次の方法があります。

  1. スレッドのエントリ関数として、型の関数呼び出しoperator()()を提供します。MusicPlayer
  2. メンバー関数を最初の引数として使用し、実際のオブジェクトを渡されるパラメーターとして使用しますstd::thread t1(&MusicPlayer::test, &A)
  3. std::threadへのパラメーターとして、簡単にバインドされた関数オブジェクトを使用しますstd::thread t1(std::bind(&MusicPlayer::test, std::ref(A))
于 2012-12-25T03:38:08.633 に答える
2

さて、問題は解決しました。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;
}
于 2012-12-25T19:37:50.610 に答える
1

std::threadクラスのメンバーとして使用MusicPlayerし、 state に変わるとすぐにスレッド関数を割り当ててバックグラウンド スレッドを開始しますMUSIC_PLAYING

于 2012-12-25T03:34:04.277 に答える
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 */ }
};
于 2012-12-25T03:35:23.797 に答える