Search code examples
pythonpython-3.xkivykivy-languageandroid-music-player

SoundLoader overlaps songs in kivy, python. How to play a song in place of other in python kivy?


I have been developing an app using python and kivymd
This is a simple music player app which finds all the music in the phone and show it as a list
And when we click on the song name it will play the song But the problem is that the songs overlaps and then it keep on overlapping
What I want is that when we click on any other song the previous one stops and the clicked one starts to play

My previous code in which there is no stop function-:

from kivy.lang import Builder
from kivymd.uix.list import OneLineListItem
from kivymd.app import MDApp
from kivy.core.audio import SoundLoader
import os

helper_string = """
Screen:
    BoxLayout:
        orientation: "vertical"
        ScrollView:
            MDList:
                id: scroll

"""


class MainApp(MDApp):
    def build(self):
        screen = Builder.load_string(helper_string)
        return screen

    def on_start(self):
        for root, dirs, files in os.walk('C:/'):
            for file in files:
                if file.endswith('.mp3'):
                    required_file = file
                    the_location = os.path.abspath(required_file)
                    self.root.ids.scroll.add_widget(OneLineListItem(text=required_file, on_release=self.play_song))
                    # print(required_file)

    def play_song(self, onelinelistitem):
        # print('play:', onelinelistitem.text)
        the_song_path = os.path.abspath(onelinelistitem.text)
        sound = SoundLoader.load(the_song_path)
        if sound:
            sound.play()
        print(the_song_path)


MainApp().run()

My new code in which I tried a simple fix using the lists and it also did not worked -:

from kivy.lang import Builder
from kivymd.uix.list import OneLineListItem
from kivymd.app import MDApp
from kivy.core.audio import SoundLoader
import os

helper_string = """
Screen:
    BoxLayout:
        orientation: "vertical"
        ScrollView:
            MDList:
                id: scroll

"""


class MainApp(MDApp):
    def build(self):
        screen = Builder.load_string(helper_string)
        return screen

    def on_start(self):
        for root, dirs, files in os.walk('C:/'):
            for file in files:
                if file.endswith('.mp3'):
                    required_file = file
                    the_location = os.path.abspath(required_file)
                    self.root.ids.scroll.add_widget(OneLineListItem(text=required_file, on_release=self.play_song))
                    # print(required_file)

    def play_song(self, onelinelistitem):
        SongList = []
        # print('play:', onelinelistitem.text)
        the_song_path = onelinelistitem.secondary_text
        SongList.append(the_song_path)
        if len(SongList) == 1:
            sound = SoundLoader.load(SongList[0])
            if sound:
                sound.play()
            print(the_song_path)
        if len(SongList) > 1:
            SoundLoader.load(SongList[0]).stop()
            sound = SoundLoader.load(SongList[1])
            if sound:
                sound.play()
            print(the_song_path)


MainApp().run()

😅Yes I know that it was a very bad fix

So please can anyone help me out with this issue

Thank you Very Much in advance


Solution

  • Your SongList is a local variable in method play_song() and is set to [] every time play_song() is called. So the condition:

    if len(SongList) > 1:
    

    will never be true. An easy way to handle this is to define an instance variable that holds the currently playing sound, lets call it it self.sound. Initialize it in the build() method:

    def build(self):
        self.sound = None
        screen = Builder.load_string(helper_string)
        return screen
    

    And use it in the play_song() method:

    def play_song(self, onelinelistitem):
        the_song_path = onelinelistitem.secondary_text
        if self.sound:
            self.sound.stop()
        self.sound = SoundLoader.load(the_song_path)
        if self.sound:
            self.sound.play()
        print(the_song_path)