mciSendString не приостанавливает воспроизведение звука из потока

Недавно я уже просил решение, подобное этому:

Есть ли способ приостановить / остановить воспроизведение mp3-файла с помощью mcisendstring с опцией "wait"?

Я хочу реализовать функцию в моем аудиоплеере, которая позволяет людям непрерывно воспроизводить звук, в то время как ползунок перемещается в соответствии с текущей секундой, в которой выполняется трек, а также с возможностью перехода к следующему треку после того, как текущий трек завершен. над

После (как вы можете прочитать в ссылке) попытаться сделать это с

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 для решения проблем с потоками. Может быть, это возможно и здесь?

РЕДАКТИРОВАТЬ 2: Я прочитал немного, и кажется, что есть возможность Опубликовать метод в очереди сообщений другого потока через вызов PostMessage WinAPI. Это возможность здесь? Если да, может ли кто-нибудь привести хороший пример? Я немного прочитал, но я до сих пор не очень понимаю

Есть ли что-то подобное в C++?

1 ответ

Решение

РЕДАКТИРОВАТЬ: Оказывается, это на самом деле происходит из-за потоков. Я довольно долго занимался C#, и вы могли бы использовать Invokes для решения проблем с потоками.

Да. Если вам нужен поток пользовательской земли для асинхронных событий, тогда сообщение в очереди - это ваш курс действий (например, C# (или Java и т. Д.) Invoke-on-UI-thread). Это тяжелая работа.

РЕДАКТИРОВАТЬ 2: Я прочитал немного, и кажется, что есть возможность Опубликовать метод в очереди сообщений другого потока через вызов PostMessage WinAPI. Это возможность здесь? Если да, может ли кто-нибудь привести хороший пример? Я немного прочитал, но я до сих пор не очень понимаю

Есть ли что-то подобное в C++?

То, что вы имеете в виду, это просто общий цикл обработки сообщений / событий, который лежит в основе почти всех структур пользовательского интерфейса. C++ изначально не имеет " GUI", но, безусловно, существуют библиотеки, которые имеют схожие возможности.

Ускорение Асио было одним упоминанием. Если у вас уже есть GUI-фреймворк, у него будет собственный цикл обработки событий (он есть у Qt, MFC и т. Д.).

Независимо от того, что используется, все приложения Win32 GUI в конечном итоге используют насос сообщений, о котором вы упоминали, который действительно позволяет отправлять сообщения.Это почти всегда неправильный уровень абстракции, если вы активно не разрабатываете свою среду GUI².

Вы всегда можете построить свой собственный. Просто есть какая-то (приоритетная) очередь для получения сообщений и главный цикл, обрабатывающий их. Назовите их событиями и быстро: управляемый событиями дизайн.


¹ в настоящее время есть волна назад с новомодными назад к основам, таким как https://github.com/ocornut/imgui

² тот факт, что этот вопрос существует, говорит мне, что вы этого не делаете

Другие вопросы по тегам