Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # this try/except routine is done because the information that is generated
- # in a Python script is persistent between runs. Whats this means is that
- # anything that is created in a python script when the script gets run a
- # second, third, fourth... the objects created the first time are available to
- # every run thereafter. So if you have any objects created that are static and
- # do not change between runs then there is no need to make them over again.
- # To test for this we simply use one of those object names that are static.
- # if the object exists it will pass right on by. if it oes not it will
- # generate an error that we catch in the except portion of thee code block.
- # And that is where we will then create all of the static objects
- # adjustable set between 0 and 255
- MAX_TRANSPARENT = 255
- import time
- start = time.time()
- try:
- user32
- except NameError:
- import wx
- import datetime
- import time
- import threading
- import ctypes
- from ctypes.wintypes import (
- BOOL,
- LONG,
- UINT,
- POINT,
- RECT,
- HWND,
- LPARAM,
- DWORD
- ) # NOQA
- from eg.WinApi import (
- GetWindowText,
- GetTopLevelWindowList,
- GetProcessName
- ) # NOQA
- from eg.WinApi.Dynamic import (
- SetWindowPos,
- SWP_FRAMECHANGED,
- SWP_NOACTIVATE,
- SWP_NOOWNERZORDER,
- SWP_SHOWWINDOW,
- )
- HWND_FLAGS = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_FRAMECHANGED
- GWL_STYLE = -16
- GWL_EXSTYLE = -20
- WS_BORDER = 0x00800000
- WS_DLGFRAME = 0x00400000
- WS_THICKFRAME = 0x00040000
- WS_EX_WINDOWEDGE = 0x00000100
- WS_POPUP = 0x80000000
- WS_EX_TOPMOST = 0x00000008
- PID = DWORD
- user32 = ctypes.windll.User32
- # DWORD GetWindowThreadProcessId(
- # HWND hWnd,
- # LPDWORD lpdwProcessId
- # );
- _GetWindowThreadProcessId = user32.GetWindowThreadProcessId
- _GetWindowThreadProcessId.restype = DWORD
- # LONG GetWindowLongW(
- # HWND hWnd,
- # int nIndex
- # );
- _GetWindowLong = user32.GetWindowLongW
- _GetWindowLong.restype = LONG
- # HWND GetActiveWindow(
- #
- # );
- _GetActiveWindow = user32.GetActiveWindow
- _GetActiveWindow.restype = HWND
- BAR_TEMPLATE = \'[{bars}{remaining}] - {percent:.2f}%\'
- ELAPSED_TOTAL_TEMPLATE = \'Elapsed: {elapsed} / Total: {duration}\'
- OSD_TEMPLATE = \'{title}\
- \
- {bar}\
- {elapsed_total}\'
- osd_frame = eg.plugins.EventGhost.actions[\'ShowOSD\'].osdFrame
- _old_show_osd = osd_frame.ShowOSD
- _old_on_timeout = osd_frame.OnTimeout
- eg.globals.fade_in_event = threading.Event()
- eg.globals.fade_out_event = threading.Event()
- stop = time.time()
- ##print \'imports and setup\', (stop - start) * 1000, \'milliseconds\'
- start = time.time()
- # OK so I removed the euse of the eg.WindowMatcher.
- # it is a horribly slow thing to use and since we are only looking to see
- # if a process is running or not we use GetTopLevelWindowList which returns
- # the handles for the base window class of an application. then we ask windows
- # to get us the process id (pid) for one of the handles in the returned list.
- # Then we use that pid to get the process name. and we match that process name
- # up with the one we are looking for.
- handles = GetTopLevelWindowList(False)
- stop = time.time()
- ##print \'GetTopLevelWindowList\', (stop - start) * 1000, \'milliseconds\'
- start = time.time()
- # OK so I added some code to locate which instance of mpc to use if more then
- # one is running.
- # I elected to do some crafty coding with this. What happens is after the the
- # window handles are found I then query the Windows API to get thee styles of
- # the window. i check for specific markers like if the window has a border and
- # if the window is set to be the topmost window as these are things that get
- # turned on/off when an application goes into a fullscreen mode. at the same
- # time I am also checking for a copy of mpc that is the active window. I do
- # this to cover my bases, if there is more then a single active copy and none
- # of them are set to full screen it is going to choose the one that is active
- # (has focus). if there is a fullscreen copy running and a second. and the
- # second is active the fullscreen is going to be the one used.
- for handle in handles[:]:
- pid = PID()
- _GetWindowThreadProcessId(HWND(handle), ctypes.byref(pid))
- process_name = GetProcessName(pid.value)
- # we check the process name of the window. if it does not match then we
- # remove it form the list.
- if process_name != \'mpc-hc64.exe\':
- handles.remove(handle)
- stop = time.time()
- ##print \'_GetWindowThreadProcessId\', (stop - start) * 1000, \'milliseconds\'
- # if there are no windows found then we want to stop the macro from running and
- # exit the script
- if not handles:
- handle = None
- eg.StopMacro()
- eg.Exit()
- handle = None
- # I removed the use of eg.globals.WindowsState as a mechanism for checking if
- # the app is in fullscreen mode. Because this is one of the things we are
- # looking for when we pick the window to use we no longer need to depend on
- # an outside source to determine the window state. So you can remove that from
- # your tree if you want.
- is_fullscreen = False
- start = time.time()
- for hwnd in handles:
- # getting the windows styles and extended styles.
- style = _GetWindowLong(HWND(hwnd), GWL_STYLE)
- style_ex = _GetWindowLong(HWND(hwnd), GWL_EXSTYLE)
- # checking the styles for specific markers.
- if (
- not style & WS_BORDER and
- not style & WS_DLGFRAME and
- not style & WS_THICKFRAME and
- not style_ex & WS_EX_WINDOWEDGE and
- style & WS_POPUP and
- style_ex & WS_EX_TOPMOST
- ):
- # if there are 2 copies of mpc running and both are fullscreen then
- # we are going to use the one that is active
- if is_fullscreen is False:
- handle = hwnd
- is_fullscreen = True
- elif _GetActiveWindow() == hwnd:
- handle = hwnd
- is_fullscreen = True
- # if there is no full screen one found already and this window is active
- # then we seet it into place
- elif handle is None and _GetActiveWindow() == hwnd:
- handle = hwnd
- is_fullscreen = False
- stop = time.time()
- ##print \'is fullscreen\', (stop - start) * 1000, \'milliseconds\'
- # fallback if something does not work properly in the code.
- if handle is None:
- handle = handles[0]
- start = time.time()
- window_text = GetWindowText(handle)
- stop = time.time()
- ##print \'GetWindowText\', (stop - start) * 1000, \'milliseconds\'
- # I removed the use of re and did a simple trial and error using a for loop
- # with an else statement.
- # If i split a string on a value and that value is not n the string it is
- # going to return a list with the original string at index 0. So the list
- # only las a length of 1. if it did have the value in it the list would have a
- # length greater then 1. and we use that to break the loop. This will cause
- # the else to not get run.
- start = time.time()
- for item in (".mkv", ".mp4", ".avi", ".ogm"):
- window_text = window_text.split(item)
- if len(window_text) > 1:
- break
- window_text = window_text[0]
- else:
- window_text = window_text.split(\'.\')
- stop = time.time()
- ##print \'windows text evaluation\', (stop - start) * 1000, \'milliseconds\'
- title = window_text[0]
- print \'value of time.time() is \', + time.time()
- start = time.time()
- _elapsed, _remaining, _duration = eg.plugins.MediaPlayerClassic.GetTimes()
- print \'value of times: _elapsed:\', _elapsed, \'; _remaining:\', _remaining, \'duration;\', _duration
- # I removed all of that math involved in trying to get the seconds in
- # favor of using time.strptime and datetime.timedelta
- # time.strptime will take a string formatted time representation and turn it
- # into a python object for us. we simply have to provide details as to how the
- # string is formatted. you can get more information on the identifiers here
- # http://strftime.org/
- # once we have that object which only does the simple
- # conversion to hours minutes seconds we need to create another object that
- # does the match for us and will return the total seconds
- stop = time.time()
- ##print \'eg.plugins.MediaPlayerClassic.GetTimes\', (stop - start) * 1000, \'milliseconds\'
- start = time.time()
- while _elapsed.count(\':\') < 2:
- _elapsed = \'00:\' + _elapsed
- while _remaining.count(\':\') < 2:
- _remaining = \'00:\' + _remaining
- while _duration.count(\':\') < 2:
- _duration = \'00:\' + _duration
- elapsed = time.strptime(_elapsed, \'%H:%M:%S\')
- elapsed = datetime.timedelta(
- hours=elapsed.tm_hour,
- minutes=elapsed.tm_min,
- seconds=elapsed.tm_sec
- )
- remaining = time.strptime(_remaining, \'%H:%M:%S\')
- remaining = datetime.timedelta(
- hours=remaining.tm_hour,
- minutes=remaining.tm_min,
- seconds=remaining.tm_sec
- )
- duration = time.strptime(_duration, \'%H:%M:%S\')
- duration = datetime.timedelta(
- hours=duration.tm_hour,
- minutes=duration.tm_min,
- seconds=duration.tm_sec
- )
- stop = time.time()
- ##print \'time evaluation\', (stop - start) * 1000, \'milliseconds\'
- # heere we do a test to see if elapsed has any seconds to it. if iit does
- # that means the video is playing and to generate the osd
- if elapsed.total_seconds():
- def fade_in():
- beg = time.time()
- for i in range(MAX_TRANSPARENT):
- if eg.globals.fade_in_event.isSet():
- break
- osd_frame.SetTransparent(i)
- eg.globals.fade_in_event.wait(0.01)
- osd_frame.ShowOSD = _old_show_osd
- end = time.time()
- ##print \'fade in\', (end - beg) * 1000, \'milliseconds\'
- def fade_out():
- beg = time.time()
- for i in range(MAX_TRANSPARENT, 0, -255):
- if eg.globals.fade_out_event.isSet():
- break
- osd_frame.SetTransparent(i)
- eg.globals.fade_out_event.wait(0.01)
- _old_on_timeout()
- osd_frame.OnTimeout = _old_on_timeout
- end = time.time()
- ##print \'fade out\', (end - beg) * 1000, \'milliseconds\'
- def show_osd(*args, **kwargs):
- args = list(args)
- args[7] += MAX_TRANSPARENT * 0.01
- eg.globals.fade_out_event.set()
- eg.globals.fade_in_event.clear()
- osd_frame.SetTransparent(0)
- _old_show_osd(*args, **kwargs)
- fade_in()
- def on_timeout():
- eg.globals.fade_in_event.set()
- eg.globals.fade_out_event.clear()
- fade_out()
- osd_frame.ShowOSD = show_osd
- osd_frame.OnTimeout = on_timeout
- # instead of having to calls to ShowOSD we can set the parameters we want
- # to pass to ShowOSD into a variable you name the variable the same for
- # Fullscreen and not Fullscreen and set the parameters for each variation
- # then when we call ShowOSD the proper set of parameters will be passed
- #eg.plugins.EventGhost.ShowOSD(u\'Ahira no Sora\', u\'0;-96;0;0;0;700;0;0;0;0;3;2;1;49;Consolas\', (255, 255, 255), (0, 0, 0), 4, (0, 0), 1, 3.0, None)
- #eg.plugins.EventGhost.ShowOSD(u\'Ahira no Sora\', u\'0;-96;0;0;0;400;255;0;0;0;3;2;1;49;Consolas\', (255, 255, 255), (0, 0, 0), 4, (0, 0), 1, 3.0, None)
- print \'MPC Window State is \', eg.globals.WindowsState
- if eg.globals.WindowsState == "Fullscreen":
- osd_args = (
- u\'0;-60;0;0;0;700;255;0;0;0;3;2;1;34;Consolas\',
- (0, 255, 255),
- (0, 0, 0),
- 4,
- (0, 0),
- 1,
- 3.0,
- None
- )
- else:
- osd_args = (
- u\'0;-040;0;0;0;700;255;0;0;0;3;2;1;34;Consolas\',
- (0, 255, 255),
- (0, 0, 0),
- 4,
- (0, 0),
- 2,
- 3.0,
- None
- )
- start = time.time()
- # I trimmed down the percent math. iif you want to change an int to a
- # float you do not need to do 1.0 * int. this will work but the pythonic
- # way is to wrap that int with float()
- percent = (
- (
- float(elapsed.total_seconds()) /
- float(duration.total_seconds())
- ) * 100.0
- )
- # I removed the conversion of the percent form a float to an int because
- # i wanted the percent as a float for use further on down the line
- bars = \'/\' * int(round(percent))
- remaining = \'.\' * (100 - len(bars))
- # I created string templates for the OSD. i split the osd into 3 sections
- # I will explain as to why they are split into 3 sections further down
- # I added the percent that has elapsed to the bar line as a 2 decimal place
- # float
- bar = BAR_TEMPLATE.format(
- bars=bars,
- remaining=remaining,
- percent=percent
- )
- elapsed_total = ELAPSED_TOTAL_TEMPLATE.format(
- elapsed=_elapsed,
- duration=_duration
- )
- # OK so this is an odd thing. wx is thee GUI interface we use to generate
- # all of the graphics, windows and controls in EG. because of how text
- # gets displayed when using a GUI the characters defined in a font are
- # not of equal size, so a "G" does not have the same width as an "!"
- # I saw that you were displaying the OSD n the center of the screen with
- # what looked like center justification. because of that font issue ths
- # is extremely difficult to do. Portions of the wx library allow us to call
- # a function called GetTextExtent this function rill return the width and
- # height in pixels of a string passed into it. we have to set the font we
- # want to use then call the function. in order to get the center
- # justification as close as we can and the space is the only thing we can
- # really do it with we also want to know the width of a space.
- stop = time.time()
- ##print \'building the bar\', (stop - start) * 1000, \'milliseconds\'
- start = time.time()
- frame = wx.Frame(None, -1)
- font = wx.FontFromNativeInfoString(osd_args[0])
- frame.SetFont(font)
- bar_len = frame.GetTextExtent(bar)[0]
- title_len = frame.GetTextExtent(title)[0]
- elapsed_total_len = frame.GetTextExtent(elapsed_total)[0]
- space_len = frame.GetTextExtent(\' \')[0]
- # so here we do the checking to see which line is longer then the other to
- # adjust the one that is shorter
- if bar_len < title_len:
- # this is the number of spaces we are going to need. so we find out the
- # pixel difference divide that by the number of pixels a space is.
- # this is going to return the total number of spaces needed to make the
- # line the same length. Now remember center justification. so half of
- # those spaces would need to be on thee back end of the line. Those
- # we do not need to add to the line. so wee divide the total number of
- # spaces by 2 to get the number of spaces we need to add to the front
- # of the line
- space_count = (
- int(round(float(title_len - bar_len) / float(space_len))) / 2
- )
- bar = \' \' * space_count + bar
- elif title_len < bar_len:
- space_count = (
- int(round(float(bar_len - title_len) / float(space_len))) / 2
- )
- title = \' \' * space_count + title
- bar_len = frame.GetTextExtent(bar)[0]
- frame.Destroy()
- if elapsed_total_len < bar_len:
- space_count = (
- int(round(
- float(bar_len - elapsed_total_len) / float(space_len))) / 2
- )
- elapsed_total = \' \' * space_count + elapsed_total
- osd = OSD_TEMPLATE.format(
- title=title,
- bar=bar,
- elapsed_total=elapsed_total
- )
- # and here is the single call to ShowOSD. we prefiix that variable we made
- # earlier with a * which expands the variable into the parameters that
- # needs to be passed
- stop = time.time()
- print \'calculating bar position on the screen\', (stop - start) * 1000, \'milliseconds\'
- eg.plugins.EventGhost.ShowOSD(osd, *osd_args)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement