mirror of
https://github.com/LazoCoder/Pokemon-Terminal
synced 2025-02-17 05:18:31 +00:00
Cleanup and reorganize platform specific stuff, use unlink for close on POSIX, fix ConEmu adapter
This commit is contained in:
parent
b562a5c89a
commit
87a9e449cb
8 changed files with 143 additions and 123 deletions
|
@ -11,7 +11,7 @@ from . import scripter, slideshow
|
||||||
from pokemonterminal.command_flags import parser, is_slideshow
|
from pokemonterminal.command_flags import parser, is_slideshow
|
||||||
from pokemonterminal.database import Database
|
from pokemonterminal.database import Database
|
||||||
from pokemonterminal.filters import Filter
|
from pokemonterminal.filters import Filter
|
||||||
from pokemonterminal.platform.named_event import create_named_event
|
from pokemonterminal.platform import PlatformNamedEvent
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,40 +69,39 @@ def main(argv=None):
|
||||||
print("Dry run, exiting.")
|
print("Dry run, exiting.")
|
||||||
return
|
return
|
||||||
|
|
||||||
e = create_named_event("Pokemon-Terminal_Wallpaper" if options.wallpaper else "Pokemon-Terminal_Terminal")
|
event_name = "Pokemon-Terminal_Wallpaper" if options.wallpaper else "Pokemon-Terminal_Terminal"
|
||||||
try:
|
event_exists = PlatformNamedEvent.exists(event_name)
|
||||||
if options.clear:
|
|
||||||
if e.is_duplicate():
|
|
||||||
e.set()
|
|
||||||
scripter.clear_terminal()
|
|
||||||
return
|
|
||||||
|
|
||||||
if is_slideshow and options.id <= 0 and size > 1:
|
if options.clear:
|
||||||
if e.is_duplicate():
|
if event_exists:
|
||||||
print("One or more slideshows is already running.\n")
|
slideshow.stop(event_name)
|
||||||
while True:
|
if not options.wallpaper:
|
||||||
print("[S]top the previous slideshow(s) / ", end='')
|
scripter.clear_terminal()
|
||||||
if not options.wallpaper:
|
return
|
||||||
print("[I]gnore and continue / ", end='')
|
|
||||||
print("[A]bort")
|
if is_slideshow and options.id <= 0 and size > 1:
|
||||||
inp = input("Pick one: ").lower() # FIXME weird bug: inputting s here doesn't actually close the older process but "pokemon -c" does
|
if event_exists:
|
||||||
if inp == 's':
|
print("One or more slideshows is already running.\n")
|
||||||
e.set()
|
while True:
|
||||||
break
|
print("[S]top the previous slideshow(s) / ", end='')
|
||||||
elif inp == 'i' and not options.wallpaper:
|
if not options.wallpaper:
|
||||||
break
|
print("[I]gnore and continue / ", end='')
|
||||||
elif inp == 'a':
|
print("[A]bort")
|
||||||
return
|
inp = input("Pick one: ").lower()
|
||||||
else:
|
if inp == 's':
|
||||||
print("Not a valid option!\n")
|
slideshow.stop(event_name)
|
||||||
if options.slideshow <= 0:
|
break
|
||||||
print("Time has to be greater then 0. You can use decimal values.")
|
elif inp == 'i' and not options.wallpaper:
|
||||||
return
|
break
|
||||||
e.clear()
|
elif inp == 'a':
|
||||||
target_func = scripter.change_wallpaper if options.wallpaper else scripter.change_terminal
|
return
|
||||||
slideshow.start(Filter.filtered_list, options.slideshow, target_func, e.name())
|
else:
|
||||||
finally:
|
print("Not a valid option!\n")
|
||||||
e.close()
|
if options.slideshow <= 0:
|
||||||
|
print("Time has to be greater then 0. You can use decimal values.")
|
||||||
|
return
|
||||||
|
target_func = scripter.change_wallpaper if options.wallpaper else scripter.change_terminal
|
||||||
|
slideshow.start(Filter.filtered_list, options.slideshow, target_func, event_name)
|
||||||
|
|
||||||
if options.wallpaper:
|
if options.wallpaper:
|
||||||
scripter.change_wallpaper(target.get_path())
|
scripter.change_wallpaper(target.get_path())
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
from .named_event.win import WindowsNamedEvent as platform_event
|
||||||
|
else:
|
||||||
|
from .named_event.posix import PosixNamedEvent as platform_event
|
||||||
|
|
||||||
|
PlatformNamedEvent = platform_event
|
|
@ -1,11 +1,67 @@
|
||||||
import sys
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
from .adapters import NamedEvent
|
class NamedEvent(ABC):
|
||||||
|
"""
|
||||||
|
Interface representing an operating system event object with a name.
|
||||||
|
"""
|
||||||
|
|
||||||
def create_named_event(name: str) -> NamedEvent:
|
@staticmethod
|
||||||
if sys.platform == 'win32':
|
@abstractmethod
|
||||||
from .adapters.win import WindowsNamedEvent
|
def exists(name: str) -> bool:
|
||||||
return WindowsNamedEvent(name)
|
"""
|
||||||
else:
|
check if event exists
|
||||||
from .adapters.posix import PosixNamedEvent
|
does not returns event, use the constructor for that.
|
||||||
return PosixNamedEvent(name)
|
:return a boolean indicating wether the event exists.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def is_set(self) -> bool:
|
||||||
|
"""
|
||||||
|
check if event set
|
||||||
|
:return a boolean indicating wether the event has been set.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def set(self):
|
||||||
|
"""
|
||||||
|
sets the event
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def clear(self):
|
||||||
|
"""
|
||||||
|
resets the event
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def wait(self, timeout=None):
|
||||||
|
"""
|
||||||
|
block until event is set
|
||||||
|
:param timeout Optional timeout for wait in seconds.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def name(self) -> str:
|
||||||
|
"""
|
||||||
|
gets the name set at creation of the event
|
||||||
|
:return Name of the event
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def close(self):
|
||||||
|
"""
|
||||||
|
release native resources
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
|
self.close()
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
class NamedEvent(ABC):
|
|
||||||
"""
|
|
||||||
Interface representing an operating system event object with a name.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def is_set(self) -> bool:
|
|
||||||
"""
|
|
||||||
check if event set
|
|
||||||
:return a boolean indicating wether the event has been set.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def set(self):
|
|
||||||
"""
|
|
||||||
sets the event
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def clear(self):
|
|
||||||
"""
|
|
||||||
resets the event
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def wait(self, timeout=None):
|
|
||||||
"""
|
|
||||||
block until event is set
|
|
||||||
:param timeout Optional timeout for wait in seconds.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def is_duplicate(self) -> bool:
|
|
||||||
"""
|
|
||||||
determines if the event was created or opened as a result of creating this class
|
|
||||||
:return True if it was opened. False if it was created.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def name(self) -> str:
|
|
||||||
"""
|
|
||||||
gets the name set at creation of the event
|
|
||||||
:return Name of the event
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def close(self):
|
|
||||||
"""
|
|
||||||
release native resources
|
|
||||||
"""
|
|
||||||
pass
|
|
|
@ -7,14 +7,19 @@ class PosixNamedEvent(NamedEvent):
|
||||||
A wrapper for named events using a named semaphore
|
A wrapper for named events using a named semaphore
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def exists(name: str) -> bool:
|
||||||
semaphore_name = '/' + name
|
semaphore_name = '/' + name
|
||||||
try:
|
try:
|
||||||
self.__semaphore = posix_ipc.Semaphore(semaphore_name, flags=posix_ipc.O_CREX)
|
semaphore = posix_ipc.Semaphore(semaphore_name)
|
||||||
self.__duplicate = False
|
semaphore.close()
|
||||||
|
return True
|
||||||
except posix_ipc.ExistentialError: # Semaphores are reconsidering their life choices
|
except posix_ipc.ExistentialError: # Semaphores are reconsidering their life choices
|
||||||
self.__semaphore = posix_ipc.Semaphore(semaphore_name)
|
return False
|
||||||
self.__duplicate = True
|
|
||||||
|
|
||||||
|
def __init__(self, name: str):
|
||||||
|
semaphore_name = '/' + name
|
||||||
|
self.__semaphore = posix_ipc.Semaphore(semaphore_name, flags=posix_ipc.O_CREAT)
|
||||||
|
|
||||||
# NOTE this doesn't works on macOS, see http://semanchuk.com/philip/posix_ipc/#platforms
|
# NOTE this doesn't works on macOS, see http://semanchuk.com/philip/posix_ipc/#platforms
|
||||||
def is_set(self) -> bool:
|
def is_set(self) -> bool:
|
||||||
|
@ -37,11 +42,9 @@ class PosixNamedEvent(NamedEvent):
|
||||||
except posix_ipc.BusyError:
|
except posix_ipc.BusyError:
|
||||||
return
|
return
|
||||||
|
|
||||||
def is_duplicate(self) -> bool:
|
|
||||||
return self.__duplicate
|
|
||||||
|
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return self.__semaphore.name
|
return self.__semaphore.name
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.__semaphore.close()
|
# FIXME do we also need to close it here?
|
||||||
|
self.__semaphore.unlink()
|
|
@ -7,21 +7,36 @@ class WindowsNamedEvent(NamedEvent):
|
||||||
Named events using the native Windows APIs
|
Named events using the native Windows APIs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
__SYNCHRONIZE = 0x00100000
|
||||||
|
__EVENT_MODIFY_STATE = 2
|
||||||
|
|
||||||
__WAIT_OBJECT_0 = 0
|
__WAIT_OBJECT_0 = 0
|
||||||
__WAIT_FAILED = 0xFFFFFFFF
|
__WAIT_FAILED = 0xFFFFFFFF
|
||||||
|
|
||||||
__ERROR_ALREADY_EXISTS = 183
|
__ERROR_FILE_NOT_FOUND = 2
|
||||||
|
|
||||||
def __raise_last_error():
|
def __raise_last_error():
|
||||||
err_no = ctypes.GetLastError()
|
err_no = ctypes.GetLastError()
|
||||||
raise WindowsError(err_no, ctypes.FormatError(err_no))
|
raise WindowsError(err_no, ctypes.FormatError(err_no))
|
||||||
|
|
||||||
|
def exists(name: str) -> bool:
|
||||||
|
event = ctypes.windll.kernel32.OpenEventW(WindowsNamedEvent.__SYNCHRONIZE | WindowsNamedEvent.__EVENT_MODIFY_STATE, False, name)
|
||||||
|
if event == 0:
|
||||||
|
if ctypes.GetLastError() == WindowsNamedEvent.__ERROR_FILE_NOT_FOUND:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
WindowsNamedEvent.__raise_last_error()
|
||||||
|
else:
|
||||||
|
result = ctypes.windll.kernel32.CloseHandle(event)
|
||||||
|
if result == 0:
|
||||||
|
WindowsNamedEvent.__raise_last_error()
|
||||||
|
return True
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
event = ctypes.windll.kernel32.CreateEventW(ctypes.c_void_p(), True, False, name)
|
event = ctypes.windll.kernel32.CreateEventW(ctypes.c_void_p(), True, False, name)
|
||||||
if event == 0:
|
if event == 0:
|
||||||
WindowsNamedEvent.__raise_last_error()
|
WindowsNamedEvent.__raise_last_error()
|
||||||
|
|
||||||
self.__duplicate = ctypes.GetLastError() == WindowsNamedEvent.__ERROR_ALREADY_EXISTS
|
|
||||||
self.__event = event
|
self.__event = event
|
||||||
self.__name = name
|
self.__name = name
|
||||||
|
|
||||||
|
@ -47,9 +62,6 @@ class WindowsNamedEvent(NamedEvent):
|
||||||
if result == WindowsNamedEvent.__WAIT_FAILED:
|
if result == WindowsNamedEvent.__WAIT_FAILED:
|
||||||
WindowsNamedEvent.__raise_last_error()
|
WindowsNamedEvent.__raise_last_error()
|
||||||
|
|
||||||
def is_duplicate(self) -> bool:
|
|
||||||
return self.__duplicate
|
|
||||||
|
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return self.__name
|
return self.__name
|
||||||
|
|
|
@ -2,7 +2,7 @@ import atexit
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from .platform.named_event import create_named_event
|
from .platform import PlatformNamedEvent
|
||||||
|
|
||||||
def __print_fork(pid, length, delay):
|
def __print_fork(pid, length, delay):
|
||||||
print(f"Starting slideshow with {length} Pokemons and a delay of {delay} minutes.")
|
print(f"Starting slideshow with {length} Pokemons and a delay of {delay} minutes.")
|
||||||
|
@ -27,8 +27,7 @@ def __get_sleeper_and_listener(event):
|
||||||
return sleeper, listener
|
return sleeper, listener
|
||||||
|
|
||||||
def __slideshow_worker(filtered, delay, changer_func, event_name):
|
def __slideshow_worker(filtered, delay, changer_func, event_name):
|
||||||
e = create_named_event(event_name)
|
with PlatformNamedEvent(event_name) as e:
|
||||||
try:
|
|
||||||
sleeper, listener = __get_sleeper_and_listener(e)
|
sleeper, listener = __get_sleeper_and_listener(e)
|
||||||
random.shuffle(filtered)
|
random.shuffle(filtered)
|
||||||
queque = iter(filtered)
|
queque = iter(filtered)
|
||||||
|
@ -40,8 +39,6 @@ def __slideshow_worker(filtered, delay, changer_func, event_name):
|
||||||
continue
|
continue
|
||||||
changer_func(next_pkmn.get_path())
|
changer_func(next_pkmn.get_path())
|
||||||
sleeper(delay * 60)
|
sleeper(delay * 60)
|
||||||
finally:
|
|
||||||
e.close()
|
|
||||||
|
|
||||||
def start(filtered, delay, changer_func, event_name):
|
def start(filtered, delay, changer_func, event_name):
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
|
@ -59,3 +56,7 @@ def start(filtered, delay, changer_func, event_name):
|
||||||
__print_fork(pid, len(filtered), delay)
|
__print_fork(pid, len(filtered), delay)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
__slideshow_worker(filtered, delay, changer_func, event_name)
|
__slideshow_worker(filtered, delay, changer_func, event_name)
|
||||||
|
|
||||||
|
def stop(event_name):
|
||||||
|
with PlatformNamedEvent(event_name) as e:
|
||||||
|
e.set()
|
||||||
|
|
|
@ -11,7 +11,7 @@ class ConEmuProvider(_TProv):
|
||||||
return "CONEMUPID" in os.environ
|
return "CONEMUPID" in os.environ
|
||||||
|
|
||||||
def __run_command(command: str):
|
def __run_command(command: str):
|
||||||
output = subprocess.check_output(["ConEmuC", "-GuiMacro", command]).decode(sys.stdout.encoding)
|
output = subprocess.check_output(f"ConEmuC -GuiMacro {command}", shell=True).decode(sys.stdout.encoding)
|
||||||
if output != 'OK':
|
if output != 'OK':
|
||||||
print(output)
|
print(output)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue