Quick answer: pygame.mixer.music.set_endevent(pygame.USEREVENT + 1) before play(). Listen for it in the event loop.

You queue up the next track on song end. Track finishes. Nothing happens. You never told the mixer to post an end event.

The Fix

import pygame
pygame.init()
pygame.mixer.init()

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

pygame.mixer.music.load("bgm_intro.ogg")
pygame.mixer.music.play()

playlist = ["bgm_loop1.ogg", "bgm_loop2.ogg"]
idx = 0

while running:
    for event in pygame.event.get():
        if event.type == MUSIC_END:
            pygame.mixer.music.load(playlist[idx])
            pygame.mixer.music.play()
            idx = (idx + 1) % len(playlist)

Now end-of-track posts to the queue. You handle it like any other event — queue next, fade, switch, whatever.

Verifying

Play a 5-second clip. After 5 seconds, MUSIC_END fires; next track loads and plays. Sequence persists across the playlist.

“set_endevent before play. Event posts. Playlist advances.”

Related Issues

For Rect float warning, see Rect warning. For Clock vsync, see Clock vsync.

set_endevent. Event posts. Playlist runs.