0

I can't figure out how to get a tkinter list box to play continuous audio files in my Music Player without using classes, which I don't fully understand yet since I am new to python. I already created an event by following examples ,that prints the song that played and the next song in the list box but I don't know how to move from there.

SONG_END = pygame.USEREVENT+1
pygame.mixer.music.set_endevent(SONG_END)

def check_event():
    for event in pygame.event.get():
        if event.type == SONG_END:
            print('music end event')
            for i in listbox.curselection():
                nxt_song = listbox.get(i + 1)
                print(nxt_song)

    root.after(100, check_event)

def next_s ():
# i cant figure out how to proceed from here to
# get the nxt song and play it
    pass

def play():
# activates the play button
    current = listbox.get(ACTIVE)
    playing_song['text'] = current # goes to a label displaying the current track name
    mixer.music.load(current)
    mixer.music.play()

# everything works as i want exept continuous play
# note that i dont want the player to have previous and next buttons   
    
3
  • Your check_event function is happening every .1 seconds is that what you really want? If you have been able to print the next song via the binding to nxt_song then what is stopping you from using that? It's easier to make suggestions when you add your attempt. What did you try inside of next_s that didn't work?
    – Rory
    Commented May 17, 2023 at 18:21
  • I dont know how to use it..I cant get the variable nxt_song out of the check_event function..i try to copy the function in new function next_s but i get listbox or nxt_song errors..then i tried to load and play in the next_s function but igot the same errors..after searching for examples i found that such functions were part of a huge class or they were getting the sting values of the playlist form open file directory but that is not what i need,,i need to get nxt_song as a variable to load and play when the check_event happens.
    – andypappy
    Commented May 17, 2023 at 21:00
  • Hi Rory..do yo have any idea how to activate the check_event function at the last n seconds of the song instead of have it running every .1 sec?
    – andypappy
    Commented May 18, 2023 at 9:08

3 Answers 3

0

Suggest to put the logic of finding next song into next_s() instead:

def check_event():
    for event in pygame.event.get():
        if event.type == SONG_END:
            print('music end event')
            next_s() # play next song
    root.after(100, check_event)

def next_s():
    selection = listbox.curselection()
    if selection:
        i = listbox.curselection()[-1] + 1
        if i < listbox.size():
            next_song = listbox.get(i)
            print(f"{next_song=}")
            # update selection
            listbox.selection_clear(0, "end")
            listbox.selection_set(i)
            # play next song
            play()
        else:
            print("no more song")

def play():
    selection = listbox.curselection()
    if selection:
        current = listbox.get(selection[-1])
        playing_song['text'] = current
        pygame.mixer.music.load(current)
        pygame.mixer.music.play()
1
  • i = listbox.curseselection()[-1] + 1 creates error tupple index out of range,,if i replace with for loop goes immediately to print " no more song"
    – andypappy
    Commented May 18, 2023 at 6:38
0

So here is the code that works and allows the Music Player for continuous play..thanks for the inputs that helped a lot. There is a new problem now

If i press the stop Button the music_stop fnction is a check_event and auto starts playback of the next song.I can always press mute and resume and deactivate the music_stop function or remove the music_stop function and button but i would appreciate any ideas that will separate the music_stop function from check_event. I already tried : if event.type == SONG_END and not music_stop in the check_music function but it prevents the next song to load and i am back where i started!

pygame.init()
SONG_END = pygame.USEREVENT+1
pygame.mixer.music.set_endevent(SONG_END)

def check_event():
    for event in pygame.event.get():
        if event.type == SONG_END:
            print('music end event')
            for i in listbox.curselection():
                next_s()

    root.after(100, check_event)

def next_s():
    # assume there is at least one item selected
    for i in listbox.curselection():
        if i < listbox.size():
            next_song = listbox.get(i + 1)
            print(f"{next_song=}")
            # update selection
            listbox.selection_clear(0, "end")
            listbox.selection_set(i + 1)
            # play next song
            mixer.music.load(next_song)
            mixer.music.play()
        else:
            print("no more song")

def pause_song():
    mixer.music.pause()

def play():
    current_song = listbox.get(ACTIVE)
    playing_song['text'] = current_song
    mixer.music.load(current_song)
    mixer.music.play()


def resume_song():
    mixer.music.unpause()

def music_stop():
    #mixer.music.stop()
    pass
2
  • 1
    Note that next_s() will raise exception when it is executed after playing the last song in the listbox because next_song is an empty string.
    – acw1668
    Commented May 18, 2023 at 10:01
  • Well you ae right..i havnt dealt with such an instance yet because the list is long and i always close the programme before the end of the list..so how to catch this exception? if i reloop to first tract when last track is been played by using the listbox index..any suggestions on that?
    – andypappy
    Commented Jun 3, 2023 at 8:27
0

It would be the same thing as playing the song. You would have to do

pygame.mixer.load(next_song) pygame.mixer.play()

Also you would have to adjust the value of the current song so that it will it moving in the list.

current = next_song

SONG_END = pygame.USEREVENT+1
pygame.mixer.music.set_endevent(SONG_END)

current = None

def check_event():
for event in pygame.event.get():
    if event.type == SONG_END:
         pygame.mixer.music.stop()
         next_s()

def next_s():
  next_song = listbox.curselection()
  next_song = next_song[0] + 1
  current = listbox.get(next_song)
  pygame.mixer.music.load(current)
  pygame.mixer.music.play()
  listbox.selection_clear(0, END)
  listbox.activate(next_song)
  listbox.selection_set(next_song, last = None)

def play():
  # activates the play button
  current = listbox.get(ACTIVE)
  playing_song['text'] = current # goes to a label displaying the 
  current track name
  pygame.mixer.music.load(current)
  pygame.mixer.music.play()

# everything works as i want exept continuous play
# note that i dont want the player to have previous and next button
5
  • Can you please be a little more specifiq..nxt_song is not defined outside the check_event function..i tried global but didnt work either..my question is how do i insert this variable in the play function?
    – andypappy
    Commented May 17, 2023 at 21:03
  • You would have to set the current song variable outside of the functions so it can be accessed. Remove everything below print(“music end event”) and just call the next_s function. Then find the next song in list of the current song and set that to the current song. Then load the new current song and play it. Commented May 17, 2023 at 21:08
  • next_song = next_song[0] + 1 creates error tuple index out of range
    – andypappy
    Commented May 18, 2023 at 7:09
  • You would have to add a if statement checking if there are any more songs, if there is that will run, if not it should play the first song. Commented May 18, 2023 at 11:03
  • I also made a music player. This might help you: github.com/Darkshadogt/Dark-Music-Player Commented May 18, 2023 at 11:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.