Hosein Remezan
Hosein Remezan

Reputation: 438

Play/stop music with classes in kivy

I'm trying to execute this:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.audio import SoundLoader,Sound
from kivy.lang import Builder
Builder.load_string('''
<MenuPage>:
    BoxLayout:
        orientation:'vertical'
        Button:
            text:'play'
            on_press:root.plays()
        Button:
            text:'stop'
            on_press:root.stops()
''') 


class Music(Sound):
    def __init__(self):
        self.sound = SoundLoader.load('/home/hosein/Music/Man.mp3')


class MenuPage(Screen):
    def __init__(self):
        self.M = Music()

    def plays(self):
        self.M.play()

    def stops(self):
        self.M.stop()

music = Music()
sm = ScreenManager()
menu = MenuPage(name='menu')
sm.add_widget(menu)


class TestApp(App):
    def build(self):
        return sm




TestApp().run()

https://gist.github.com/daryasary/f69e1d0444ae70ff5296

There should be just two buttons to play or stop a song.

But it doesn't work. What is the solution?

Also, is there any way to make the play and stop buttons into a single button, where the first touch plays the song and the second stops it?

Upvotes: 1

Views: 5855

Answers (3)

Hosein Remezan
Hosein Remezan

Reputation: 438

it should be something like this:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.audio import SoundLoader,Sound
from kivy.lang import Builder
Builder.load_string('''
<MenuPage>:
    BoxLayout:
        orientation:'vertical'
        Button:
            text:'song'
            on_press:root.plays()
''')

class MenuPage(Screen):
    M = SoundLoader.load('/home/hosein/Music/Man.mp3')

    def plays(self):
        if MenuPage.M.state == 'stop':
            MenuPage.M.play()
        else:
            MenuPage.M.stop()


sm = ScreenManager()
menu = MenuPage(name='menu')
sm.add_widget(menu)


class TestApp(App):
    def build(self):
        return sm




TestApp().run()

Upvotes: 1

kitti
kitti

Reputation: 14824

The problem is that you're using Sound wrong. You should not be subclassing Sound or trying to create a new instance directly.

SoundLoader.load returns a Sound instance created using one of the available audio providers - this should be used instead. Try something like this:

class MenuPage(Screen):
    def __init__(self):
        self.M = SoundLoader.load('/home/hosein/Music/Man.mp3')

    def plays(self):
        self.M.play()

    def stops(self):
        self.M.stop()

    def toggle(self):
        self.M.state = 'play' if self.M.state == 'stop' else 'play'
        return self.M.state

Upvotes: 1

mcastle
mcastle

Reputation: 2982

If you want to use one button, you could try using Kivy's ToggleButton and play music when the toggle button's state is 'down' and not play music when the state is 'normal'.

<MenuPage>:
    BoxLayout:
        orientation:'vertical'
        ToggleButton:
            id: music_button
            text:'play'
            on_press:root.play_or_stop()
''')

class MenuPage(Screen):
    def __init__(self):
        self.M = Music()

    def play_or_stop(self):
        if self.music_button.state == 'down':
            self.music_button.text = "Stop"
            self.M.play()
        else:
            self.music_button.text = "Play"
            self.M.stop()

Or, you could use a regular button that sets a variable to either True or False each time it's pressed. You can then have this value determine whether the music plays or stops.

Upvotes: 2

Related Questions