Musicplayer - play next in playlist automatically

Previous topic - Next topic

Faux Clef

I'm pretty new to GLbasic, and I am writing a musicplayer.
i have a array containing all the music to be played, it works fine. But I want the player to automatically jump to the next. I have tried with

Code (glbasic) Select

PLAYMUSIC track[0].filename$, TRUE
draw(track[0], 0, resx,resy)
IF ISMUSICPLAYING()=0
SLEEP 100
i%=i%+1
PLAYMUSIC track[i%].filename$, TRUE
draw(track[i%], i%, resx,resy)
SHOWSCREEN
ENDIF

Hemlos

tried to add STOPMUSIC right before the next playmusic ?
Bing ChatGpt is pretty smart :O

Faux Clef


kanonet

I never use music commands, but if im right you erros is that you used 'PLAYMUSIC filename, TRUE' cuz means its an endless loop, if the song finishes it gets started again. So ISMUSICPLAYING() never returnes false and so your next music track never gets started. Just switch PLAYMUSIC to FALSE should fix it.
Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64

Faux Clef

Thank you very much, so thats why ISMUSICPLAYING() allways was true, even though the track didn't loop

Faux Clef

and it didn't work  :(
is it any way to read the timelength of a mp3 in GLB?

kanonet

The following works for me, it playes the next song:
Code (glbasic) Select
LOCAL music$[], id%=-1
DIMDATA music$[], "1.mp3", "2.mp3"

REPEAT
IF ISMUSICPLAYING()=FALSE
INC id
PLAYMUSIC music$[id], FALSE
ENDIF

PRINT "Playing: "+music$[id], 0,0, 1
SHOWSCREEN
UNTIL KEY(1)
END
Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64

Hemlos

I wrote a thing about playing sounds...lots of them, with perfect precision.

Its probably a bit overwhelming, but once you figgure it out, youll do great.

I use this method to run helicopter sounds and machine guns and a slew of other sounds:
http://www.glbasic.com/forum/index.php?topic=3917.msg36491#msg36491
Bing ChatGpt is pretty smart :O

Falstaff

It's hard to say what's going on without seeing the rest of your code.. maybe it has something to do with your variable "i%"? Has it been defined as global? I like to give my global variables more meaningful names, and only use 1 letter variables for simple local variables that are only used in 1 place ever. This variable should be global because it should retain its state in between calls.

Also you don't have a check for going past the end of your array.

I shared the code I'm using in my game for looping music. It first loads in a playlist of mp3s from the media directory, then shuffles the array, then constantly checks to see if the music is playing and moves to the next track in the list if it isn't. You can see the code for yourself here.

Slydog

I don't know your exact problem, but if it helps any, here's my music / sound effect library:
(it assumes your sound files are in certain sub-folders, as specified at the top of the library)

Code (glbasic) Select
CONSTANT SOUND_PATH_MUSIC$ = "Sounds/Music/"
CONSTANT SOUND_PATH_EFFECTS$ = "Sounds/Effects/"

?IFDEF IPHONE
CONSTANT SOUND_MUSIC_EXT$ = ".m4a"
CONSTANT SOUND_EFFECTS_EXT$ = ".caf"
?ELSE
CONSTANT SOUND_MUSIC_EXT$ = ".mp3"
CONSTANT SOUND_EFFECTS_EXT$ = ".wav"
?ENDIF

GLOBAL _volume_music# = 0.5
GLOBAL _volume_effects# = 0.75

//==============================================================================
//  S O U N D
//==============================================================================

TYPE TSoundEffect
id%
channel%
volume#
pan#
is_playing%
ENDTYPE

TYPE TSound
music_ix%
music_playlist_first%
music$[]
effects[] AS TSoundEffect

FUNCTION Music_Add%: fn$
fn$ = SOUND_PATH_MUSIC$ + fn$ + SOUND_MUSIC_EXT$
DIMPUSH self.music$[], fn$
//LOG(">Music Add: [" + fn$ + "] | ix:[" + BOUNDS(self.music$[], 0) - 1 + "]")
RETURN BOUNDS(self.music$[], 0) - 1
ENDFUNCTION

FUNCTION Music_PlaylistSetFirst%: first%
self.music_playlist_first = first
RETURN TRUE
ENDFUNCTION

FUNCTION Music_PlayList%:
IF self.music_ix < self.music_playlist_first
self.Music_Stop()
self.music_ix = self.music_playlist_first
ENDIF
IF self.Music_IsPlaying() = TRUE THEN RETURN
INC self.music_ix
IF self.music_ix >= BOUNDS(self.music$[], 0)
self.music_ix = self.music_playlist_first
ENDIF
LOG(">MUSIC :: Now Playing: [" + self.music$[self.music_ix] + "]")
PLAYMUSIC self.music$[self.music_ix], FALSE
self.Music_Volume(0.5)
RETURN TRUE
ENDFUNCTION

FUNCTION Music_Play%: song%, b_loop%=FALSE
IF song >= BOUNDS(self.music$[], 0) THEN RETURN
IF (self.music_ix = song) AND (self.Music_IsPlaying()) THEN RETURN

self.music_ix = song
self.Music_Stop()
PLAYMUSIC self.music$[self.music_ix], b_loop
self.Music_Volume(1.0)
RETURN TRUE
ENDFUNCTION

FUNCTION Music_IsPlaying%:
RETURN ISMUSICPLAYING()
ENDFUNCTION

FUNCTION Music_Volume: volume#
MUSICVOLUME volume * _volume_music
ENDFUNCTION

