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

mciSendString doesn't pause sound played from a thread

本文关键字:播放 声音 线程 暂停 mciSendString      更新时间:2023-10-16

最近我已经提出了类似于以下问题的解决方案:

有没有一种方法可以暂停/停止用mcisendstring播放的mp3文件;等待";选项

我想在我的音频播放器中实现一个功能,让人们可以连续播放声音,同时滑块根据曲目运行的当前秒移动,还可以在当前曲目超过后转到下一首曲目

在(正如你可以在链接中阅读的)尝试用做它之后

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);

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

然而,问题是它仍然不起作用。暂停根本不会影响音乐的播放,尽管我努力想出一个不使用mciSendString 中等待选项的解决方案

有什么建议吗?

编辑:事实证明,这实际上是由于线程的缘故。我做一些C#已经有很长一段时间了,您可以使用Invoke来解决线程问题。也许这在这里也是可能的?

编辑2:我读了一点,似乎有一个选项可以通过PostMessage WinAPI调用在另一个线程的消息队列中发布一个方法。这里有可能吗?如果是,有人能提供一个好的例子吗?我读了一些,但到目前为止我还不太明白

C++中也有类似的东西吗?

编辑:事实证明,这实际上是由于线程的缘故。我做一些C#已经有很长一段时间了,您可以使用Invoke来解决线程问题。

是的。如果异步事件需要一个用户陆地线程,那么队列消息就是您的操作过程(比如C#(或Java等)在UI线程上的调用)。这是一项艰苦的工作。

编辑2:我读了一点,似乎有一个选项可以通过PostMessage WinAPI调用在另一个线程的消息队列中发布一个方法。这里有可能吗?如果是,有人能提供一个好的例子吗?我读了一些,但到目前为止我还不太明白

C++中也有类似的东西吗?

您所指的只是作为几乎所有UI框架基础的一般消息泵/事件循环。C++不";具有";GUI本身,但肯定存在具有类似功能的库。

Boost Asio是一个值得一提的话题。如果您已经有了GUI框架,它将有自己的事件循环(Qt、MFC等都有)。

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

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


cco现在有一股回归潮流,新的回归基础,比如https://github.com/ocornut/imgui

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