How to use C++ PlaySound() function with sound from resources? - c++

I'm trying to play the song in simple console executable. However after running the .exe the song doesn't play and the windows notification sound appears instead in loop. The resources are created properly (l am using Codeblocks so l can see them in /obj/debug/) so l suppose that's because the PlaySound() path that l set doesn't lead to the right directory.
How to set the path to resources in PlaySound() function? Thank you in advance
play/main.cpp:
#include <iostream>
#include <thread>
#include <windows.h>
#include <mmsystem.h>
void play() {
PlaySound(TEXT("a18.wav"), NULL, SND_FILENAME|SND_LOOP|SND_ASYNC);
}
int main() {
std::thread t(play);
system("pause>>nul");
t.join();
return 0;
}
play/song.rc:
song WAVE "/rsrc/a18.wav"

SND_FILENAME is the wrong flag to use when the audio is in a resource. You need to use the SND_RESOURCE flag instead.
The .rc you have shown is assigning a non-numeric ID song to the resource, you need to use that ID to play the resource. There is even an example of this in PlaySound's documentation: Playing WAVE Resources. In comments, you say you tried MAKEINTRESOURCE(IDR_WAVE1) as the resource ID to play, but MAKEINTRESOURCE() works only with numeric IDs.
Also, you are using the SND_ASYNC flag, which means PlaySound() will exit immediately, thus your thread will terminate immediately, making it useless. You don't really need the thread at all, unless you remove the SND_ASYNC flag.
Try this instead:
#include <windows.h>
#include <mmsystem.h>
#include <cstdlib>
int main() {
PlaySound(TEXT("song"), GetModuleHandle(NULL), SND_RESOURCE|SND_LOOP|SND_ASYNC);
std::system("pause>>nul");
PlaySound(NULL, NULL, 0);
return 0;
}
Alternatively:
#include <thread>
#include <atomic>
#include <cstdlib>
#include <windows.h>
#include <mmsystem.h>
std::atomic_bool stop(false);
void play() {
while (!stop.load()) {
PlaySound(TEXT("song"), GetModuleHandle(NULL), SND_RESOURCE);
}
}
int main() {
std::thread t(play);
std::system("pause>>nul");
stop.store(true);
t.join();
return 0;
}

Related

how to add a background sound in my program that does not stop until I close the console in c++

