Python/Pygame script not responding when closed, while Renoise is open - python

I'm writing a Python script using Pygame and OSC that will allow me to control the music tracker software Renoise (version 3.0.0) by doing things in a Pygame (1.9.1) environment and sending messages to the software via OSC. If you're wondering, the purpose of this script is for live performance and generative music creation. I'm having a pretty annoying issue, however: when I try to close the Pygame window, it just hangs - doesn't even respond to Control+C - but this only happens if Renoise is open, or has been opened at least once during the session. If I reboot and run the script without opening Renoise, it works as intended. What could possibly be the issue here?
I'm using Python version 2.7.6, Pygame version 1.9.1, and Renoise version 3.0.0. This is all running on an Xubuntu 14.04 laptop.
Code for my main script (the imported OSC module is simply OSC.py available in many places on the internet):
#!/usr/bin/python
import sys
import pygame
import OSC
from pygame.locals import *
class Pot:
def __init__(self, ip, port):
self.clk = pygame.time.Clock()
self.screen = pygame.display.set_mode( (1600, 900) )
self.fillColor = pygame.Color(255,255,255)
pygame.display.set_caption("Pygame OSC Test")
self.client = OSC.OSCClient()
self.client.connect( (ip, port) )
def oscsend(self, addr, *data):
msg = OSC.OSCMessage()
msg.setAddress("/renoise" + str(addr))
for d in data:
msg.append(d)
try:
self.client.send(msg)
except OSC.OSCClientError, err:
print err
def tick(self):
# clear the screen
self.screen.fill(self.fillColor)
#TODO: other drawing stuff here
# process events
for event in pygame.event.get():
if event.type == QUIT:
self.client.close()
del(self.client)
return False
pygame.display.update()
self.clk.tick(10)
return True
if __name__ == "__main__":
p,f = pygame.init()
print "Num modules passed:", p
print "Num modules failed:", f
pot = Pot("localhost", 8000)
running = True
while running:
running = pot.tick()
pygame.quit()
sys.exit(0)

I managed to fix my problem by making sure pygame.mixer wasn't initialized. I assume it was causing some problems with Renoise by them both using the sound hardware at the same time.
To only initialize certain modules of pygame, just call their initialization methods individually. For instance, pygame.display.init() will initialize the Display module. Calling pygame.init() is simply a shortcut to initializing all the currently loaded modules. Hope this helps somebody!

Edited version after a closer look: You are returning False when the programme is quitted. But the variable "running" still remains true! Your loop is still going about his business and happily looping there...
I'd change it this way:
for event in pygame.event.get():
if event.type == QUIT:
self.client.close()
del(self.client)
pygame.quit()
sys.exit()
2nd option:
return False
Change this part that "running" is set to false. i'd go with the first option though.
If that doesn't solve the problem, please let me know, that would be an interesting issue to have a closer look at.

Related

Segmentation fault when running "assistant_library_demo.py" using the AIY voice kit and Raspberry Pi

