Pygame midi prevents other input - python-2.7

I wish to have real-time midi input, in order to control some wx.Sliders. I have been able to achieve this, however it prevents interaction with the sliders via the mouse or keyboard and causes the application to crash.
This is the code I have at the moment.
import wx, pygame, pygame.midi
class windowClass(wx.Frame):
def __init__(self, *args, **kwargs):
super(windowClass, self).__init__(*args, **kwargs)
self.basicGUI()
def basicGUI(self):
panel = wx.Panel(self)
self.slider = wx.Slider(panel, -1, 2, 0, 128, pos=(10,25), size=(250,-1), style=wx.SL_AUTOTICKS | wx.SL_LABELS)
sliderText = wx.StaticText(panel, -1, 'Slider 1 ', (8,8))
self.slider2 = wx.Slider(panel, -1, 2, 0, 128, pos=(10,110), size=(250,-1), style=wx.SL_AUTOTICKS | wx.SL_LABELS)
sliderText = wx.StaticText(panel, -1, 'Slider 2', (8,88))
self.Bind(wx.EVT_SLIDER, self.sliderUpdate)
self.SetTitle('Sliders Window!')
self.Show(True)
pygame.init()
pygame.midi.init()
inp = pygame.midi.Input(1)
running = True
while running:
if inp.poll():
dataset = inp.read(1)
control = dataset[0][0][1]
if control > 8:
continue
if control == 1:
value = dataset[0][0][2]
self.slider.SetValue(value)
if control == 2:
value = dataset[0][0][2]
self.slider2.SetValue(value)
pygame.time.wait(10)
def sliderUpdate(self, event):
value1 = self.slider1.GetValue()
value2 = self.slider2.GetValue()
print value1, value2
def main():
app = wx.App()
windowClass(None)
app.MainLoop()
main()
What is causing pygame.midi to take all resources? I have a feeling it is regarding while running = True, however my attempts at trying to close the instance don't seem to work.
How can I have the sliders being controlled by the midi and the mouse calling sliderUpdate? Thanks for any help.

You have a loop that never exits, so your program never reaches the parts that deal with anything except the midi input
I would move the code that is currently in that loop into a function, remove the loop, and add a timer to the panel, e.g.
def basicGUI(self):
... panel stuff
pygame.init()
pygame.midi.init()
timer = wx.Timer(self, -1)
self.Bind(wx.EVT_TIMER, self.OnTimer)
timer.Start(10, False)
def OnTimer(self, event):
inp = pygame.midi.Input(1)
if inp.poll():
dataset = inp.read(1)
control = dataset[0][0][1]
if control > 8:
continue
if control == 1:
value = dataset[0][0][2]
self.slider.SetValue(value)
if control == 2:
value = dataset[0][0][2]
self.slider2.SetValue(value)

Related

Dropbox script/Do something when download done

Maybe I missed something when I looked over the Dropbox uploader https://github.com/andreafabrizi/Dropbox-Uploader . I'm creating a python script that uploads files from a USB plugged into a RPi, but need to have it so when the upload is complete, a boolean changes to false. Is there a way to detect this? Code is commented where I want this to occur.
import pygame
from pygame.locals import *
from subprocess import call
uploadSym = pygame.image.load('uploadsymbol.png')
loadingSym = pygame.image.load('loading.png')
uploadSym = pygame.transform.scale(uploadSym, (250,300))
loadingSym = pygame.transform.scale(loadingSym, (300,300))
rect = uploadSym.get_rect()
rect = rect.move((200,60))
rect = loadingSym.get_rect()
rect = rect.move((200,60))
firstSlide = False
def toggle_fullscreen():
screen = pygame.display.get_surface()
tmp = screen.convert()
caption = pygame.display.get_caption()
cursor = pygame.mouse.get_cursor()
w,h = screen.get_width(),screen.get_height()
flags = screen.get_flags()
bits = screen.get_bitsize()
pygame.display.quit()
pygame.display.init()
screen = pygame.display.set_mode((w,h),flags^FULLSCREEN,bits)
screen.blit(tmp,(0,0))
pygame.display.set_caption(*caption)
pygame.key.set_mods(0)
pygame.mouse.set_cursor( *cursor )
return screen
if __name__ == '__main__':
SW,SH = 640,480
screen = pygame.display.set_mode((SW,SH),pygame.NOFRAME)
pygame.display.set_caption('Uploader')
_quit = False
while not _quit:
for e in pygame.event.get():
if (e.type is KEYDOWN and e.key == K_RETURN and (e.mod&(KMOD_LALT|KMOD_RALT)) != 0):
toggle_fullscreen()
elif e.type is QUIT:
_quit = True
elif e.type is KEYDOWN and e.key == K_ESCAPE:
_quit = True
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
screen = pygame.display.get_surface()
screen.fill([255, 255, 255])
#Click within the given area and upload begins
if 450 > mouse[0] > 250 and 360 > mouse[1] > 60 and click[0] == 1:
firstSlide = True
#T/F keeps png up for new slide
elif firstSlide == True:
loadRot = pygame.transform.rotate(loadingSym,0)
screen.blit(loadRot, rect)
#Upload test file to dropbox
Upload = "/home/pi/Uploader/Dropbox-Uploader/dropbox_uploader.sh upload loading.png /"
call ([Upload], shell=True)
#Here I need an if statement that says, when upload done firstSlide = False
#{
#
#
#}
else:
screen.blit(uploadSym, rect)
pygame.display.update()
The subprocess.call() function returns the exit-code of the command. So the call() will (should) return 0 on success, and non-zero on error.
So:
uploaded_ok = ( subprocess.call( Upload, shell=True) == 0 )
Will give you a True/False success.
NOTE: Link to 2.7 doco, since OP tagged question Python2.7

