I want to make a little command line music player based on the python module "mp3play".
I want to check regularly, if a song has stopped playing (and eventually start a new song), but the user should be able to type new commands during that time (like pausing the music).
Therefor i tried to use threading.Timer for that. However, it gives me an error if i am inside the function that was called using the timer. the error does not occur when the function was called normally. Heres my (reduced) code:
from threading import Timer
global currentmusic
def rep():
b = currentmusic.isplaying() #this is where the error occurs
if b:
print "Music is playing"
else:
print "Music has stopped"
t=Timer(5.0,rep) #repeat every 5 seconds
t.start()
currentmusic=playrandomfile() #loads a song and starts playing it
rep() #call the first time
When rep() is called the second time, it gives me an MCI error in the function isplaying(), saying that it cannot read the device. My questions:
Am i making a mistake with the way the threading.Timer works? (and how can i fix it?)
Is there another way than threading.Timer to achieve the stuff i want?
My thoughts so far were, that it could be a problem to access currentmusic from another thread, but i am not sure. Also i dont know how to avoid it.
Thx for helping
Ive used mp3play in some projects, and it works fine for me.
IMO recursion threading is the problem.
Just remove the threading timer and leave the rep function call, it wont lag any pc.
You should use threading only for raw_input.
Related
I am creating a game using Python and tkinter, and when I tried to add some music, the function making the music stopped the rest of the script (and also the window).
So I need to create a new thread I think to play the audio and keep the window working...
I tried some things making errors, not running, or stopping the window, I currently have :
window.after(2000,showText,"Text 1")
window.after(2000,playSound,"Sound 1.wav")
window.after(7000,showText,"Text 2")
Important detail : the playSound function returns nothing, so nothing needs to wait for it.
I also don't know much about programming in Python, I prefer using LUAU.
Try using the module threading. I found this article very useful for understanding the core concepts and setting up my first multithreaded program
I found another article telling exactly how to make it work and it now works.
The article is probably in french, but I give the link : http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_parallelisation/thread.html
I want to make a program stop running for a certain amount of time to save CPU power. I have a self.after function that I want to run to make the program stop running for a set amount of time. However, it always crashes the program.
self.after(int(self.timeSleep*1000),print("Sleeping."))
The word Sleeping. is printed but the window crashes. I thought that Sleeping. should only be printed after the "sleep" was done. I'm not sure what I'm doing wrong and I couldn't find another question like this. Forgive me if it's a stupid mistake as it's my first time using TKinter.
Thanks in advance.
EDIT:
I am not getting any errors in my terminal. By crash I mean the window stops responding.
Your code has the same effect as below:
execute print("Sleeping.")
execute self.after(int(self.timeSleep*1000), None) which is the same as time.sleep(int(self.timeSleep*1000)).
You need to change it to use lambda:
self.after(int(self.timeSleep*1000), lambda: print("Sleeping."))
I found a solution that doesn't require using self.after. Instead, you can use a thread to run this specific method, allowing you to use while loops and time.sleep without crashing the main GUI program.
I want a Maya camera orbiting a mesh while user chooses what to do with that mesh on my own script interface.
So i have a while orbiting the camera, but no way to interact with user interface while this happens.
There is anyway to "share", or part the focus in second's decims to be able to interact with user interface?
I tried with cmds.evaldeferred(), but no luck...
Technically, Maya widgets interface is immediately available when script finishes the job...
I'm trying to finish the job with one single camera little orbit, and relaunch it with mouse movement event... Time changing event... But no way how to do that... Would be like a daemon running in the background... No idea how I could reach something like that....
Some code:
import maya.cmds as cmds
#declares global variable
global orbitCam
#just something to see in the scene
cmds.polyCube()
#function to stop camera orbit
def stopOrbiting():
global orbitCam
orbitCam = False
#simplest ui
cmds.window("testWindow")
cmds.formlayout("flo", parent="testWindow")
#button that calls stopOrbit function
cmds.button("pushMeIfYouCan", parent="flo", label="pushMeIfYouCan", c="stopOrbiting()")
cmds.showWindow("testWindow")
#condition for the while
orbitCam=True
#while itself
while orbitCam:
cmds.orbit("persp", ra=(0.2,0.1))
Any way to be able to push the button -and interact with widgets- while camera orbits?
Well, based on solution provided by mhlester in the link I posted under the question (and considering a great answer too by theodox, as a wonderful alternative, thank you both, guys), I'm gonna aswer my own question and provide another new detailed explanation perhaps can help somebody in the future.
First of all, Maya's "scriptjob" command utility puts in memory a script (or a function), haves a trigger to start executing that function, and the condition to Maya to execute that function once registered and triggered, is that Maya must to be doing exactly nothing, so, Maya must be idle.
Being that way, Maya never collapses or crashes or hangs by a scriptJob. ScriptJob is basically a... kind of "daemon" working in the background.
The good thing, is that is possible to limit the maximum number of times per second, so you can even maintain your system fresh and working if you want to care it about.
Once a scriptJob is launched (or registered in Maya memory), it can be killed to never runs again, and obviously, can be registered again if we want to start working again.
Exists an internal scriptJobs list inside of Maya, where you can find the scriptjob if you have forgotten to store that scriptJob in a variable, where you can find the "scriptJob ID", just an integer number you can use to kill the job.
After the first theory, let's see some code now:
This line will register a new daemon (maya scriptjob), its reference will be stored in "activeDaemon" variable, it will call a function called "camDaemon" with some arguments:
activeDaemon = registerDaemon(0.04, BackgroundFunction, ArgumentsForBackgroundFunction)
The point here is not just launch the daemon with conditions, besides, to store the daemon id to be able to kill it with:
cmds.scriptJob(kill=activeDaemon)
If we forgotten to store the daemon (scriptjob) id, we can use this command to watch a list with all scriptJobs of Maya:
cmds.scriptJob(listJobs=True)
We would need to find the last ids in the list with the event "idle", and probably we could hit and finished stopping our daemon killing it.
Now let's see "registerDaemon" function (all the absolute credit for MhLester):
def registerDaemon(seconds, backgroundFunction, *args, **kwargs):
def updateNow():
now = time.time()
if now - updateNow.then > seconds:
updateNow.then = now
backgroundFunction(*args, **kwargs)
updateNow.then = time.time()
return cmds.scriptJob(event=("idle", updateNow))
registerDaemon defines an internal function (updateNow) that calls "automatically" at the backgroundFunction we pass as argument, including this "backgroundFunction" arguments. Just that. A function A that defines a function B that calls a function C. And it calls it every quantity of seconds we specify at register the daemon with the first argument, so if we want it executed 25 times per second, 1seg/25fps = 0.04 would be the right value.
To have this function working, we must import the module time in our script with:
import time
Finally it returns the scriptJob id at the same time it registers it in Maya memory, registering with the event "idle" and with the function (B) that calls the function (C) we really want executed in the background. This way we can control the temperatures of the machine not overwhelming the cpu unnecessary. Very complete last line, brilliant, at least, for me.
At this point no other thing left than just register the function we want to have running the background in the Maya memory (take the code you want in the background, put inside a function and execute it one time in Script Editor)
def backgroundFunction():
print "this message shows in idle time by a daemon (Maya scriptjob)"
Of course there are much more in the documentation (Maya scriptJob documentation), as a list of events or conditions, but the base is this.
When I use the function time.sleep() in the terminal, it is no problem.
When I use PyQt and want to use a label, it crashes and/or only shows the last number.
By the way: I want a function, that counts e.g. a year from 2020 to 2030 in various speed, that the user can change and the year should be shown in a label.
Thanks a lot for your help.
# timer that counts in the future with various speed // still crashing
def timer(self):
x=datetime.datetime.now()
z=x.ctime()
self.ui.labelDateTime.setText(z)
var=x.year
while True:
if var==2030:
break
else:
var+=1
y=x.replace(year=var)
z=y.ctime()
self.ui.labelDateTime.setText(z)
time.sleep(0.5)
print("You are dead")
You should call QtCore.QCoreApplication.processEvents() within your for loop to make the Qt's event loop proceed the incoming event (from keyboard or mouse or sleep).
Although calling QtCore.QCoreApplication.processEvents() works , I have read in many places on the web that it should be a last resort. Unfortunately none of the sources clearly explain why -- but see for example
How to make Qt work when main thread is busy?
Should I use QCoreApplication::processEvents() or QApplication::processEvents()?
How to implement a QThread that runs forever{} with a QWaitCondition but still needs to catch another Slot while doing that
http://qt-project.org/forums/viewthread/22967
So it does seem allowed, but in general, it seems to be better design to use QTimer or QThread.
I have some code:
l1 = clutter.Label()
l1.set_position(100,100)
for i in range(0,10):
l1.set_text(str(i))
time.sleep(1)
That is designed to show a count from 1 to 10 seconds on the screen in clutter, but I'm getting a strange error. When I run the script normally the screen runs as it should do, but there is no text displayed until 10 seconds are up. However, When I run with breakpoints in pdb the text shows up just fine.
I'm also getting a strange error at the start of the program:
do_wait: drmWaitVBlank returned -1, IRQs don't seem to be working correctly.
Try adjusting the vlank_mode configuration parameter.
But I don't see why that would affect the code out of break points but not in breakpoints.
Any help would be greatly appreciated.
Not sure if you've already figured out the answer to this but:
The reason you are having this problem is because you are blocking the main thread (where all the drawing occurs) with your time.sleep() calls, preventing the library from redrawing the screen.
E.g. your code is currently doing this:
Clutter redraws the screen.
You loop over ten seconds and change the text ten times.
Clutter redraws the screen.
If you want to queue something on a timer, you should look into gobject.timeout_add.
Have you tried posting (or searching) on the Clutter mailing list? Here's someone who got the same message about drmWaitVBlank for example.
My guess is most people on SO wouldn't be familiar with solving Clutter problems. I know I'm not :)