0

I am building a simple audio player in Python. However, when I add a song, the data fields are empty but the song is able to start when I press the play button. Also, the radio button IntVar returns 0 no matter what. So the issue has to do with the StringVars and IntVar. I thought it had something to do with the scope of the window but even if I don't destroy it, it still doesn't work. I have also tried using Global for the variables instead. Any help would be appreciated. Also, I know my code isn't optimized but please only comment on why I might be having issues.

from tkinter import *
import pygame
from MusicPlayer.DoublyCircularLLClass import *
from tkinter import filedialog
from tkinter import messagebox

class songClass:
    def __init__(self, songname, songartist, songalbum, songfilename):
        self.name = songname
        self.artist = songartist
        self.album = songalbum
        self.filename = songfilename
        return

class MusicPlayer:
    def __init__(self):
        pygame.mixer.init()
        self.nodeList = DoublyLinkedList()
        root = Tk()
        root.title('The Better iTunes')
        paused = False
        database = open('SongDatabase.txt', 'r')
        read = database.readlines()
        database.close()

        for line in read:
           read = line.strip()
           tempsong = read.split(',')
           self.nodeList.addToRear(songClass(tempsong[0], tempsong[1], tempsong[2], tempsong[3]))

        self.currentSong = self.nodeList.firstNode
        pygame.mixer.music.load(self.nodeList.firstNode.data.filename)

        self.nameLabel = Label(root, text = self.currentSong.data.name)
        self.nameLabel.pack(side= LEFT)
        self.artistLabel = Label(root, text = self.currentSong.data.artist)
        self.artistLabel.pack(side= LEFT)
        self.albumLabel = Label(root, text = self.currentSong.data.album)
        self.albumLabel.pack(side= LEFT)
        #albumCoverLabel = Label(root, text = "")

        Button(root, text='Play', command = self.playsong).pack(side= LEFT)
        Button(root, text='Stop', command = self.stopsong).pack(side= LEFT)
        self.pauseB = Button(root, text='Pause', command = self.pausesong)
        self.pauseB.pack(side= LEFT)
        Button(root, text='Next', command = lambda direction ="Next": self.updateSong(direction)).pack(side= LEFT)
        Button(root, text='Previous', command = lambda direction ="Prev": self.updateSong(direction)).pack(side= LEFT)
        Button(root, text='Delete', command = self.delete).pack(side= LEFT)
        Button(root, text='Add', command = self.add).pack(side= LEFT)
        Button(root, text='Search', command = self.search).pack(side= LEFT)

        root.mainloop()

    def playsong(self):
        pygame.mixer.music.play()
        self.pauseB["text"] = "Pause"

    def pausesong(self):
        global paused
        if paused:
            pygame.mixer.music.unpause()
            self.pauseB["text"] = "Pause"
            paused = False
        else:
            pygame.mixer.music.pause()
            self.pauseB["text"] = "Resume"
            paused = True

    def stopsong(self):
        pygame.mixer.music.stop()
        self.pauseB["text"] = "Pause"

    def delete(self):
        self.currentSong = self.currentSong.next
        self.nodeList.removeCurrent(self.currentSong.prev)
        self.nameLabel["text"] = self.currentSong.data.name
        self.artistLabel["text"] = self.currentSong.data.artist
        self.albumLabel["text"] = self.currentSong.data.album
        self.pauseB["text"] = "Pause"
        return

    def add(self):
        self.addWindow = Toplevel()
        self.addWindow.title('Enter Song Info')
        addName = StringVar()
        addArtist = StringVar()
        addAlbum = StringVar()
        nameEntry = Entry(self.addWindow, textvariable = addName).pack(side=LEFT)
        artistEntry = Entry(self.addWindow, textvariable = addArtist).pack(side=LEFT)
        albumEntry = Entry(self.addWindow, textvariable = addAlbum).pack(side=LEFT)
        filenameLocation = filedialog.askopenfilename()
        Button(self.addWindow, text='Submit', command = lambda name = addName.get(), artist = addArtist.get(), album = addAlbum.get(), filename = filenameLocation: self.updateList(name, artist, album, filename)).pack(side= LEFT)
        return

    def updateList(self, name, artist, album, filename):
        self.nodeList.addToRear(songClass(name, artist, album, filename))
        self.addWindow.destroy()
        return

    def search(self):
        self.searchWindow = Toplevel()
        self.searchWindow.title('Search Song')
        selection = IntVar()
        selection.set(0)
        radioA = Radiobutton(self.searchWindow, variable=selection, value=0)
        radioB = Radiobutton(self.searchWindow, variable=selection, value=1)
        radioA.pack()
        radioB.pack()
        searchInfo = StringVar()
        searchEntry = Entry(self.searchWindow, textvariable=searchInfo).pack(side=LEFT)
        Button(self.searchWindow, text='Search', command=lambda info=searchInfo.get(), type=selection.get(): self.updateSearch(type, info)).pack(side=LEFT)
        return

    def updateSearch(self, type, info):
        self.searchWindow.destroy()
        searchSong = self.nodeList.firstNode
        print(type)
        if type == 0:
            for i in range(self.nodeList.size):
                if searchSong.data.name == info:
                    self.currentSong = searchSong
                    self.nameLabel["text"] = self.currentSong.data.name
                    self.artistLabel["text"] = self.currentSong.data.artist
                    self.albumLabel["text"] = self.currentSong.data.album
                    self.pauseB["text"] = "Pause"
                    break
                else:
                    print(searchSong.data.name)
                    print(info)
                    searchSong = searchSong.next
            messagebox.showinfo('Error', 'Song not found')
        else:
            for i in range(self.nodeList.size):
                if searchSong.data.artist == info:
                    self.currentSong = searchSong
                    self.nameLabel["text"] = self.currentSong.data.name
                    self.artistLabel["text"] = self.currentSong.data.artist
                    self.albumLabel["text"] = self.currentSong.data.album
                    self.pauseB["text"] = "Pause"
                    break
                else:
                    searchSong = searchSong.next
            messagebox.showinfo('Error', 'Artist not found')
        return

    def updateSong(self, direction):
        if direction == "Next":
            pygame.mixer.music.load(self.currentSong.next.data.filename)
            self.currentSong = self.currentSong.next
        else:
            pygame.mixer.music.load(self.currentSong.prev.data.filename)
            self.currentSong = self.currentSong.prev
        self.nameLabel["text"] = self.currentSong.data.name
        self.artistLabel["text"] = self.currentSong.data.artist
        self.albumLabel["text"] = self.currentSong.data.album
        self.pauseB["text"] = "Pause"
        return

m1 = MusicPlayer()
1
  • 2
    Welcome to stackoverflow! You might have to reduce the code quite a bit to make it easier for people to help you. Can you produce shorter example code? Commented Mar 1, 2016 at 13:25

1 Answer 1

2
Button(self.addWindow, text='Submit', command=lambda name=addName.get(), artist=addArtist.get(), album=addAlbum.get(), filename=filenameLocation: self.updateList(name, artist, album, filename)).pack(side=LEFT)

Your command is the huge lambda function. The lambda function has lots of default arguments. Those default arguments are evaluated when you make the function (rather than when you call it). At that time, your variables (addName, addArtist, etc.) are still empty.

You need the command function to only evaluate addName.get() when the button is clicked (so within the lambda function, though I recommend just using a regular function instead) rather than in the default argument list.

Side issue: you don't need to use StringVars if your Entry is so short-lived. You can just use my_entry.get() directly.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much, that worked. I had tried not using lambda and instead just making the StringVars global and getting them rather then passing parameters and that didn't work either.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.