I have following code which use infinite loop to check if active window has changed.This program prints the name of current window when active window changes. There must be better way to do this. how can a keep my python code always listening to active window change without infinite loop?
import subprocess
import psutil
pid = subprocess.check_output(["xdotool", "getactivewindow", "getwindowpid"]).decode("utf-8").strip()
prevpid=pid
print(pid)
while(True):
pid = subprocess.check_output(["xdotool", "getactivewindow", "getwindowpid"]).decode("utf-8").strip()
if prevpid!=pid:
process=psutil.Process(int(pid))
processName=process.name()
print("Current Active Process is "+processName)
prevpid=pid
If you are on X, instead of polling, it is much better to use the Wnck.Screen's active_window_changed signal, running from a Gtk loop. In a simple example:
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Wnck', '3.0')
from gi.repository import Gtk, Wnck
def dosomething(screen, previous_window):
try:
print(
previous_window.get_name(), "||",
screen.get_active_window().get_name()
)
# or run any action
except AttributeError:
pass
wnck_scr = Wnck.Screen.get_default()
wnck_scr.force_update()
wnck_scr.connect("active-window-changed", dosomething)
Gtk.main()
Related
I want to create a program in Python that allows to edit text that moves and show on top of a video. I want to do that in a website overlay (WPEWebKit).
I have found some code to start a pipeline with wpe and gst-launch-1.0, problem is that when I run gst-launch-1.0 -v wpesrc location="https://gstreamer.freedesktop.org" ! queue ! glimagesink from https://gstreamer.freedesktop.org/documentation/wpe/wpesrc.html it says WARNING: erroneous pipeline: no element "wpesrc". I have checked and I have installed gstreamer1.0-plugins-bad.
The other challange is that I want to create it in a python application. Here's my code so far:
import threading
import time
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst, GLib
Gst.init()
main_loop = GLib.MainLoop()
thread = threading.Thread(target=main_loop.run)
thread.start()
pipeline = Gst.parse_launch("videotestsrc ! decodebin ! videoconvert ! autovideosink")
pipeline.set_state(Gst.State.PLAYING)
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
pass
pipeline.set_state(Gst.State.NULL)
main_loop.quit()
I will be probably rewrite this because I want it in a GTK application.
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
DBusGMainLoop(set_as_default=True)
dbus_loop = DBusGMainLoop()
loop = GLib.MainLoop()
bus2 = dbus.SystemBus(mainloop=dbus_loop)
bus2_object = bus2.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
def handler():
print("Received")
bus2.add_signal_receiver(handler, "idle", 'org.freedesktop.DBus', None, '/org/freedesktop/DBus')
loop.run()
I tried going through several examples this is a small demo program I created to show what I am trying out currently but I get same error in all of them.
RuntimeError: To make asynchronous calls, receive signals or export objects, D-Bus connections must be attached to a main loop by passing mainloop=... to the constructor or calling dbus.set_default_main_loop(...)
I have 2 pieces of code that works fine up until now. Code A (FileRecord) creates a pipeline and writes whatever it hears from mic to an .ogg file named file.ogg. Code B (FilePlayer) must start after the user stops manual (Ctrl + C) the execution of script A and plays in pulsesink (user's headset) whatever recorder recorded during execution(file.ogg).
My goal is to make the 2 pieces of code work simultaneously and playing file from code B while code A records.
Code A (FileRecord)
from time import sleep
import gi
gi.require_version("Gst","1.0")
from gi.repository import Gst
from gi.repository import GLib
import signal
signal.signal(signal.SIGTSTP, signal.SIG_IGN) #When Ctrl + Z is pressed file is not playable (this command ignores Ctrl + Z)
print("In order to stop press: Ctrl C.")
Gst.init()
main_loop = GLib.MainLoop()
main_loop_thread = Thread(target = main_loop.run)
main_loop_thread.start()
#buffer = gst_buffer_new ()
pipeline = Gst.parse_launch('autoaudiosrc ! audioconvert ! tee name="source" ! queue ! vorbisenc ! oggmux ! filesink location=file.ogg')
pipeline.set_state(Gst.State.PLAYING)
try:
while True:
sleep(0.1)
except KeyboardInterrupt:
pass
pipeline.set_state(Gst.State.NULL)
main_loop.quit()
main_loop_thread.join()
Code B (FilePlayer)
from time import sleep
import gi
gi.require_version("Gst","1.0")
from gi.repository import Gst
from gi.repository import GLib
import signal
Gst.init()
main_loop = GLib.MainLoop()
main_loop_thread = Thread(target = main_loop.run)
main_loop_thread.start()
pipeline = Gst.parse_launch('filesrc location=file.ogg ! decodebin ! pulsesink')
pipeline.set_state(Gst.State.PLAYING)
try:
while True:
sleep(0.1)
except KeyboardInterrupt:
pass
pipeline.set_state(Gst.State.NULL)
main_loop.quit()
main_loop_thread.join()
I don't know how to achieve sound stream. Please help me!
I have one module which uses python "threading" for concurrency, and "signal" for shutdown hook:
signal.signal(signal.SIGINT, self.shutdownhook)
I have another module which uses dbus and gobject
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
....
GObject.threads_init()
mainloop = GObject.MainLoop()
mainloop.run()
When I run them seperately, they both operate as expected and ctrl+c causes termination via "KeyboardInterrupt".
However, when I run them together the mainloop terminates but the shutdown hook is never called - the process does not terminate without kill -9 pid.
Can someone please explain why this occurs, and how best to integrate the two models
Here is a working example which highlights my problem. I cannot exit the program with just a CTRL+C and the shutdown hook is not called in this case either.
import threading
import signal
import sys
from gi.repository import GObject
def runMainloop():
print('running mainloop')
mainloop.run()
def shutdown():
print('shutdown')
def readInput():
print('readInput')
print(sys.stdin.readline())
if __name__ == '__main__':
signal.signal(signal.SIGINT, shutdown)
signal.signal(signal.SIGTERM, shutdown)
GObject.threads_init()
mainloop = GObject.MainLoop()
mainloopThread = threading.Thread(name='mainloop', target=runMainloop)
mainloopThread.setDaemon(True)
mainloopThread.start()
print('started')
inputThread = threading.Thread(name='input', target=readInput)
inputThread.start()
print('started input')
No one is interested, so let me try.
Just to be on the same page:
import signal
from gi.repository import GObject
GObject.threads_init()
mainloop = GObject.MainLoop()
signal.signal(signal.SIGINT, lambda n, f: mainloop.quit())
mainloop.run()
This code works:
import signal
from gi.repository import GObject
signal.signal(signal.SIGINT, lambda n, f: print("kill"))
GObject.threads_init()
mainloop = GObject.MainLoop()
mainloop.run()
I've first registered signal handler, and then initiated the loop. Strange is that it is not called. However result is - as expected...
As a side note - according to their doc... mainloop is deprecated. That is first thing.
Edit
Here is example with reading from stdin inside MainLoop:
import signal
import sys
from gi.repository import GObject, GLib
GObject.threads_init()
def readInput():
print('readInput\n')
while True:
input = sys.stdin.readline()
print(input)
if input.strip() == 'exit':
print('closing main loop')
mainloop.quit()
print('terminating thread')
return
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal.SIG_DFL)
mainloop = GObject.MainLoop.new(None, False)
GObject.timeout_add(1000, readInput)
# inputThread = threading.Thread(name='input', target=readInput)
# inputThread.start()
# print('started input')
print('running mainloop\n')
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
Adding .new(None, False) allows CTRL-C working normally. Took it from here, also here is another thread about integrating pulse audio controller with GLib/GObject loop. There are samples about integration dbus with the loop, but I'm not sure which way you wish to go...
Adding a timer makes the loop receive Unix signals.
import gi
from gi.repository import GLib
import signal
GLib.threads_init()
mainloop = GLib.MainLoop()
signal.signal(signal.SIGTERM, lambda signum, frame: mainloop.quit())
GLib.timeout_add(1000, lambda *args: (print("tick") or True))
try:
mainloop.run()
except KeyboardInterrupt:
print()
What I'm trying to do is to write a script which would open an application only in process list. Meaning it would be "hidden". I don't even know if its possible in python.
If its not possible, I would settle for even a function that would allow for a program to be opened with python in a minimized state maybe something like this:
import subprocess
def startProgram():
subprocess.Hide(subprocess.Popen('C:\test.exe')) # I know this is wrong but you get the idea...
startProgram()
Someone suggested to use win32com.client but the thing is that the program that i want to launch doesn't have a COM server registered under the name.
Any ideas?
It's easy :)
Python Popen Accept STARTUPINFO Structure...
About STARTUPINFO Structure: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx
Run Hidden:
import subprocess
def startProgram():
SW_HIDE = 0
info = subprocess.STARTUPINFO()
info.dwFlags = subprocess.STARTF_USESHOWWINDOW
info.wShowWindow = SW_HIDE
subprocess.Popen(r'C:\test.exe', startupinfo=info)
startProgram()
Run Minimized:
import subprocess
def startProgram():
SW_MINIMIZE = 6
info = subprocess.STARTUPINFO()
info.dwFlags = subprocess.STARTF_USESHOWWINDOW
info.wShowWindow = SW_MINIMIZE
subprocess.Popen(r'C:\test.exe', startupinfo=info)
startProgram()
You should use win32api and hide your window e.g. using win32gui.EnumWindows you can enumerate all top windows and hide your window
Here is a small example, you may do something like this:
import subprocess
import win32gui
import time
proc = subprocess.Popen(["notepad.exe"])
# lets wait a bit to app to start
time.sleep(3)
def enumWindowFunc(hwnd, windowList):
""" win32gui.EnumWindows() callback """
text = win32gui.GetWindowText(hwnd)
className = win32gui.GetClassName(hwnd)
#print hwnd, text, className
if text.find("Notepad") >= 0:
windowList.append((hwnd, text, className))
myWindows = []
# enumerate thru all top windows and get windows which are ours
win32gui.EnumWindows(enumWindowFunc, myWindows)
# now hide my windows, we can actually check process info from GetWindowThreadProcessId
# http://msdn.microsoft.com/en-us/library/ms633522(VS.85).aspx
for hwnd, text, className in myWindows:
win32gui.ShowWindow(hwnd, False)
# as our notepad is now hidden
# you will have to kill notepad in taskmanager to get past next line
proc.wait()
print "finished."
What is the purpose?
if you want a hidden(no window) process working in background, best way would be to write a windows service and start/stop it using usual window service mechanism. Windows service can be easily written in python e.g. here is part of my own service (it will not run without some modifications)
import os
import time
import traceback
import pythoncom
import win32serviceutil
import win32service
import win32event
import servicemanager
import jagteraho
class JagteRahoService (win32serviceutil.ServiceFramework):
_svc_name_ = "JagteRaho"
_svc_display_name_ = "JagteRaho (KeepAlive) Service"
_svc_description_ = "Used for keeping important services e.g. broadband connection up"
def __init__(self,args):
win32serviceutil.ServiceFramework.__init__(self,args)
self.stop = False
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
self.log('stopping')
self.stop = True
def log(self, msg):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_,msg))
def SvcDoRun(self):
self.log('folder %s'%os.getcwd())
self.ReportServiceStatus(win32service.SERVICE_RUNNING)
self.start()
def shouldStop(self):
return self.stop
def start(self):
try:
configFile = os.path.join(jagteraho.getAppFolder(), "jagteraho.cfg")
jagteraho.start_config(configFile, self.shouldStop)
except Exception,e:
self.log(" stopped due to eror %s [%s]" % (e, traceback.format_exc()))
self.ReportServiceStatus(win32service.SERVICE_STOPPED)
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(AppServerSvc)
and you can install it by
python svc_jagteraho.py--startup auto install
and run it by
python python svc_jagteraho.py start
I will be also be seen in services list e.g. services.msc will show it and you can start/stop it else you can use commandline
sc stop jagteraho
Run Hidden:
from subprocess_maximize import Popen
Popen("notepad.exe",show='hidden', priority=0)
Before the code above, use the following command:
pip install subprocess-maximize
If what is appearing is a terminal, redirect the process's stdout.