FUNCTION Music_Stop%:
STOPMUSIC
ENDFUNCTION

FUNCTION Effect_Add%: id%, fn$, buffers%=1, b_preload%=FALSE, volume#=1.0, pan#=0.0
LOCAL effect AS TSoundEffect
effect.id = id
effect.volume = volume
effect.pan = pan
effect.channel = BLANK
effect.is_playing = FALSE
fn$ = SOUND_PATH_EFFECTS$ + fn$ + SOUND_EFFECTS_EXT$
//LOG(">Sound Add: [" + fn$ + "] | id:[" + id + "]")
LOADSOUND fn$, effect.id, buffers
DIMPUSH self.effects[], effect
IF b_preload = TRUE THEN self.Effect_Play(id, 0.0)
RETURN TRUE
ENDFUNCTION

FUNCTION Effect_Play%: id%, volume#=BLANK, pan#=BLANK
LOCAL ex%
ex = self.Effect_Find(id)
IF ex < 0 THEN RETURN FALSE
IF volume = BLANK THEN volume = self.effects[ex].volume
IF    pan = BLANK THEN    pan = self.effects[ex].pan
self.effects[ex].channel = PLAYSOUND(id, pan, 1.0)//_volume_effects * volume)
//LOG("Effect_Play: [" + id + "]")
RETURN TRUE
ENDFUNCTION

FUNCTION Effect_IsPlaying%: id%
LOCAL ex%
ex = self.Effect_Find(id)
IF ex < 0 THEN RETURN FALSE
RETURN SOUNDPLAYING(self.effects[ex].channel)
ENDFUNCTION

FUNCTION Effect_Find%: id%
LOCAL ex%
FOR ex = 0 TO BOUNDS(self.effects[], 0) - 1
IF self.effects[ex].id = id THEN RETURN ex
NEXT
RETURN BLANK
ENDFUNCTION

FUNCTION Sound_Mute%:
self.Music_Volume(0.0)
HUSH
RETURN TRUE
ENDFUNCTION

FUNCTION Sound_GetNextId%: b_reset% = FALSE
STATIC id% = 1000
IF b_reset = TRUE THEN id = 0
INC id
RETURN id
ENDFUNCTION

ENDTYPE


Here's some sample code on how I use it:
Code (glbasic) Select
CONSTANT SOUND_MENU% = 2
CONSTANT SOUND_MOVE% = 3
CONSTANT SOUND_MOVE_UP% = 4
CONSTANT SOUND_MOVE_DN% = 5
CONSTANT SOUND_STAR% = 6

GLOBAL MUSIC_INTRO%
GLOBAL MUSIC_MENU%
GLOBAL MUSIC_GAMEOVER%
GLOBAL MUSIC_LIST%

FUNCTION Sound_Initialize:
// MUSIC
MUSIC_INTRO = _Sound.Music_Add("intro")
MUSIC_MENU = _Sound.Music_Add("menu")
MUSIC_GAMEOVER = _Sound.Music_Add("gameover")
MUSIC_LIST = _Sound.Music_Add("song_07")
_Sound.Music_PlaylistSetFirst(MUSIC_LIST)

// EFFECTS
_Sound.Effect_Add(SOUND_MENU, "ting", 1)
_Sound.Effect_Add(SOUND_MOVE, "move_01", 2)
_Sound.Effect_Add(SOUND_MOVE_UP, "move_02", 2)
_Sound.Effect_Add(SOUND_MOVE_DN, "move_03", 2)
_Sound.Effect_Add(SOUND_STAR, "flag_01", 1)
ENDFUNCTION

// Then later on in your main loop . . .
_Sound.Music_PlayList()
// or
_Sound.Effect_Play(SOUND_MOVE_DN)
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Faux Clef

my type
Code (glbasic) Select

TYPE TTrack
artist$
songtitle$
filename$
graphics$
ENDTYPE


Creates a array of the type TTrack
aSongs[] AS TTrack
pushes stuff into the array.



my player function:

Code (glbasic) Select

GLOBAL i%
LET i%=0
FUNCTION play: track[] AS TTrack
LOCAL currvolume=0.5, volume
MUSICVOLUME currvolume
init(resx, resy,"16.jpg",1)
SLEEP 5000

//Spill av uforstyrret
nexttrack:
PLAYMUSIC track[i%].filename$, FALSE
WHILE (ISMUSICPLAYING()=TRUE)
curplay:
draw(track[i%], i%, resx,resy)
IF KEY(203)=1
GOTO prev //prevtrack
ELSEIF KEY(205)=1
GOTO skip //nexttrack right arrow
ELSEIF KEY(57)=1
GOTO ablab //about Space hold
ELSEIF KEY(200)=1
GOSUB greetScroller //Alternative greeter down arrow
ELSEIF KEY(28)=1
GOSUB pause //pause return
ELSEIF KEY(1)=1
END
ENDIF

WEND
STOPMUSIC

i%=i%+1
IF i%>11 THEN END

SLEEP 100
GOTO nexttrack


prev:
IF i%<1
i%=0
GOTO curplay
ELSE
STOPMUSIC
i%=i%-1
GOTO nexttrack
ENDIF
GOTO curplay


skip:
STOPMUSIC
IF i%>11
i%=12
GOTO curplay
ELSE
i%=i%+1
GOTO nexttrack
ENDIF
GOTO curplay


I was looking for a way to do this without the labels and still having a functional commandloop, but this works fine
Thanks for all the help  :)