I am a very new programmer and wanted to try out the AIY voice kit that uses Google Assistant API. I have a step-by-step guide that pretty much tells me how to set it up but now when it's up and running the guide tells me to run "assistant_library_demo.py" which is to make sure that the google assistant understands you. I have already done a mic check and sound check which worked perfectly.
However, when I run it I only get
pi#raspberrypi:~/AIY-projects-python $ src/examples/voice/assistant_library_demo.py
Segmentation fault
I've tried google but only found out that Segmentation fault means that the program crashed. I am not sure what to do from here since I am not very good at programming. Please let me know if I need to give any more information.
This is the code that I'm trying to run
import logging
import platform
import sys
from google.assistant.library.event import EventType
from aiy.assistant import auth_helpers
from aiy.assistant.library import Assistant
from aiy.board import Board, Led
def process_event(led, event):
logging.info(event)
if event.type == EventType.ON_START_FINISHED:
led.state = Led.BEACON_DARK # Ready.
logging.info('Say "OK, Google" then speak, or press Ctrl+C to quit...')
elif event.type == EventType.ON_CONVERSATION_TURN_STARTED:
led.state = Led.ON # Listening.
elif event.type == EventType.ON_END_OF_UTTERANCE:
led.state = Led.PULSE_QUICK # Thinking.
elif (event.type == EventType.ON_CONVERSATION_TURN_FINISHED
or event.type == EventType.ON_CONVERSATION_TURN_TIMEOUT
or event.type == EventType.ON_NO_RESPONSE):
led.state = Led.BEACON_DARK
elif event.type == EventType.ON_ASSISTANT_ERROR and event.args and event.args['is_fatal']:
sys.exit(1)
def main():
logging.basicConfig(level=logging.INFO)
credentials = auth_helpers.get_assistant_credentials()
with Board() as board, Assistant(credentials) as assistant:
for event in assistant.start():
process_event(board.led, event)
if __name__ == '__main__':
main()
It appears that you need to load an older version of the library for V1 AIY Voice to work.
Try pip3 install google-assistant-library==1.0.0
I also ran into the same problem. Here is the fix I googled.
Fix from the ref link:
--- env/lib/python3.7/site-packages/google/assistant/library/assistant.py~ 2019-12-18 08:07:00.039021501 +0000
+++ env/lib/python3.7/site-packages/google/assistant/library/assistant.py 2019-12-18 08:31:35.365685657 +0000
## -100,8 +100,7 ##
self._inst = c_void_p(
self._lib.assistant_new(
self._event_callback,
- device_model_id.encode('ASCII')))
+ device_model_id.encode('ASCII'), None))
self._credentials_refresher = CredentialsRefresher(
credentials, self._set_credentials)
## -278,7 +277,7 ##
# void* assistant_new(EventCallback listener, const char*
# device_model_id);
- self._lib.assistant_new.argtypes = [EVENT_CALLBACK, c_char_p]
+ self._lib.assistant_new.argtypes = [EVENT_CALLBACK, c_char_p, c_char_p]
self._lib.assistant_new.restype = c_void_p
# void assistant_free(void* instance);
This may not be helpful but I had the same problem in getting mine to run. On page https://lb.raspberrypi.org/forums/viewtopic.php?t=249368
I found this comment on the same problem:
Re: google-assistant-demo and googlesamples-assistant-hotword segmentation fault
Quote
Sun Nov 10, 2019 1:52 pm
This is due to the deprecated google-assistant-library. The Google Assistant Service no longer supports hotword detection. “Ok Google” and “Hey Google” are no longer supported. There are still options out there to use the library. Check out the aiyprojects-raspbian on github.
The second option is to use another library to convert the speech to text and pass it the the assistant service api. Snowboy looks like a viable option, with what seems like quite a bit of configuration.
I did not try Snowboy yet but there seems to be a lot posted on it and people I know have used it.
This page links code that he says works with Snowboy (I have not tried it)
https://cyber-renegade.org/2017/12/21/aiy-voice-kit-voice-vad-or-hotword-activation/
Hope this helps.

PyImgui Graphical User Interface not visible

