Locale problems in EventGhost.

If you have a question or need help, this is the place to be.
Post Reply
User avatar
kgschlosser
Site Admin
Posts: 5508
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Locale problems in EventGhost.

Post by kgschlosser » Thu Apr 02, 2020 8:26 am

OK folks so I have hit a road block. the author of wxWidgets is not going to fix the locale problems in wxWidgets, he states that it is working fine. Even tho in the last 10 years he has closed a slew of issues as invalid where the issue stems from the problem with how wxWidgets handles the locale.

I have spent some time writing a wrapper around the bits and pieces in wxPython/wxWidgets to see if I am able to get the damned thing to work correctly. I am still working on it actually. I do not know if it is going to work correctly. Whether it does or not we need to change the GUI framework. I really dislike it when a program author has that "god complex" and states "it's not happening to me so the problem is invalid" Even tho I walked him step by step through the issues with it. Explaining every single piece of it and why it is not working right, I still ended up getting no where with it.

If anyone has any suggestions or input on a framework or any other suggestions please feel free to comment. I am open to ideas at this point. This is going to be a royal pain in the ass to do because of the plugins and any help is going to be greatly appreciated.
If you like the work I have been doing then feel free to Image

User avatar
Sem;colon
Plugin Developer
Posts: 758
Joined: Sat Feb 18, 2012 10:51 am
Location: Germany

Re: Locale problems in EventGhost.

Post by Sem;colon » Thu Apr 02, 2020 9:11 am

That's a royal pain indeed! wx Python is so deeply integrated into eventghost and it's plugins.. I totally understand your frustration and yeah, it's pretty rude from that developer :evil: but changing the GUI framework would mean reprogramming Eventghost in it's core and especially for the hundreds of plugins I don't really see a chance to do it without spending far too much effort :?
*Edit* unless there is another framework that's compatible with the wx syntax.
Can't we just apply some sort workaround?
I'm not familiar what exactly is interpreted incorrectly with the locals, but there should be a faster solution than changing the GUI framework.
For example some sort of mapping table that defaults to english if the locals are not in the list, something like that?
If you like my work, Image me a drink :wink:

User avatar
kgschlosser
Site Admin
Posts: 5508
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Locale problems in EventGhost.

Post by kgschlosser » Thu Apr 02, 2020 10:07 pm

I am working on the band-aide. but it still doesn't change the fact that it's going to be a band-aide. and what happens to all band-aids? they eventually fall off. It will buy some time, but there needs to be a plan put into place and we need to follow that plan.

The hardest thing is with any change like that is it's going to cause stability issues with EG until the bugs get worked out. This is the single largest reason There have been no HUGE changes to EG. Upgrading Python was an inconvenience and updating wxPython was an annoyance. I wouldn't call them HUGE changes. Not like changing out the framework. and wxPython is not as intertwined as you think. It is actually fairly simple to remove it from the code. EG can and does run form a command line without any GUI what's so ever. This is how I made EG able to be run as a service. The main message receiver needs to be changed so it creates a frame using the windows api instead of wx. This frame is invisible and is only there for the sole purpose of receiving windows notifications.

This is where it gets hard because if we change the framework should we also make the changes necessary to get EG to run as a service? It would almost be the best time to do it instead of back pedaling to do it after the frame work. I wish I had 5 people at my disposal that could work with me while doing this. I am a fairly smart person, but I cannot think of all possible ways to go about making a change of that magnitude, There needs to be several people that spend some time mapping out exactly what needs to be done and set a time table and also who is going to do what portion. any changes going forward needs to be done in a modular way.

I do not know how much of the EG code you have given a thorough look over.. This is an example of what I like to call "voodoo code"

when you click on the Configure menu option to configure an Action this is what takes place.

Event from wxPython for clicking on the menu option.
Utils.AsTasklet
Classes.Tasklet.Tasklet
Classes.MainFrame.MainFrame.OnCmdConfigure
Classes.Document.Document.CmdConfigure
Classes.UndoHandler.Configure
Classes.UndoHandler.Configure.Do
Classes.ActionThread.ActionThread.Func
Classes.ActionItem.ActionItem.GetArgumentString (Classes.TreeItem.TreeItem)
Classes.ActionThread.ActionThread.Func
Classes.ActionItem.ActionItem.GetArguments (Classes.TreeItem.TreeItem)
Classes.TaskletDialog.TaskletDialog.Create
Classes.ConfigDialog.ConfigDialog.__init__
Classes.Tasklet.Tasklet
Classes.TaskletDialog.TaskletDialog.ProcessingTask
Classes.ConfigDialog.ConfigDialog.Configure
Classes.ActionItem.ActionItem.Configure(Classes.TreeItem.TreeItem)
Classes.PluginBase.PluginBase.info
Classes.PluginInstanceInfo.PluginProxy.actions
Classes.PluginInstanceInfo.PluginInstanceInfo.actions
Classes.ActionBase.ActionBase.Configure
Classes.ConfigPanel.ConfigPanel.__init__