Cannot populate radio button correctly - Tkinter

I am trying out few things with Tkinter as an exercise.
In my example app i want user to select one option from drop down list. Based on this selection i want to populate the list of radio button. I have created a list of values to populate in dropdown list and a dictionary for radio button. please check the code.
See below some working and not working examples:
As you can see from the picture. The first window works well. Second also. However the third window is not quite correct. The option '410' remains. I am making subsequent selections without closing the application.
I think perhaps i am not declaring the variables at the right place. It would be very helpful if some one can have a look at the code and rectify it.
Code:
from Tkinter import *
import ttk
class App(Frame):
def __init__(self,parent):
Frame.__init__(self)
self.parent = parent
self.v = IntVar()
#self.radio_value = []
#self.i = 0
self.GUI()
def GUI(self):
self.master.title('Example')
self.pack(fill = BOTH, expand = 1)
self.options = ['a1','a2','a3','a4','a5']
self.box_value = StringVar()
self.box = ttk.Combobox( self, textvariable=self.box_value)
self.box.bind("<<ComboboxSelected>>", self.set_Radio)
self.box['values'] = self.options
self.box.current(0)
self.box.grid(row = 0, column = 0 )
self.choices = {'a1':['30', '70', '140', '410'], 'a2': ['a', 'b', 'c'], 'a3': ['x', 'y', 'z'], 'a4':['p', 'q', 'r'], 'a5': ['l', 'm', 'n']}
def set_Radio(self,parent):
i = 0
radio_value = []
if self.box_value.get() in self.choices.keys():
radio_value = self.choices[self.box_value.get()]
print radio_value
for t in radio_value:
i = i+1
b = Radiobutton(self, text=t, variable=self.v, value=t)
b.grid(row = i, column = 0)
def main():
root = Tk()
root.geometry('250x250')
app1= App(root)
root.mainloop()
if __name__ == '__main__':
main()
The problem is that you don't delete the old radiobuttons before creating the new radiobuttons. One solution is to put them in an invisible frame. When you delete the frame, the radiobuttons will automatically be destroyed. Another solution is to keep a reference to them so that you can destroy them individually later.
Here's an example of keeping a reference:
def __init-_(self, parent):
...
self.radios = []
def set_Radio(self,parent):
for widget in self.radios:
widget.destroy()
self.radios = []
...
for t in radio_value:
...
b = Radiobutton(...)
self.radios.append(b)
...

Setting and Retrieving Data with TkInter