So I just started coding GUI in python and after coding some stuff in tkinter i felt like I might as well use imgui as I know some stuff about it from C++.
Now starting to read the docs and somehow the imgui window isn't showing up. I just see a console pop open for a milisecond but no gui.
# initilize imgui context (see documentation)
imgui.create_context()
imgui.get_io().display_size = 100, 100
imgui.get_io().fonts.get_tex_data_as_rgba32()
# start new frame context
imgui.new_frame()
# open new window context
imgui.begin("Your first window!", True)
# draw text label inside of current window
imgui.text("Hello world!")
# close current window context
imgui.end()
# pass all drawing comands to the rendering pipeline
# and close frame context
imgui.render()
imgui.end_frame()
I feel like I didn't choose any engine to render but I'm not sure.
Yes, if you don't select a backend renderer for pyimgui, it won't render anything. I think you might find an imgui.ini file with imgui's interpretation of what you've asked for, in the current directory, but you won't get any graphical output.
To get graphical output, select a renderer, like in this file in the master pyimgui repository:
https://github.com/swistakm/pyimgui/blob/master/doc/examples/integrations_pygame.py
Note that, as I write this, most but not all of the examples in this directory work:
https://github.com/swistakm/pyimgui/tree/master/doc/examples
The "all in one" example did not work for me, and the SDL2 example required changing:
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16)
to:
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4)
as my GPU doesn't seem to do 16-point multisampling.
Also, these examples don't play well with Python3 in that the error prints() are wrong, and will fail instead of printing a useful error:
print("Error: SDL could not initialize! SDL Error: " + SDL_GetError())
should be:
print("Error: SDL could not initialize! SDL Error: ", SDL_GetError())
So, if you get any errors at these lines, you know what to do. :-)
Finally, for future searchers, here is a quick cut and paste of the pygame version which works for me (from https://github.com/swistakm/pyimgui/blob/master/doc/examples/integrations_pygame.py ). I ran it with python 3.6:
#!/usr/bin/env python3
from __future__ import absolute_import
import sys
import pygame
import OpenGL.GL as gl
from imgui.integrations.pygame import PygameRenderer
import imgui
def main():
pygame.init()
size = 800, 600
pygame.display.set_mode(size, pygame.DOUBLEBUF | pygame.OPENGL | pygame.RESIZABLE)
imgui.create_context()
impl = PygameRenderer()
io = imgui.get_io()
io.display_size = size
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
impl.process_event(event)
imgui.new_frame()
if imgui.begin_main_menu_bar():
if imgui.begin_menu("File", True):
clicked_quit, selected_quit = imgui.menu_item(
"Quit", 'Cmd+Q', False, True
)
if clicked_quit:
exit(1)
imgui.end_menu()
imgui.end_main_menu_bar()
imgui.show_test_window()
imgui.begin("Custom window", True)
imgui.text("Bar")
imgui.text_colored("Eggs", 0.2, 1., 0.)
imgui.end()
# note: cannot use screen.fill((1, 1, 1)) because pygame's screen
# does not support fill() on OpenGL sufraces
gl.glClearColor(1, 1, 1, 1)
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
imgui.render()
impl.render(imgui.get_draw_data())
pygame.display.flip()
if __name__ == "__main__":
main()

Python program won't respond until keyboard interrupt

I'm trying to draw an image with PyGame, and I copied this code from Adafruit. It's strange, seems nothing displays on the screen until I Ctrl-C, at which time it shows the image. Then the image stays on the screen until I press Ctrl-C again. I then get the following message:
Traceback (most recent call last):
File "RaspiDisplay.py", line 60, in
time.sleep(10)
KeyboardInterrupt
What's going on? By the way, I'm running this via ssh on a raspberry pi, with Display set to 0 (my TV) If I put a print statement in init, that also doesn't print until I press Ctrl-C.
import os
import pygame
import time
import random
class pyscope :
screen = None;
def __init__(self):
"Ininitializes a new pygame screen using the framebuffer"
# Based on "Python GUI in Linux frame buffer"
# http://www.karoltomala.com/blog/?p=679
disp_no = os.getenv("DISPLAY")
if disp_no:
print "I'm running under X display = {0}".format(disp_no)
# Check which frame buffer drivers are available
# Start with fbcon since directfb hangs with composite output
drivers = ['fbcon', 'directfb', 'svgalib']
found = False
for driver in drivers:
# Make sure that SDL_VIDEODRIVER is set
if not os.getenv('SDL_VIDEODRIVER'):
os.putenv('SDL_VIDEODRIVER', driver)
try:
pygame.display.init()
except pygame.error:
print 'Driver: {0} failed.'.format(driver)
continue
found = True
break
if not found:
raise Exception('No suitable video driver found!')
size = (pygame.display.Info().current_w, pygame.display.Info().current_h)
print "Framebuffer size: %d x %d" % (size[0], size[1])
self.screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
# Clear the screen to start
self.screen.fill((0, 0, 0))
# Initialise font support
pygame.font.init()
# Render the screen
pygame.display.update()
def __del__(self):
"Destructor to make sure pygame shuts down, etc."
def test(self):
# Fill the screen with red (255, 0, 0)
red = (255, 0, 0)
self.screen.fill(red)
# Update the display
pygame.display.update()
# Create an instance of the PyScope class
scope = pyscope()
scope.test()
time.sleep(10)
You're not running an event loop anywhere. Instead, you're just initializing everything, and then going to sleep for 10 seconds. During that 10 seconds, your code is doing nothing, because that's what you told it to do. That means no updating the screen, responding to mouse clicks, or anything else.
There are a few different ways to drive pygame, but the simplest is something like this:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
# any other event handling you need
# all the idle-time stuff you want to do each frame
# usually ending with pygame.display.update() or .flip()
See the tutorial for more information.
As a side note, your initialization code has a bunch of problems. You iterate through three drivers, but you only set SDL_VIDEODRIVER once, so you're just trying 'fbcon' three times in a row. Also, you've got code to detect the X display, but you don't allow pygame/SDL to use X, so… whatever you were trying to do there, you're not doing it. Finally, you don't need a found flag in Python for loops; just use an else clause.

disable or lock mouse and keyboard in Python?

Is there a way of disabling or locking mouse and keyboard using python? I want to freeze the mouse and disable the keyboard.
I haven't tested (actually I've tested the mouse part, and it annoyingly works) but something like this using pyhook would do what you want:
import pythoncom, pyHook
def uMad(event):
return False
hm = pyHook.HookManager()
hm.MouseAll = uMad
hm.KeyAll = uMad
hm.HookMouse()
hm.HookKeyboard()
pythoncom.PumpMessages()
I have extended Fábio Diniz's answer to a class which provides both a block() and an unblock() function which block (selectively) mouse/keyboard inputs. I also added a timeout functionality which (hopefully) addresses the annoyance of locking oneself out.
import pyHook
from threading import Timer
import win32gui
import logging
class blockInput():
def OnKeyboardEvent(self,event):
return False
def OnMouseEvent(self,event):
return False
def unblock(self):
logging.info(" -- Unblock!")
if self.t.is_alive():
self.t.cancel()
try: self.hm.UnhookKeyboard()
except: pass
try: self.hm.UnhookMouse()
except: pass
def block(self, timeout = 10, keyboard = True, mouse = True):
self.t = Timer(timeout, self.unblock)
self.t.start()
logging.info(" -- Block!")
if mouse:
self.hm.MouseAll = self.OnMouseEvent
self.hm.HookMouse()
if keyboard:
self.hm.KeyAll = self.OnKeyboardEvent
self.hm.HookKeyboard()
win32gui.PumpWaitingMessages()
def __init__(self):
self.hm = pyHook.HookManager()
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
block = blockInput()
block.block()
import time
t0 = time.time()
while time.time() - t0 < 10:
time.sleep(1)
print(time.time() - t0)
block.unblock()
logging.info("Done.")
You can have a look at the main routine for example usage.
For me, just two lines of programming solved the problem:
from ctypes import *
ok = windll.user32.BlockInput(True) #enable block
#or
ok = windll.user32.BlockInput(False) #disable block
Totally different take since all the solutions mentioned above use a quiet outdated library(pyhook) and this pyhook method personally didnt work for me.
import keyboard
from pynput.mouse import Controller
from time import sleep
def blockinput():
global block_input_flag
block_input_flag = 1
t1 = threading.Thread(target=blockinput_start)
t1.start()
print("[SUCCESS] Input blocked!")
def unblockinput():
blockinput_stop()
print("[SUCCESS] Input unblocked!")
def blockinput_start():
mouse = Controller()
global block_input_flag
for i in range(150):
keyboard.block_key(i)
while block_input_flag == 1:
mouse.position = (0, 0)
def blockinput_stop():
global block_input_flag
for i in range(150):
keyboard.unblock_key(i)
block_input_flag = 0
blockinput()
print("now blocking")
sleep(5)
print("now unblocking")
I just slightly modified the #Robert code and instead of the time I used external interrupt to close the program i.e. if you connect any external drive then the program gets close and your mouse and keyboard will be working perfectly.
import pyHook
from threading import Timer
import win32gui
import logging
import win32file
def locate_usb():#this will check any external Drives
drive_list = []
drivebits = win32file.GetLogicalDrives()
# print(drivebits)
for d in range(1, 26):
mask = 1 << d
if drivebits & mask:
# here if the drive is at least there
drname = '%c:\\' % chr(ord('A') + d)
t = win32file.GetDriveType(drname)
if t == win32file.DRIVE_REMOVABLE:
drive_list.append(drname)
return drive_list
class blockInput():
def OnKeyboardEvent(self,event):
return False
def OnMouseEvent(self,event):
return False
def unblock(self):
try: self.hm.UnhookKeyboard()
except: pass
try: self.hm.UnhookMouse()
except: pass
def block(self ,keyboard = True, mouse = True):
while(1):
if mouse:
self.hm.MouseAll = self.OnMouseEvent
self.hm.HookMouse()
if keyboard:
self.hm.KeyAll = self.OnKeyboardEvent
self.hm.HookKeyboard()
win32gui.PumpWaitingMessages()
cg= locate_usb()
if cg:
break
def __init__(self):
self.hm = pyHook.HookManager()
if __name__ == '__main__':
block = blockInput()
block.block()
block.unblock()
I hope this code will help you
Since 2018, you can now use pynput (v1.4+) to suppress keyboard and mouse events on Windows, Mac, and Linux.
import pynput
# Disable mouse and keyboard events
mouse_listener = pynput.mouse.Listener(suppress=True)
mouse_listener.start()
keyboard_listener = pynput.keyboard.Listener(suppress=True)
keyboard_listener.start()
# Enable mouse and keyboard events
mouse_listener.stop()
keyboard_listener.stop()
This also disables mouse scrolling and clicking.
However, this does not stop users from pressing Ctrl+Alt+Del on Windows. But you can run the script in an elevated command prompt, and the mouse and keyboard will still be disabled, even if they opened Task Manager using Ctrl+Alt+Delete, so there is no harm done (apparently there are way to actually prevent Ctrl+Alt+Delete, but do your own research for that)
You can use pyautogui to do this. Though I recommend adding keyboard for making a stopping key. First, you want to install pyautogui and keyboard.
Please note: this only disables the mouse not the keyboard, that is a very bad idea.
pip install pyautogui
pip install keyboard
Ok, with that sorted, we have to actually make the disabler.
import pyautogui
import keyboard
stopKey = "s" #The stopKey is the button to press to stop. you can also do a shortcut like ctrl+s
maxX, maxY = pyautogui.size() #get max size of screen
While True:
if keyboard.is_pressed(stopKey):
break
else:
pyautogui.moveTo(maxX/2, maxY/2) #move the mouse to the center of the screen
Ok, but there is 2 ways to get out of this. pressing S, and also quickly moving the mouse to one of the corners of the screen (that is a pyautogui failsafe, but we can disable that). If you want to disable the failsafe, add this after the imports:
pyautogui.FAILSAFE = False
Please note that disabling the failsafe is NOT recommended!
Ok, so now the only way to exit is the S key. If you want to stop this somewhere else in your program, do this:
pyautogui.press(stopKey)
Ok, so its not perfect, but it will stop you from doing basically anything with your mouse.

