EDIT: I just noticed you got another reply, and that's the boiled down version of all this. But I'm gonna post anyways.
Hey, sorry it took a while, I maybe went a bit overboard on making an example...
I'm also just really slow... But anyways! Here ya go!
I'll explain more afterwards...
This may look like a lot, but it's very simple. I'm just horrible at explaining things simply.
Sorry for the information dump, I can't help it ;_;
I also checked for possible errors, and so that adds a lot to the code. Probably 80% of this is unimportant to your question, but I wanted to give you a fuller explanation. If it's too much, just say, and I can boil it down.
Code: Select all
--Set our seed, so when we use math.random(), the number is actually random...
love.math.setRandomSeed(os.time())
--Where our loaded song will go, so leave it blank for now
local song
--The directory the songs are in
local dir = "songs/"
--What kind of file extensions we are looking for
local validExtensions = {".mp3", ".ogg"}
--The list of valid songs. We will generate this in love.load, so leave this blank too
local dirList
love.load = function(arg)
--Get a list of things in the song folder
dirList = love.filesystem.getDirectoryItems(dir)
--Take out all the directories from the list
for k,v in pairs(dirList) do
if love.filesystem.isDirectory(dir .. v) then
table.remove(dirList, k)
end
end
--Do the same thing, but this time, check the file extensions!
--Any file without an extension in validExtensions will be removed, even those with no extension
for k,v in pairs(dirList) do
for i,vv in ipairs(validExtensions) do
--If this file has a valid extentsion, then we can break out of this inner loop; the file can stay
if string.find(v, vv) then break end
--If we get this far, and this was the last valid extension, then this must be a bad file...
if i == #validExtensions then table.remove(dirList, k) end
end
end
--[[
So now dirList is a sequence of everything in dir
...minus directories
...minus any files without an extension in validExtensions
]]--
--Let's actually load the song now...
pickNewSong()
end
pickNewSong = function()
--The number of the song we will pick from the list (This is NOT the name of the song, just the place in the list)
local songNumber = love.math.random(1, #dirList)
--Load our song, finally...
song = love.audio.newSource(dir .. dirList[songNumber], "stream")
end
love.keypressed = function(key, scancode, isrepeat)
--Get those repeats outta here!
if isrepeat then return end
if key == "n" then
--Can't just stop at one!
--Just make sure we stop the old song before we start a new one
song:stop()
pickNewSong()
end
if key == "p" then
--Is the song stopped? Then play it!
if song:isStopped() then
song:play()
else
--Ok, well maybe its paused? Resume it then!
if song:isPaused() then
song:resume()
else
--Ok well, the only thing it can be now is playing, so um, PAUSE!
song:pause()
end
end
end
if key == "l" then
--Want it to never stop?
song:setLooping(not(song:isLooping()))
end
if key == "s" then
--GAHH NEVER MIND MAKE IT STOPPPPP
song:stop()
end
end
So basically:
[*] Use
love.filesystem.getDirectoryItems to get a sequence of all the items in the directory you give to the function. When I say sequence, I mean a table that only has integer keys, and in
sequential order. So a table like:
Code: Select all
{
[1] = "a",
[2] = "b",
[3] = "c"
}
is a sequence, but if it skipped a number, or used a key that isn't a whole number, it would not be a sequence.
[*] Take out all of the invalid entries in the sequence. When we use getDirectoryItems, it returns something like this
- An example of what love.filesystem.getDirectoryItems returns.
- getDirectoryItems.png (26.84 KiB) Viewed 2372 times
Notice this is a sequence as well! See how it's unorganized, and contains EVERYTHING in the directory? We gotta get rid of that stuff. I used two different for loops to run through the items, and check what they are. The first one checks for directories, and the second checks if
string.find finds any valid extension. If we find a match, break out of the loop. (Thats what the command
break does, it just immediately exits the loop it is nested in) This part could be simplified, but I left it 'expanded' so that it's easier to show and explain.
[*] Finally, I have a separate function for actually loading the song, that way we can use it later if we want to load another! I also spiffed up the keypressed event to include more audio source functions. Most of the functions in love.audio have equivalents in the actual source, and I just prefer to use those. For example:
Code: Select all
love.audio.play(song)
song:play()
love.audio.stop(song)
song:stop()
Those pairs do the same thing, one just has less typing...
You can find all the other things a
song object has in it
here! Some special things for a song can only be accessed this way, such as getting the duration of the song, or skipping to a time in the song, so take a look if you want more control over the playback.
So uh, I think that's it maybe? I have a tendency to only make sense in my own head, so if that was confusing, feel free to ask me to re-explain any parts, or something else if you want to more than this.
Just remember this doesn't have any display at all. The screen is just black while the song plays, and you press keys for the playback commands.
Tell me whatcha think!