SDL_mixer stop playing music on certain event - c++

My program needs to stop playing sound if certain point is in range, for that I have class with function run() which runs on seperate thread and plays sound using SDL.h and SDL_mixer.h:
void SoundCheck::run()
{
Mix_PlayMusic(music, 1);
while(1)
{
if(normalize(sound[0], range_->getPos()))
{
printf("stop sound\n");
Mix_HaltChannel(-1);
}
sleep(1);
}
}
but when if condition returns true it prints "stop sound" but sound still plays, what seems to be the problem?

Mix_HaltChannel is used to stop a Mix_Chunk after being started with Mix_PlayChannel.
To stop a Mix_Music after being started with Mix_PlayMusic, you must use Mix_HaltMusic.

Related

OpenCV multithreading for videoCapturing and Processing independently C++

As the title, i'm trying to do the following things:
First, a videoCapture object that read frame from external source (like video, webcam).
Second, for each frame captured, the processing thread(s) processes it and imshow to the screen.
I've tried this:
#define FRAME_FPS 10
void frameCaptureThread(cv::VideoCapture* cap, cv::Mat* ref){
while (cap->read(*ref)) {
cv::waitKey(1000/FRAME_FPS);
}
}
void frameProcessThread(cv::Mat* ref){
while(true){
if(!ref->empty()){
/* Processing ... */
cv::imshow("frameWindow", *ref);
cv::waitKey(1000/FRAME_FPS);
}
}
}
int main() {
cv::VideoCapture videoCapture("videoPath");
cv::Mat sharedMat;
std::thread t1(frameCaptureThread, &videoCapture, &sharedMat);
std::thread t2(frameProcessThread, &sharedMat);
t1.join();
t2.join();
return 0;
}
This looks wrong right, because i think the frameProcessingThread is put in a while(True) loop thats run forerver and beside that, it also has to check if the *ref is empty or not.
Is there a way to make the Processing Thread only do the process if:
the new frame is coming AND it just finished it recent task.
And if i want to create another thread to do other processing task, what should i do ?
I've look around for some async concepts but have no idea what is the optimal way for this situation.

QT: Run a function as long as button is toggled

I want to implement a GUI that receives messages from an external device. The "advancedReceiveExample" is waiting for messages. Once it has received one, it does stuff with it, saves it and terminates.
I want to make my function wait for new messages after receiving one as long as the button is toggled.
I have tried this so far:
void MainWindow::on_pushButton_clicked()
{
if (ui.pushButton->isChecked()) {
ui.pushButton->setText("Stop Receiving");
ui.label_3->setText("Receiving...");
advancedReceiveExample(ui.comboBox->currentIndex() + 1);
}
else
{
ui.pushButton->setText("Start Receiving");
ui.label_3->setText("Not Receiving");
}
}
This works perfectly fine but as mentioned above it only receives one message. If I do that:
void MainWindow::on_pushButton_clicked()
{
if (ui.pushButton->isChecked()) {
ui.pushButton->setText("Stop Receiving");
ui.label_3->setText("Receiving...");
while (1)
{
advancedReceiveExample(ui.comboBox->currentIndex() + 1);
}
}
else
{
ui.pushButton->setText("Start Receiving");
ui.label_3->setText("Not Receiving");
}
}
it blocks the function because the state of the button can only be change after the function "on_pushButton_clicked()" has terminated.
Visual Studio 2019
C/C++
EDIT: Okay, I have understood the problem of blocking the thread. Multithreading might be the right option but I am very unexperienced regarding this topic. The <QThread> could be possible. How would you use it?
Do you have suggestions which other library could be used?
Note QT is event-based. If you keep your computer busy inside some function without returning to the main loop frequently, your GUI will freeze.
What you need to do is slice your action that you want to do into small bits that can repeatedly return to the main loop in order to keep the GUI responsive. (Another method yould be to swap out your action into a separate thread and handle it in parallel, killing the thread when the button is released)
Probably the simplest method to do what you want is with timers that you arm in the PushButton::clicked slot, and then check in the timer event whether the button is still pressed, and, if yes, do a bit of your action, save state and re-arm the timer to have you return.
Something along the lines of the following pseudo code should work and execute what you want to do in slices every 10ms:
MainWindow::onPushButtonClicked () {
// do the action, or, alternatively, start a
// parallel thread that does it
do_a_bit_of_action();
// sets up a timer to call onTimer after 10ms
QTimer::singleShot (10, this, SLOT(onTimer()));
}
MainWindow::onTimer () {
// check if button is still held down
if (pushButton.down) {
// re-arm timer
Timer::singleShot (10, this, SLOT(onTimer()));
// do some more action bits
do_a_bit_of_action();
}
else {
// kill optional background thread here
}
}
You can try it with:
while(ui.pushButton->isChecked()){
*your function*
}