pygame freezes when I try to exit it after running it from IDLE!

I'm running it through the livewires wrapper which is just training wheels for pygame and other python modules in general; but everytime I run it, it'll execute and when I try to exit, it will not respond and then crash.
Any input on how I could go about fixing this would be great. There isn't any input in my textbook and all google seems to yield are results to this problem using pygame itself.
Apparently pygame and Tkinter seem to conflict?
Thanks in advance!
Addendum - This is the code I was trying to run:
from livewires import games
screen_w = 640
screen_h = 480
my_screen = games.Screen (wid, heit)
my_screen.mainloop()
Similar question: Pygame screen freezes when I close it
There isn't any input in my textbook
and all google seems to yield are
results to this problem using pygame
itself.
Those results probably address the same problem you're having. This is the relevant part of the games.py file from livewires, and nowhere does it call pygame.quit():
def handle_events (self):
"""
If you override this method in a subclass of the Screen
class, you can specify how to handle different kinds of
events. However you must handle the quit condition!
"""
events = pygame.event.get ()
for event in events:
if event.type == QUIT:
self.quit ()
elif event.type == KEYDOWN:
self.keypress (event.key)
elif event.type == MOUSEBUTTONUP:
self.mouse_up (event.pos, event.button-1)
elif event.type == MOUSEBUTTONDOWN:
self.mouse_down (event.pos, event.button-1)
def quit (self):
"""
Calling this method will stop the main loop from running and
make the graphics window disappear.
"""
self._exit = 1
def mainloop (self, fps = 50):
"""
Run the pygame main loop. This will animate the objects on the
screen and call their tick methods every tick.
fps -- target frame rate
"""
self._exit = 0
while not self._exit:
self._wait_frame (fps)
for object in self._objects:
if not object._static:
object._erase ()
object._dirty = 1
# Take a copy of the _objects list as it may get changed in place.
for object in self._objects [:]:
if object._tickable: object._tick ()
self.tick ()
if Screen.got_statics:
for object in self._objects:
if not object._static:
for o in object.overlapping_objects ():
if o._static and not o._dirty:
o._erase ()
o._dirty = 1
for object in self._objects:
if object._dirty:
object._draw ()
object._dirty = 0
self._update_display()
self.handle_events()
# Throw away any pending events.
pygame.event.get()
The QUIT event just sets a flag which drops you out of the while loop in the mainloop function. I'm guessing that if you find this file in your Python directory and stick a pygame.quit() after the last line in mainloop, it will solve your problem.
I agree. you need to put the whole program (the part to be executed, not the definitions and such) into a while loop.The problem is that pygame is not told to close when exited in IDLE, but outside of IDLE the closure of the program overrides the need to close pygame.
here is the loop:
done = False
while done==False:
# ALL EVENT PROCESSING SHOULD GO BELOW THIS COMMENT
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done=True # Flag that we are done so we exit this loop
#Main program here
pygame.quit()

Categories

Resources