-
By December 27, 2013 I will need to have created a music player for a personal project. My schedule is extremely strict for my project to be successful. I've been fine with playing one music file. What I need now is to know how to get different music files to play like an itunes playlist. What I'm thinking is having music files in a folder and having a stream read that folder. BUT I have no idea how to do this. I know that I have to run the music player in a separate thread than the main menu, but have the main menu change variables for playlists to play. What I'm missing now is just, how do you make a playlist? Can you make one sf::Music function have more than one file assigned? If not, how can I achieve something similar? Any help will be appreciated. Thank you very much.
For those of you who are curious, my project is a smart helmet. I think I'm calling it Smart FML Helmet in honor of the library. I chose to use SFML because although the library is made for games, it seems to have everything I need for my project. My software will be a main menu that will have access to a music menu and a stats menu. The music meny will allow you to chose from different playlists/genres. The stats menu will tell you basic stats about the helmet, like time it's been used or battery left. The menu will be easily accessible from a joypad. My idea is to rebuild my PC in my helmet with along with an audio system and an HUD (with a small screen) A joypad will be connected via bluetooth (I'm also having trouble with that if anyone wants to help). The joypad will have easy music access controls. Changing a playlist will be as easy as changing a radio station in Grand Theft Auto V (I could also use help with playlist changing). A strap for the joypad will be built for it to be able to strap onto a motorcycle or ATV handle bar. Thank you for all support in this project. All help will be appreciated.
-
I know that I have to run the music player in a separate thread than the main menu
You don't. sf::Music internally already starts a thread to play the music, so you can handle it asynchronously from your main thread.
What I'm missing now is just, how do you make a playlist?
Are you familiar with STL containers? Then it can be something as simple as std::vector<std::string> with the list of filenames. In your main loop, you check whether the current music is still playing, and if it is not, you advance to the next file, open and play it.
-
Are you familiar with STL containers?
I'm sorry. I'm really new to this. I'm trying to make the best out of the little stuff I know. I'm not familiar at all with STL containers. What I am doing is having a string be my filename. What I'm having trouble with now is checking the music status.
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
int main()
{
//Playlist track number
std::string testMusicFilename;
int testMusic = 1;
//defining filename strings
switch (testMusic) {
case 0:
testMusic = 4;
case 1:
testMusicFilename = "CheckYoSelf.wav";
break;
case 2:
testMusicFilename = "Helicopter.wav";
break;
case 3:
testMusicFilename = "BittersweetSymphony.wav";
case 4:
testMusic = 1;
break;
default:
testMusicFilename = "LevelsGoodFeeling.wav";
break;
}
//Window, sprites, and textures
sf::RenderWindow window(sf::VideoMode(1350, 700), "Smart Fast Multimedia Library Helmet");
sf::Texture mainMenuTexture;
if (!mainMenuTexture.loadFromFile("titleScreen.png")) {
return -1;
}
mainMenuTexture.setSmooth(true);
sf::Sprite mainMenuSprite;
mainMenuSprite.setTexture(mainMenuTexture);
//Opening the music file
sf::Music testingPlaylist;
if (!testingPlaylist.openFromFile(testMusicFilename)) {
return - 1;
}
//Main Window Loop
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event)) //Making sure that the Window can close
{
if (event.type == sf::Event::Closed)
window.close();
}
//Playing Music
testingPlaylist.play();
enum musicStatus = testingPlaylist(sf::SoundSource::getStatus()));
if (musicStatus == Stopped) {
testMusic++;
testingPlaylist.play();
}
window.clear();
window.draw(mainMenuSprite);
window.display();
}
return 0;
}
Can you tell what's wrong? In that "Playing music" section, how can I get that if statement to work? How can I say "if the music is stopped, run this code"? Thanks.
-
I'm sorry. I'm really new to this. I'm trying to make the best out of the little stuff I know. I'm not familiar at all with STL containers.
You had a week time, and the STL container basics would have been learned in a few hours (or less, if you know C++ well). I think that might have been less time than caused by the trouble you have without them ;)
enum musicStatus = testingPlaylist(sf::SoundSource::getStatus()));
Why the enum keyword, and what kind of function call is that? You have to use the correct type (a member of sf::Music, maybe Status, but look at the docs).
sf::Music::Status status = testingPlaylist.getStatus();
And your variable is badly named; testingPlaylist is a single music file, not a playlist. As stated, you need STL containers for lists...
-
I'm sorry. I'm really new to this. I'm trying to make the best out of the little stuff I know. I'm not familiar at all with STL containers.
You had a week time, and the STL container basics would have been learned in a few hours (or less, if you know C++ well). I think that might have been less time than caused by the trouble you have without them ;)
enum musicStatus = testingPlaylist(sf::SoundSource::getStatus()));
Why the enum keyword, and what kind of function call is that? You have to use the correct type (a member of sf::Music, maybe Status, but look at the docs).
sf::Music::Status status = testingPlaylist.getStatus();
And your variable is badly named; testingPlaylist is a single music file, not a playlist. As stated, you need STL containers for lists...
Sorry about not learning to use STL containers. I barely learned the basics before engaging in my projects, and I spent the week learning SFML concepts. I thought STL containers had something to do with SFML. My bad! I'll try to research them right now. May I ask you for one last favor? How can I use the music status in an if statement? Like, how can I make sure that the song will change if the music is stopped? SFML has different syntax than other C++ libraries for if statements, so I'm not sure that I'll be doing it right. Thanks for all your help and suggestions! You really have helped me a lot.
-
How can I use the music status in an if statement? Like, how can I make sure that the song will change if the music is stopped?
Dude, if statements are really most basic C++ stuff, you should have learned them at the very beginning. But since it's Christmas, I'll show you nevertheless ;)
if (music.getStatus() == sf::Music::Stopped)
... // change music (I still don't know how you want to do this, maybe reload?)
SFML has different syntax than other C++ libraries for if statements
No, totally not. if statements are a language feature, their syntax is the same everywhere.
You only have to combine the different parts (like the music status) meaningfully to get a boolean condition.
-
Nexus, thank you for everything. You've been extremely nice and helpful. I was just hoping you could help me with one las thing. Why won't the song change once the previous one is done?
#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
int main()
{
//Music Status Text
sf::Text playingText;
sf::Font base;
if (!base.loadFromFile("Base 02.ttf")) {
return -1;
}
playingText.setFont(base);
playingText.setString("Music is Playing");
playingText.setCharacterSize(24);
playingText.setColor(sf::Color::Green);
//Playlist track number
int trackNumber = 2;
if (trackNumber == -1) {
trackNumber = 3;
}
else if (trackNumber == 4) {
trackNumber = 0;
}
else {trackNumber = trackNumber;}
//Vector Container
std::vector <std::string> testingFiles;
testingFiles.push_back("BitterSweetSymphony.wav");
testingFiles.push_back("Helicopter.wav");
testingFiles.push_back("CheckYoSelf.wav");
testingFiles.push_back("LevelsGoodFeeling.wav");
//Window, sprites, and textures
sf::RenderWindow window(sf::VideoMode(1200, 700), "Smart Fast Multimedia Library Helmet");
sf::Texture mainMenuTexture;
mainMenuTexture.loadFromFile("titleScreen.png");
sf::Sprite mainMenuSprite;
mainMenuSprite.setTexture(mainMenuTexture);
//Opening the music file
sf::Music testingPlaylist;
testingPlaylist.openFromFile(testingFiles[trackNumber]);
//Main Window Loop
while (window.isOpen())
{
sf::Event windowIsClosed;
while (window.pollEvent(windowIsClosed)) //Making sure that the Window can close
{
if (windowIsClosed.type == sf::Event::Closed)
window.close();
}
//Playing Music
testingPlaylist.play();
window.clear();
window.draw(mainMenuSprite);
window.display();
if (testingPlaylist.getStatus() == sf::Music::Stopped) {
trackNumber++;
testingPlaylist.play();
}
while (testingPlaylist.getStatus() == sf::Music::Playing) {
window.clear();
window.draw(mainMenuSprite);
window.draw(playingText);
window.display();
}
//Drawing the window
window.clear();
window.draw(mainMenuSprite);
window.display();
} /*Window Loop Ending*/
return 0;
} /*Main Function ending*/
I think that will be the last I ask for, although I am not sure. I finally learned about STL and Vector containers . Thanks for all the suggestions you have given me.
-
You don't change the sf::Music object, you only call its play() method.
-
So, should I use it like:
play(testingPlaylist)
this? How exacly do you call play for only one specific music object without changing it?
-
Nevermind. Sorry, I realize the stupidity in my question. I thought you were saying I didn't have to use testingplaylist.play() again. My bad! :-[
-
My program is freezing and functioning terribly. I'm not sure what's wrong or what's causing this. I finally successfully got the music to move on, but I still have that one major issue. Trying to click on the window will allow the program to keep on playing the music, but the window will freeze and stop working. Might there be something in my code that causes this? I've already tried to make the window smaller than the desktop so I doubt that it has to do with that. I also tried adding a testing interaction (pausing the music when the space key is pressed) to see if that made What do you think is causing my program to do this?
My current code:
#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
int main()
{
//Rendering the Window
sf::RenderWindow window(sf::VideoMode(1200, 400), "Smart Fast Multimedia Library Helmet");
window.setVerticalSyncEnabled(true);
window.setFramerateLimit(30);
//Music Status Text
sf::Text playingText;
sf::Font base;
if (!base.loadFromFile("Base 02.ttf")) {
return -1;
}
playingText.setFont(base);
playingText.setString("Music is Playing");
playingText.setCharacterSize(24);
playingText.setColor(sf::Color::Green);
sf::Text pausedText;
pausedText.setString("Music is Paused");
pausedText.setCharacterSize(24);
pausedText.setColor(sf::Color::Green);
//Playlist track number
int trackNumber = 3;
while (trackNumber == 4) {
trackNumber = 0;
}
while (trackNumber == -1) {
trackNumber == 3;
}
//Vector Container
std::vector <std::string> testingFiles;
testingFiles.push_back("BitterSweetSymphony.wav");
testingFiles.push_back("Helicopter.wav");
testingFiles.push_back("CheckYoSelf.wav");
testingFiles.push_back("LevelsGoodFeeling.wav");
//Window, sprites, and textures
while (window.isOpen())
{
sf::Texture mainMenuTexture;
mainMenuTexture.loadFromFile("titleScreen.png");
sf::Sprite mainMenuSprite;
mainMenuSprite.setTexture(mainMenuTexture);
//Opening the music file
sf::Music testingPlaylist;
testingPlaylist.openFromFile(testingFiles.at(trackNumber));
//Main Window Loop
sf::Event windowIsClosed;
while (window.pollEvent(windowIsClosed)) //Making sure that the Window can close
{
if (windowIsClosed.type == sf::Event::Closed)
window.close();
}
//Playing Music
testingPlaylist.play();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) {
testingPlaylist.pause();
}
//Making sure the track moves on
while (testingPlaylist.getStatus() == sf::Music::Playing) {
window.clear();
window.draw(mainMenuSprite);
window.draw(playingText);
window.display();
}
while (testingPlaylist.getStatus() == sf::Music::Paused) {
window.clear();
window.draw(mainMenuSprite);
window.draw(pausedText);
window.display();
}
while (testingPlaylist.getStatus() == sf::Music::Stopped) {
trackNumber++;
testingPlaylist.play();
}
//Drawing the window
window.clear();
window.draw(mainMenuSprite);
window.display();
} /*Window Loop Ending*/
return 0;
} /*Main Function ending*/
-
You have multiple lets call it "mini drawing loops" where you aren't handling events. Remove other loops and you should be good.
-
I tried deleting the while (testingPlaylist.getStatus() == sf::Music::Stopped) loop but it wouldn't really work after that. The music simply wouldn't start
-
I tried deleting the while (testingPlaylist.getStatus() == sf::Music::Stopped) loop but it wouldn't really work after that. The music simply wouldn't start
Ever tried if?
-
Ever tried if?
Yup. I tried. The music simply won't start. Isn't there something that I could modify within those loops so that I could still get paused text and playing text?
-
Isn't there something that I could modify within those loops so that I could still get paused text and playing text?
Yes learn C++. Sorry if this sounds rude but this is basic c++ not something special. You have a few essential logic problems.
- You load the titlescreen texture every frame
- You create a new sf::Music object every frame and load the file (your music will restart every frame)
- Your drawing loops are destroying the "normal" frame procedure (Event handling, update logic, rendering) You should use if instead(but you have to fix the second point first)
I my opinion, you should buy/lend a good c++ book/ebook and return after you have solid c++ knowledge.
Here is a list with good c++ books: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list
AlexAUT
-
It's okay. It's not rude. It's true. I have to master C++ in a better way, but for now I do need some hints. Guys, thank you all for your help. I figured out one of the problems. The reason that the music wouldn't play without the glitchy drawing loop was that it was inside the window loop. Now, I moved the music outside of the drawing loop, but the music won't switch. I've tried a lot of things, but no matter what, the track number won't move on when outside of the window loop. This is what my code looks like now (I simplified it to focus on the basic music problem:
#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
int main()
{
//Rendering the Window
sf::RenderWindow window(sf::VideoMode(1200, 400), "Smart Fast Multimedia Library Helmet");
window.setVerticalSyncEnabled(true);
window.setFramerateLimit(30);
//Music Status Text
sf::Text playingText;
sf::Font base;
if (!base.loadFromFile("Base 02.ttf")) {
return -1;
}
playingText.setFont(base);
playingText.setString("Music is Playing");
playingText.setCharacterSize(24);
playingText.setColor(sf::Color::Green);
sf::Text pausedText;
pausedText.setString("Music is Paused");
pausedText.setCharacterSize(24);
pausedText.setColor(sf::Color::Green);
//Vector Container
std::vector <std::string> testingFiles;
testingFiles.push_back("Title Screen.wav");
testingFiles.push_back("firstTrack.wav");
testingFiles.push_back("secondTrack.wav");
testingFiles.push_back("thirdTrack.wav");
//Playlist track number
int trackNumber = 0;
//Opening the music file
sf::Music testingPlaylist;
testingPlaylist.openFromFile(testingFiles.at(trackNumber));
//Playing Music
testingPlaylist.play();
//Making sure that the track moves on
testingPlaylist.getStatus();
if (testingPlaylist.getStatus() == sf::Music::Stopped) {
switch (trackNumber) {
case 0:
trackNumber++;
case 1:
trackNumber++;
break;
case 2:
trackNumber++;
break;
default:
trackNumber = 0;
break;
}
testingPlaylist.play();
}
//Window, sprites, and textures
while (window.isOpen())
{
sf::Texture mainMenuTexture;
mainMenuTexture.loadFromFile("titleScreen.png");
sf::Sprite mainMenuSprite;
mainMenuSprite.setTexture(mainMenuTexture);
//Main Window Loop
sf::Event windowIsClosed;
while (window.pollEvent(windowIsClosed)) //Making sure that the Window can close
{
if (windowIsClosed.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) && testingPlaylist.getStatus() == sf::Music::Playing) {
testingPlaylist.pause();
}
//Drawing the window
window.clear();
window.draw(mainMenuSprite);
window.display();
} /*Window Loop Ending*/
return 0;
} /*Main Function ending*/
-
Well, your switch statement is totally unnecessary. You can accomplish the same thing more easily doing this:
if (trackNumber >= 0 && trackNumber <= 2)
trackNumber++;
else
trackNumber = 0;
-
Thanks, but that's not necessarily my problem. Both the switch and the if statement do absolutely the same thing. My problem is that the music will not start playing again after the track number goes up. Do you think there's a reason for that?
-
You are changing the trackNumber outside the window.isOpen() loop. So, the trackNumber will only be increased once, try using a function that increase the trackNumber and call it inside the loop, after a certain key is pressed by example.
-
Guys, I think this is it. I successfully created a playlist. I feel like I should share in case other people have the same problem. I fixed it by placing my music.openFromFile() outside of the window loop, and my first music.play() outside of the window loop. Inside the window loop, my condition was:
if (music.getStatus() == sf::Music::Stopped)
if (trackNumber <= 2) {
trackNumber++;
}
else
trackNumber = 0;
music.openFromFile(testingFiles.at(trackNumber));
music.play
}
All I did was make the music load again after every track was changed. Thanks for all your help guys. I'll give credit to all of you when presenting my project! ( If you want me to).
-
...fixed it by placing my music.openFromFile() outside of the window loop, and my first music.play() outside of the window loop.
It's good that you got it working, but hopefully this will become a lesson to you. Learn C++ now so you can be independent and won't have to depend on others telling you what to do or by trial and error. I wish you the best of luck. :)
-
You may be interested in this little Jukebox class I wrote a while ago : https://github.com/SFML/SFML/wiki/Source%3A-Jukebox