I just ran into some strange behavior that has me stumped. I'm writing a simple little GUI for some in-house data processing. I want to allow a user to switch between a few different data-processing modes and input some parameters which define how the data is processed for each mode. The problem is that when the user inputs new parameters, the app ignores requests to switch modes.
The code below replicates the issue. I apologize for the size, this was the shortest code that replicates the problem.
import Tkinter as Tk
class foo(Tk.Frame):
def __init__(self):
self.master = master =Tk.Tk()
Tk.Frame.__init__(self,self.master) #Bootstrap
#Here mode and parameters as key, value pairs
self.data = {'a':'Yay',
'b':'Boo'
}
self.tex = Tk.Text(master=master)
self.tex.grid(row=0,column=0,rowspan=3,columnspan=4)
self.e = Tk.Entry(master=master)
self.e.grid(row=3,column=0,columnspan=4)
self.sv =Tk.StringVar()
self.sv.set('a')
self.b1 = Tk.Radiobutton(master=master,
text = 'a',
indicatoron = 0,
variable = self.sv,
value = 'a')
self.b2 = Tk.Radiobutton(master=master,
text = 'b',
indicatoron = 0,
variable = self.sv,
value = 'b')
self.b3 = Tk.Button(master = master,
text='Apply',command=self.Apply_Func)
self.b4 = Tk.Button(master = master,
text='Print',command=self.Print_Func)
self.b1.grid(row=4,column=0)
self.b2.grid(row=4,column=1)
self.b3.grid(row=4,column=2)
self.b4.grid(row=4,column=3)
def Apply_Func(self):
self.innerdata = self.e.get()
def Print_Func(self):
self.tex.insert(Tk.END,str(self.innerdata)+'\n')
#This is how I'm retrieving the user selected parameters
#property
def innerdata(self):
return self.data[self.sv.get()]
#And how I'm setting the user defined parameters
#innerdata.setter
def innerdata(self,value):
self.data[self.sv.get()] = value
if __name__ == "__main__":
app = foo()
app.mainloop()
Expected behavior:
1) Press button 'a' then 'print' prints:
Yay
2) Press button 'b' then 'print' prints:
Boo
3) Type 'Zep Rocks' into the entry field and press apply
4) Pressing 'print' now yields
Zep Rocks
5) Pressing 'a' then 'print' should yield
Yay
But instead yields
Zep Rocks
Which might be true, but not desired right now. What is going on here?
Edit: I have some new information. Tk.Frame in python 2.7 is not a new-style class. It isn't friendly with descriptors, so rather than interpreting the '=' as a request to use the foo.innerdata's __set__ method, it just assigns the result of self.e.get() to innerdata.
ARGLEBARGLE!!!
Still an open question: how do I get this to do what I want in a clean manner?
So the core problem is that Tk.Frame doesn't subclass from object, so it is not a new-style python class. Which means it doesn't get down with descriptors like I was trying to use. One solution that I found is to subclass my app from object instead.
Code that solves my problem is below:
import Tkinter as Tk
class foo(object):
def __init__(self,master):
self.master = master #Bootstrap
self.mainloop = master.mainloop
self.data = {'a':{'value':7,'metavalue':False},
'b':{'value':'Beeswax','metavalue':True}
}
self.tex = Tk.Text(master=master)
self.tex.grid(row=0,column=0,rowspan=3,columnspan=4)
self.e = Tk.Entry(master=master)
self.e.grid(row=3,column=0,columnspan=4)
self.sv =Tk.StringVar()
self.sv.set('a')
self.b1 = Tk.Radiobutton(master=master,
text = 'a',
indicatoron = 0,
variable = self.sv,
value = 'a')
self.b2 = Tk.Radiobutton(master=master,
text = 'b',
indicatoron = 0,
variable = self.sv,
value = 'b')
self.b3 = Tk.Button(master = master,text='Apply',command=self.Apply_Func)
self.b4 = Tk.Button(master = master,text='Print',command=self.Print_Func)
self.b1.grid(row=4,column=0)
self.b2.grid(row=4,column=1)
self.b3.grid(row=4,column=2)
self.b4.grid(row=4,column=3)
def Apply_Func(self):
self.innerdata = self.e.get()
def Print_Func(self):
self.tex.insert(Tk.END,str(self.innerdata)+'\n')
#property
def innerdata(self):
return self.data[self.sv.get()]
#innerdata.setter
def innerdata(self,value):
self.data[self.sv.get()] = value
if __name__ == "__main__":
master = Tk.Tk()
app = foo(master)
app.mainloop()

Tkinter button doesn't respond (has no mouse over effect)