The issue I'm facing is that the sound is not running in a loop, the whole sound is executed once, it does not repeat.
So basically, I have used this method:
#include <Windows.h>
#include <thread>
#include <iostream>
void play_music() {
PlaySoundA("sound.wav", NULL, SND_FILENAME | SND_LOOP);
}
int main(){
std::thread t(play_music);
//code
t.join();
}
From the documentation:
SND_LOOP
The sound plays repeatedly until PlaySound is called again with the pszSound parameter set to NULL. If this flag is set, you must also set the SND_ASYNC flag.
The SND_LOOP flag requires the SND_ASYNC flag, which means PlaySoundA() will exit immediately, and thus your thread will terminate, which will cause join() to exit, allowing main() to exit.
If you want to play the sound in a synchronous loop, then remove the SND_LOOP flag and call PlaySoundA() in a loop instead, eg:
#include <Windows.h>
#include <thread>
#include <iostream>
#include <atomic>
std::atomic_bool keep_playing{ true };
void play_music() {
while (keep_playing.load()) {
PlaySoundA("sound.wav", NULL, SND_FILENAME);
}
}
int main(){
std::thread t(play_music);
//code
keep_playing.store(false);
t.join();
}
But in this case, you don't actually need the thread at all, just let SND_ASYNC to its job, eg:
#include <Windows.h>
#include <iostream>
int main(){
PlaySoundA("sound.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
//code
PlaySoundA(NULL, NULL, 0);
}

C++ std::thread makes segmentation fault error when it was used with SFML [duplicate]

im new to sfml and c++.and I have a project that uses the sfml library's to draw the graphics but when I add an additional thread to my program it fails to execute the code inside the thread. this is my code:(please help me!)
#include <SFML\Graphics.hpp>
#include <SFML\window.hpp>
#include <SFML\system.hpp>
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int h(sf::RenderWindow* win){
//do something
win->close();
this_thread::sleep_for(chrono::milliseconds(10));
return 0;
}
int main(){
sf::RenderWindow window(sf::VideoMode(800,600),"My window");
thread t1(h,&window);
_sleep(10000000);
t1.join();
return 0;
}
http://www.sfml-dev.org/tutorials/2.0/graphics-draw.php#drawing-from-threads
SFML supports multi-threaded drawing, and you don't even have to do
anything to make it work. The only thing to remember is to deactivate
a window before using it in another thread; that's because a window
(more precisely its OpenGL context) cannot be active in multiple
threads at the same time.
call window.setActive(false); in your main(), before you pass it off to the thread.
And remember that you must handle events in the GUI thread (the main thread) for maximum portability.

Is there a simple way to play a sound in a background thread using SFML

I am trying to play a song in a background thread of my GUI application so that the song doesn't block the GUI thread. Is there a simple way to do this with either std::thread or SFML Threads?
I have tried using std::thread for this, but it still blocks the GUI thread when I call my_thread.join().
Here is an example of what I want to do:
#include <thread>
#include <SFML/Audio.hpp>
#include <unistd.h>
#include <iostream>
void func() {
sf::Music music;
music.openFromFile("mysong.wav");
music.play();
// if I don't have usleep here the function exits immediately
// why is that exactly???
usleep(100000000);
}
int main() {
std::thread my_thread(func);
my_thread.join();
// this is where I would process events/build windows in GUI
while(1)
std::cout << "here"; // <--- Want this to run while song plays
}
in SFML you need to have a valid sf::Sound or sf::Music for music to play, when that variable gets destroyed you will no longer have a valid reference to that object a possible solution for the code you posted would be something like this:
#include <SFML/Audio.hpp>
#include <unistd.h>
#include <iostream>
class CAudio
{
sf::Music music;
public:
void func()
{
music.openFromFile("mysong.wav");
music.play();
}
sf::Status getStatus()
{
return music.getStatus();
}
}
int main() {
CAudio my_music;
my_music.func();
// http://www.sfml-dev.org/documentation/2.0/SoundSource_8hpp_source.php
while(my_music.getStatus() == sf::Status::Playing)
{
std::cout << "here"; // <--- Want this to run while song plays
}
}
Also, always use brackets, regardless if its a 1 line statement always use brackets, I know its allowed but it will make your life easier when you troubleshoot later on.

Unable to call `SetWallpaper()` due to error LNK2019

Intro
First of all, I would like to say that I have read through the previous answers for this type of question, including this excellently written one.
However, I do not understand enough about C++ to be able to use the more "advanced" fixes.
I have ensured that the right type of console has been selected (Console (/SUBSYSTEM:CONSOLE) for those interested), and have the required imports with the possible exception of an IDL mentioned somewhere (that falls into the lack of understanding category).
If this is a duplicate, I would be more than happy to use the post I duplicated, but I have not been able to find anything that can help someone of my skill level.
Technical Information
IDE: Visual Studio
Platform: Windows
Code
headers.h
#pragma once
#include <stdio.h>
#include <iostream>
#include <string>
#include <windows.h>
#include <Shobjidl.h>
#include <time.h>
#include <stdlib.h>
#include <tchar.h>
main.cpp
#include "headers.h"
using namespace std;
int main() {
string x = "C://Users/student/Desktop/i-should-buy-a-boat.jpg";
x.c_str();
wstring tempx = std::wstring(x.begin(), x.end());
LPCWSTR sw = tempx.c_str();
HRESULT SetWallpaper(
LPCWSTR monitorID,
LPCWSTR wallpaper
);
SetWallpaper(NULL, sw);
}
SetWallpaper() is not a standalone function exported by the Win32 API. It is a method of the IDesktopWallpaper interface (see here).
So you need to use code that is more like this instead:
#include "headers.h"
int main()
{
std::wstring x = L"C:\\Users\\student\\Desktop\\i-should-buy-a-boat.jpg";
CoInitialize(NULL);
IDesktopWallpaper *p;
if (SUCCEEDED(CoCreateInstance(__uuidof(DesktopWallpaper), 0, CLSCTX_LOCAL_SERVER, __uuidof(IDesktopWallpaper), (void**)&p)))
{
p->SetWallpaper(NULL, x.c_str());
p->Release();
}
CoUninitialize();
return 0;
}

SFML fails in multithreading

im new to sfml and c++.and I have a project that uses the sfml library's to draw the graphics but when I add an additional thread to my program it fails to execute the code inside the thread. this is my code:(please help me!)
#include <SFML\Graphics.hpp>
#include <SFML\window.hpp>
#include <SFML\system.hpp>
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int h(sf::RenderWindow* win){
//do something
win->close();
this_thread::sleep_for(chrono::milliseconds(10));
return 0;
}
int main(){
sf::RenderWindow window(sf::VideoMode(800,600),"My window");
thread t1(h,&window);
_sleep(10000000);
t1.join();
return 0;
}
http://www.sfml-dev.org/tutorials/2.0/graphics-draw.php#drawing-from-threads
SFML supports multi-threaded drawing, and you don't even have to do
anything to make it work. The only thing to remember is to deactivate
a window before using it in another thread; that's because a window
(more precisely its OpenGL context) cannot be active in multiple
threads at the same time.
call window.setActive(false); in your main(), before you pass it off to the thread.
And remember that you must handle events in the GUI thread (the main thread) for maximum portability.