QMediaPlayer crashes when pausing playback

I have a longer wav-file, where I wanted to play smaller parts.
I stored startTime and endTime as qint64 and already loaded the audiofile:
player = new QMediaPlayer;
connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(slotTick(qint64)));
player->setNotifyInterval(10);
player->setMedia(QUrl::fromLocalFile(mediasource));
...
player->setPosition(startTime);
player->play();
I observe the position with the positionChanged Signal andd use the following slot, to stop the playback once the end of the desired part is reached:
void PlayerWidget::slotTick(qint64 time){
if(endTime >= 0 && time >= endTime){
if(player->state() == QMediaPlayer::PlayingState){
player->stop();
}
}
Unfortunately, the program crashes shortly after the player stops. WHat could be the reason
Just had the same issue, and while I don't really know the underlying reason, I managed to somehow intuit a solution that actually works.
Instead of calling player->stop() directly, trigger it with a singleShot QTimer. Python code equivalent: QtCore.QTimer.singleShot(0, player.stop).

C++ async makes program unresponsive

I'm currently trying to create a C++ wrapper for my program to use GStreamer.
So I have created a Class "Audio" with a method "play" that starts a stream. Because of the call to g_main_loop_run inside it, it won't return until the main loop quits.
I dont want that behaviour and thus I'm trying to make an async call to another method within the play method, which would then start the main loop and allow the play method to return.
It currently looks like this:
void play(const char* uri) {
stop();
if (uri) {
g_object_set(G_OBJECT(pipeline), "uri", uri, NULL);
} else {
cout << "Please specify an URI you wish to play" << endl;
return;
}
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
auto handle = async( launch::async, &Audio::playAsync, this, uri);
}
void playAsync(const char* uri) {
cout << "playing async" << endl;
g_main_loop_run(this->getLoop());
}
But the result is that the program is getting unresponsive... the playAsync method is called (its printing the cout), and playback starts and continues to play, but the GUI becomes totally unresponsive and can only be quit by killing the program.
Do you have any help for me?
regards, tagelicht
Async returns future and future must be finished (it waits for the result) when it goes out of scope.
It's exactly the same as using just async(...); as handle goes out of scope just after assigment.

what's the correct implementation of this multithreading program in C++(11)

I have a game program and it need to do large amount of AI calculation per frame,so I think it is a problem if I create hundreds of thread in every frame. Here is my solution(pseudo-code,for short,because the source code is too long):
void AIThread(AIAdapter *ai)
{
while (!exit)
{
condition_variable.wait(goThink);
// AI calculation...
ai->Think();
// notify the main thread
mutex.lock();
done++;
mutex.unlock();
condition_variable.notify(doneOne);
}
}
// Invoke it per frame
void MainThread()
{
condition_variable.notify(goThink);
while(done<taskCount)
condition_variable.wait(doneOne);
Update();
}
And Here is the problem: when the last AIThread done,it notify the MainThread and break the while loop AND SOMETIME CONTINUE TO EXECUTE TO NEXT condition_variable.notify(goThink); . Now the last AIThread still stay in if (!exit) goto Ready; and DOES NOT RECEIVE the notification and stay at condition_variable.wait(goThink); forever. And the MainThread will stay at while(done<taskCount) forever.What should I do?How to write the correct code?