管理人さんのお this Japanese language is there an easy fix for the Japanese font not working with Show OSD?New OSD Style
imports and setup 0.0 milliseconds
GetTopLevelWindowList 0.0 milliseconds
_GetWindowThreadProcessId 82.9999446869 milliseconds
is fullscreen 0.0 milliseconds
GetWindowText 0.0 milliseconds
windows text evaluation 0.0 milliseconds
eg.plugins.MediaPlayerClassic.GetTimes 0.0 milliseconds
time evaluation 0.0 milliseconds
Fullscreen
building the bar 0.0 milliseconds
Traceback (most recent call last):
Python script "9", line 462, in <module>
elapsed_total=elapsed_total
UnicodeEncodeError: 'ascii' codec can't encode characters in position 51-60: ordinal not in range(128)
Help.. how OSD not working with Japanese fonts
Help.. how OSD not working with Japanese fonts
It took me a bit of time to figure out why Show OSD will not work with some videos. It appears it does not like foreign font types and throws up this error.
Re: Help.. how OSD not working with Japanese fonts
This is a wild guess but I would make sure the Japanese language pack is installed on your PC. You might also need a Japanese don't pack.
- kgschlosser
- Site Admin
- Posts: 5508
- Joined: Fri Jun 05, 2015 5:43 am
- Location: Rocky Mountains, Colorado USA
Re: Help.. how OSD not working with Japanese fonts
yes it is an easy fix. but I am going to need to know how your are trying to show the OSD. are your using an action or calling it from a script?
if you are using an action I need to know what you have entered in the text box.
if it is from a script i am going to need to see the line in the script that makes the call to show the OSD
if you are using an action I need to know what you have entered in the text box.
if it is from a script i am going to need to see the line in the script that makes the call to show the OSD
Re: Help.. how OSD not working with Japanese fonts
Well had a chance to get back to EventGhost. I am calling it by a script.kgschlosser wrote: ↑Mon Jun 22, 2020 6:26 amyes it is an easy fix. but I am going to need to know how your are trying to show the OSD. are your using an action or calling it from a script?
if you are using an action I need to know what you have entered in the text box.
if it is from a script i am going to need to see the line in the script that makes the call to show the OSD
Code: Select all
# 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}\n \n{bar}\n{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]
start = time.time()
_elapsed, _remaining, _duration = eg.plugins.MediaPlayerClassic.GetTimes()
# print "elaps, rem, total =",elaps, rem, total
# 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, 255, -1):
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 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;-030;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)
- kgschlosser
- Site Admin
- Posts: 5508
- Joined: Fri Jun 05, 2015 5:43 am
- Location: Rocky Mountains, Colorado USA
Re: Help.. how OSD not working with Japanese fonts
unicode problems in Python 2.7 are a pain to deal with. Give the code below a shot and see if it works. I might have to decode to latin1 and then encode to utf-8 or just decode as utf-8 or it could be encode then decode. I can't remember off hand. I will get it working for you tho
Code: Select all
# 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}\n \n{bar}\n{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]
start = time.time()
_elapsed, _remaining, _duration = eg.plugins.MediaPlayerClassic.GetTimes()
# print "elaps, rem, total =",elaps, rem, total
# 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, 255, -1):
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 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;-030;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.decode('utf-8'),
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)
Re: Help.. how OSD not working with Japanese fonts
Hi kgschlosser,
I know it's been a while hope things are going fine for you. Crazy last year even had a neighbor die after getting Covid. Well currently looking for a new job had lost mine from because of Covid they lost some contracts so I have got some free time. I tried the code above and here is the error message I got.
Traceback (most recent call last):
Python script "12", line 461, in <module>
title=title.decode('utf-8'),
File "encodings\utf_8.pyc", line 16, in decode
UnicodeEncodeError: 'ascii' codec can't encode characters in position 41-43: ordinal not in range(128)
Thanks for the assist when you got the chance.
I know it's been a while hope things are going fine for you. Crazy last year even had a neighbor die after getting Covid. Well currently looking for a new job had lost mine from because of Covid they lost some contracts so I have got some free time. I tried the code above and here is the error message I got.
Traceback (most recent call last):
Python script "12", line 461, in <module>
title=title.decode('utf-8'),
File "encodings\utf_8.pyc", line 16, in decode
UnicodeEncodeError: 'ascii' codec can't encode characters in position 41-43: ordinal not in range(128)
Thanks for the assist when you got the chance.