Недавно я уже просил решение, подобное этому:
Я хочу реализовать функцию в моем аудиоплеере, которая позволяет людям непрерывно воспроизводить звук, в то время как ползунок перемещается в соответствии с текущей секундой, в которой выполняется трек, а также с возможностью перехода к следующему треку после того, как текущий трек завершен. над
После (как вы можете прочитать в ссылке) попытаться сделать это с
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 ++?
РЕДАКТИРОВАТЬ: Оказывается, это на самом деле происходит из-за потоков. Я довольно долго занимался 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
² тот факт, что этот вопрос существует, говорит мне, что вы этого не делаете
Других решений пока нет …