and that is to get just the dialog to open with not a damned thing in it.
almost feel like a ping pong ball. I just spent 30 minutes following that data path.
Changes moving forward should not be like this. everything required to do a task should be organized as such They should be module in nature. So if something gets unplugged and something new get plugged in as a replacement it should work without having to change anything else in the core.

each "module" would be given a single thread for it's operations to be performed using. calls to any other portion of EG would be done through the use of notifications. This way if an API breaking change gets made it can get handled easily because the notification would not change where it's pointed to might. but because the source of the notification has no clue what portion of the code in EG is handling the request it would make it far easier to make changes without having to worry about things getting broken.

It's ideas like this that would need to be reviewed and rejected, accepted or accepted with changes to the original idea.
A single person is not able to do this properly. LOL..
If you like the work I have been doing then feel free to Image

User avatar
Sem;colon
Plugin Developer
Posts: 758
Joined: Sat Feb 18, 2012 10:51 am
Location: Germany

Re: Locale problems in EventGhost.

Post by Sem;colon » Fri Apr 03, 2020 8:25 am

I agree with everything you wrote Kevin!

And yes, when we get our hands dirty with changing the GUI framework, we should also seperate the GUI from the rest of the code to be able to run EG as a service and for doing changes more easily in the future. While we're at it, I'd suggest to also change the event processing from serial to parallel in the same go.

However, as it's programmed right now, the UI is not seperated from the rest of the code, that's why I said you need to touch everything..
And that's what makes this change so damn complex! As you said, you need 5 more people for this, you can't possibly do this alone.
Unfortunately I can't be one of them, my wife would kill me :|
My hope is, when we finally release EG 0.5 (with the band-aid), we also attract more developers that can help to tackle this kind of undertaking. :roll:
With our resources at the moment, I see no chance to do this.
If you like my work, Image me a drink :wink:

User avatar
kgschlosser
Site Admin
Posts: 5508
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Locale problems in EventGhost.

Post by kgschlosser » Sat Apr 04, 2020 12:47 am

HOLY SHIT!!! someone that agrees with me about the parallel event processing!!!

I personally find not being able to run events in parallel and absolute annoyance. If you have 2 TV's being controlled by EG and you have 2 remotes integrated in EG as well. if someone holds down the volume button on one remote and then a button on the other remote gets pressed nothing will happen. not until the person lets go of the volume button. then and only then will any backlog of events get processed. EG was written around Windows XP when having 256 mb would be the same as having a terabyte of ram today. so the 1mb allocation for running a thread was a big deal back then. Think about that. you could never even achieve 256 threads total between all applications!!!! I have personally run 1000 for running tests. in a single process!!!

Starting a thread can be an expensive task I wrote a thread worker that handles running parallel threads. when an event comes in if the event has not come in ever before a container for that event is made. that container exists through the entire session of EG. there is one container per event. that container is the thread worker. when an event is to be processed if a thread is running already (repeat events) then a counter gets incremented by 1. each time all of the macros have been run the counter decreases by 1. once it hits 0 there is a 3 second wait. if an event does is not created in that 3 second window the thread exits. when an event comes in and a a thread is not running then it creates one. This is the best way to keep from chewing up ram but also keeping the speed for repeat events. The containers get made from '.'.join(event.split('.')[:-1]). this is so events like Event.Volume.100, Event.Eolume.99, Event.Volume.98...etc do not end up with a separate thread for each. So a single thread that processes Event.Volume.* is what you end up with.

I am still trying to hammer out how to display a log to the user. because writing to the log would be a jumble at best. I did write a debugging program https://github.com/kdschlosser/angry_debugger which has a mechanism that handles multiple threads to keep the logging output from getting all jumbled up. It also provides a bunch of other nifty features as well. I could do something like what I did in there and keep the current logging the way it is. Event Processing would slow down if a bunch of different events dump their output at the same time. Then again since the event thread is no longer going to process events and now only handles the creation of an event object or incrementing the counter which is not a whole lot of things for it to do. I could have it also write the logging information and if an event comes in that would take priority over logging.

OK so now I think I have a solution to that issue.. LOL sometimes just explaining a problem brings about a solution.
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 5508
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Locale problems in EventGhost.

Post by kgschlosser » Sat Apr 04, 2020 1:08 am

