【问题标题】:mciSendString doesn't pause sound played from a threadmciSendString 不会暂停从线程播放的声音
【发布时间】:2016-01-13 18:57:33
【问题描述】:

最近我已经要求类似以下问题的解决方案:

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

当我现在调用 pause 时,mciSendString 会暂停轨道,并锁定计数器,使其不会继续倒计时。

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

有什么建议吗?

编辑:事实证明这实际上是由于线程而发生的。我已经使用 C# 很长时间了,您可以使用 Invokes 来解决线程问题。也许这里也有可能?

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

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

【问题讨论】:

  • 你能简化一下吗? MCI 命令是否在更简单的应用程序中工作?为什么你总是产生一个新线程?你有没有考虑过使用 Boost Asio 和一个合适的时钟来测量时间(也许 MCI 有一个传输接口可以告诉你实际的轨道位置,所以你不需要做所有的英雄事)。
  • @sehe 制作了一个线程,以便在我继续播放时 UI 不会挂起,另一个线程用于计数器,因此不会妨碍歌曲的播放。是的,如果我不尝试跨线程执行它,它会起作用。我可能要研究一下 asio,但计数器现在并没有真正阻碍我,而是跨线程 mcisendstring 问题。
  • 如果没有线程kludge,您将不需要计数器。另外,我问“为什么你一直都生成一个新线程”。你只回答了第一个(明显的)部分
  • 哦,对了,我明白你的意思了。我已经解决了这个问题,我会在我可以访问我的计算机后立即更新它。

标签: c++ boost boost-thread mcisendstring


【解决方案1】:

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

是的。如果您需要异步事件的用户级线程然后排队消息是您的行动过程(如 C#(或 Java 等)invoke-on-UI-thread)。这是一项艰巨的工作。

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

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

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

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

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

您始终可以构建自己的。只是有某种(优先级)队列来接收消息并有一个处理这些消息的主循环。称它们为事件和即刻:事件驱动的设计。


¹目前有一股新潮回归基础,比如https://github.com/ocornut/imgui

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多