mciSendString不会暂停从线程播放的声音

时间:2016-01-13 18:57:33

标签: c++ boost boost-thread mcisendstring

最近我已经要求提供类似这个问题的解决方案:

Is there a way to pause/stop a mp3 file playing with mcisendstring with the "wait" option?

我想在我的音频播放器中实现一个功能,它允许人们连续播放声音,而滑块根据曲目运行的当前秒数移动,并且还具有进入下一曲目的功能。当前曲目结束了

之后(正如您可以在链接中阅读)尝试使用

mciSendString("play mp3 wait", NULL, 0, NULL);

由于轨道在完成之前无法暂停或停止的问题而失败,我现在正试图以另一种方式实现它。目前,当我开始播放曲目时,我也会启动另一个线程,即启动计数器。计数器以秒为单位获得轨道的长度,并且正在倒计时,还提供用于暂停/恢复计数器的互斥锁。为了阻止我的MusicCycle简单地循环不受控制,我加入了线程,因此等待终止。

void Music::MusicCycle(std::wstring trackPath)
{
    while (true)
    {
        OpenMP3(trackPath);
        mciSendString("play mp3", NULL, 0, NULL);

        m_counterThread = boost::thread(boost::bind(&Counter::StartCount, m_counter, <length of track in seconds>));
        m_counterThread.join();

        //... Get new track here
    }
}

请注意,整个方法也是在一个线程中创建的:

m_cycleThread = boost::thread(boost::bind(&Music::MusicCycle, this, trackPath));

MusicCycle函数启动的线程如下所示:

void Counter::StartCount(int seconds)
{
    boost::mutex::scoped_lock lock(m_mutex);

    for (int i = 0; i < seconds; i++)
    {
        while (m_counterLock)
        {
            m_condVar.wait(lock);
        }

        boost::this_thread::sleep(boost::posix_time::seconds(1));
    }
}

另外,我添加了另一个功能来使用我的Pause / Resume方法来锁定/解锁互斥锁,这也调用相应的mciSendString函数

mciSendString("resume mp3", NULL, 0, NULL);

mciSendString("pause mp3", NULL, 0, NULL);

当我现在调用暂停时,mciSendString会暂停音轨,并锁定计数器,这样它就不会继续倒计时。

然而,问题是它仍然无效。尽管我努力在不使用mciSendString中的wait选项的情况下考虑解决方案,但暂停只会影响音乐的播放

有什么建议吗?

编辑:事实证明这是由于线程实际发生的。我已经花了很长时间做一些C#,你可以使用Invokes解决线程问题。也许这也有可能吗?

EDIT2:我读了一下,似乎有一个选项可以通过PostMessage WinAPI调用在另一个线程的消息队列中发布一个方法。这是可能的吗?如果是的话,有人能提供一个很好的例子吗?我读了一下但到目前为止我还没有真正理解

C ++中也有这样的东西吗?

1 个答案:

答案 0 :(得分:5)

  

编辑:事实证明这是由于线程实际发生的。我已经花了很长时间做一些C#,你可以使用Invokes解决线程问题。

是。如果异步事件然后需要一个用户域线程,那么排队的消息就是你的行动方式(比如C#(或Java等)的UI-thread调用)。这很辛苦。

  

EDIT2:我读了一下,似乎有一个选项可以通过PostMessage WinAPI调用在另一个线程的消息队列中发布一个方法。这是可能的吗?如果是的话,有人能提供一个很好的例子吗?我读了一下但到目前为止我还没有真正理解

     

C ++中也有这样的东西吗?

你所指的只是一般的消息 - 泵/事件循环,几乎是所有UI框架的基础。 C ++本身没有“拥有”GUI,但当然存在具有类似功能的库。

Boost Asio是一个值得一提的人。如果你已经拥有一个GUI框架,它将拥有它自己的事件循环(Qt,MFC等拥有它)。

无论使用什么,所有Win32 GUI应用程序最终都使用您提到的消息泵,它确实允许发布消息。 这几乎总是错误的抽象级别,除非你正在积极开发GUI框架²

你总是可以建立自己的。只需要某种(优先级)队列来接收消息,并有一个主循环处理它们。称他们为事件和事件:事件驱动设计。

¹目前还有一股回归,如https://github.com/ocornut/imgui

这样新的回归基础

²这个问题存在的事实告诉我你没有这样做