I have been writing portions of doing exactly what we are talking about doing over the past 2 years. So I already have the ability to run EG as a service. I already have the parallel events done (mostly). Also have a version of EventGhost running on Python 3.6, and I am compiling on x86 and x64.

EG really needs to be cut into sections. So the event handling portions are not reliant on the gui portions. I should be able to delete the Classes/MainFrame directory and EG would still be able to run. Or of I delete the Event Handling in EG it will still startup. GUI will function plugins will load all actions will still be available, only the events will not be working. a system like that would allow parts of the core to become pluggable.
If you like the work I have been doing then feel free to Image

User avatar
Sem;colon
Plugin Developer
Posts: 758
Joined: Sat Feb 18, 2012 10:51 am
Location: Germany

Re: Locale problems in EventGhost.

Post by Sem;colon » Sat Apr 04, 2020 10:52 am

Great! Sounds like you really made yourself some thoughts about this already :)

Yeah, the serial event processing has always been an annoyance for me too. I understand that it makes things easier, but when you use Eventghost as the core of your automation, this can really slow down things.
I also thought there should be a main thread processing events in a way that it kicks off the threads and then that threads process the macros.
With your container you're already one step ahead my thoughts, but could make sense :)
What I'd also suggest for that design is to first check if there even is a macro associated with an event before creating a thread worker, as most events are always unused and this would unnecessarily eat resources
If you like my work, Image me a drink :wink:

User avatar
kgschlosser
Site Admin
Posts: 5508
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Locale problems in EventGhost.

Post by kgschlosser » Sat Apr 04, 2020 8:10 pm

well see that is where I am one step ahead of you yet again.. LOL

I love an instance singleton.. You have probably heard of a singleton. But maybe not an instance singleton. here is some test code for ya

Code: Select all


class InstanceSingletonMeta(type):

    def __init__(cls, name, bases, dct):
        # Any class that has this class set as a metaclass will have this code
        # run as soon as the class gets built.
        super(InstanceSingletonMeta, cls).__init__(name, bases, dct)
        cls._instances = {}

    def __call__(cls, *args, **kwargs):
        key = list(args)
        for key in sorted(list(kwargs.keys())):
            value = kwargs[key]
            key += [value]

        key = tuple(repr(arg) for arg in key)

        if key not in cls._instances:
            instance = super(InstanceSingletonMeta, cls).__call__(*args, **kwargs)
            cls._instances[key] = instance

        return cls._instances[key]


class TestClass(object):
    __metaclass__ = InstanceSingletonMeta

    def __init__(self, param_1, param_2):
        pass



test = TestClass('test1', 'test2')
test2 = TestClass('test1', 'test2')
test3 = TestClass('test3', 'test4')

print test == test2
print test == test3
print test2 == test3

Only a single instance of a class can exist if the same parameters get passed. This is a fantastic mechanism to use when dealing w multiple devices. Like on a zwave network. It insures only a single "node" can exist at any given time.
Well for the purposes of these event containers it works perfect because I am able to create the containers when the tree loads and also when an event comes in. an instance does not take up much in the way of resources so it is not a concern so much to have them "stockpiled" But this will ensure That i do not make any duplicates on accident. Plus if a reference to the class is held somewhere in the code. and elsewhere in the code I want to make a change to it I know the information is going to populate to every area of EG,
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 5508
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Locale problems in EventGhost.

Post by kgschlosser » Sat Apr 04, 2020 8:36 pm

here is an update to that code example..I made a mistake in the version posted above

Code: Select all

class InstanceSingletonMeta(type):

    def __init__(cls, name, bases, dct):
        # Any class that has this class set as a metaclass will have this code
        # run as soon as the class gets built.
        super(InstanceSingletonMeta, cls).__init__(name, bases, dct)
        cls._instances = {}

    def __call__(cls, *args, **kwargs):
        keys = list(args)
        for key in sorted(list(kwargs.keys())):
            value = kwargs[key]
            keys += [value]

        keys = tuple(repr(arg) for arg in keys)

        if keys not in cls._instances:
            instance = super(InstanceSingletonMeta, cls).__call__(*args, **kwargs)
            cls._instances[keys] = instance

        return cls._instances[keys]


class TestClass(object):
    __metaclass__ = InstanceSingletonMeta

    def __init__(self, param_1, param_2):
        pass



test = TestClass('test1', 'test2')
test2 = TestClass('test1', param_2='test2')
test3 = TestClass(param_1='test1', param_2='test2')
test4 = TestClass('test3', 'test4')
test5 = TestClass('test3', param_2='test4')
test6 = TestClass(param_1='test3', param_2='test4')


print test == test2
print test == test3
print test2 == test3
print test4 == test
print test5 == test
print test6 == test
print test6 == test4
If you like the work I have been doing then feel free to Image

Post Reply