I'm writing a game that has info that is communicated from client to server and from server to client. One specific (non-playing) client is the monitor, which only displays the game board and players. This works fine, the only thing that doesn't work is the quit button on the GUI. A minor thing, but I would like it to work. :) Plus I think that there might be something pretty wrong with the code, even though it works.
I tried all kind of different commands (sys.exit, quit...) and nothing fixed it.
There's no error message, nothing happens with the button at all. No mouse over effect, nothing if I click it. Relevant code (I removed matrix and server logic because I think it's irrelevant - if it isn't I'll post it):
class Main():
def __init__(self, master):
self.frame = Frame(master)
self.frame.pack()
# Has to be counted up by server class
rounds = 0
# Has to be communicated by server class. If numberwin == numberrobots,
# game is won
numberwin = 0
numberrobots = 2
def draw(self):
if hasattr(self, 'info'):
self.info.destroy()
if hasattr(self, 'quit'):
self.quit.destroy()
print "Main should draw this matrix %s" % self.matrix
[...] lots of matrix stuff [...]
# Pop-Up if game was won
# TODO: Make GUI quittable
if self.numberwin == self.numberrobots:
self.top = Toplevel()
self.msg = Message(self.top, text="This game was won!")
self.msg.pack(side=LEFT)
self.quittop = Button(
self.top, text="Yay", command=self.frame.destroy)
self.quittop.pack(side=BOTTOM)
# TODO: Quit GUI
self.quit = Button(self.frame, text="Quit", command=self.frame.destroy)
self.quit.pack(side=BOTTOM)
# Information on the game
self.info = Label(
self.frame, text="Rounds played: {}, Numbers of robots in win condition: {}".format(self.rounds, self.numberwin))
self.info.pack(side=TOP)
def canvasCreator(self, numberrows, numbercolumns):
# Game board
self.canvas = Canvas(
self.frame, width=numbercolumns * 100 + 10, height=numberrows * 100 + 10)
self.canvas.pack()
class Agent(Protocol, basic.LineReceiver):
master = Tk()
main = Main(master)
# So first matrix is treated differently from later matrixes
flagFirstMatrix = 1
def connectionMade(self):
msg = dumps({"type": "monitor"})
self.sendLine(msg)
print "Sent message:", msg
def dataReceived(self, data):
# Decode the json dump
print "Data received: %s" % data
data = loads(data)
self.main.matrix = np.matrix(data["positions"])
self.main.goals = np.matrix(data["goals"])
self.main.next_move_by_agent = data["next_move"]
self.main.rounds = data["rounds"]
self.main.numberwin = data["win_states"]
if self.flagFirstMatrix == 1:
self.main.numberrows, self.main.numbercolumns = self.main.matrix.shape
self.main.canvasCreator(
self.main.numberrows, self.main.numbercolumns)
self.main.canvas.pack()
self.flagFirstMatrix = 0
self.main.canvas.delete(ALL)
self.main.draw()
self.master.update_idletasks()
self.master.update()
First there is no indentation for class Agent, second for the quit button's "call back" self.frame.destroy is never defined so it doesn't do anything. If you meant tkinter destroy method try self.frame.destroy() or try explicitly defining it. You can also try calling either fram.pack_forget() or fram.grid_forget()
Add master.mainloop() to your last line in terms of the entire lines of code

I keep getting a "self" is not defined error

Im trying to add a media file, so that when you press the key a is plays and you let go it stops, any help would be appreciated!
I get the error code self is not defined and I just need a point the right direction.
from __future__ import division
import math
import sys
import pygame
pygame.mixer.init()
pygame.mixer.pre_init(44100, -16, 2, 2048)
class MyGame(object):
def __init__(self):
"""Initialize a new game"""
pygame.init()
self.width = 800
self.height = 600
self.screen = pygame.display.set_mode((self.width, self.height))
#Load resources
sound = pygame.mixer.music.load("a.mp3")
I keep getting a self is not defined error here
#use a black background
self.bg_color = 0, 0, 0
#Setup a timer to refresh the display FPS times per second
self.FPS = 30
self.REFRESH = pygame.USEREVENT+1
pygame.time.set_timer(self.REFRESH, 1000//self.FPS)
# Now jusr start waiting for events
self.event_loop()
def event_loop(self):
"""Loop forever processing events"""
while 1 < 2:
event = pygame.event.wait()
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
sys.exit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_A:
sound.play()
if event.type == pygame.KEYUP and event.key == pygame.K_A:
sound.stop()
elif event.type == self.REFRESH:
# time to draw a new frame
self. draw()
pygame.display.flip()
else:
pass #an event we dont handle
def draw(self):
"""Updating the display"""
self.screen.fill(self.bg_color)
MyGame().run()
pygame.quit()
sys.exit()
You're mixing tabs and spaces. This confuses Python about how far code is indented: your self.bg_color = 0, 0, 0 line isn't as indented as you think it is. Looking at your raw code:
'class MyGame(object):'
'\tdef __init__(self):'
'\t\t"""Initialize a new game"""'
'\t\tpygame.init()'
'\t\t'
'\t\tself.width = 800'
'\t\tself.height = 600'
'\t\tself.screen = pygame.display.set_mode((self.width, self.height))'
'\t\t'
'\t\t#Load resources'
' sound = pygame.mixer.music.load("a.mp3")'
'\t\t#use a black background'
' self.bg_color = 0, 0, 0'
Note the absence of tabs in two of the last four lines.
Use python -tt your_program_name.py to confirm this, and switch to using four spaces for indentation. Most editors allow you to configure this.