Need help creating a "Toast" or "OSD" message.
#1
Hi all,

I hope someone can help me. I need to periodically display status messages onscreen. Basically what I would like to do is create something that is functionally equivalent to the current "notification" dialog, as in ExecBuiltIn(Notification())

I would like my addon to be able to pop up messages in the same way, without stealing user focus. I want the user to be able to continue interacting with XBMC without this window interfering in any way except "visually" and then I want this window to quietly go away by itself after a few seconds. Imagine someone is scrolling through items in XBMC when this window appears. I want the user to be able to continue scrolling, even change to another window etc. without interference.

So, again, functionally it would be almost exactly the way the current notification system works, but I don't want to use the notification that exists for a number of reasons.

1 - It is different on every skin and this causes problems for my addon.
2 - In most if not all skins the layout of this notification does not allow enough room to show the information that I want to show. Sometimes I only need to show one or two lines of text, but sometimes I need to show a list of up to 8 items in addition to the title.

I have considered and tried a few options, but they all have significant issues that make them unacceptable for my purposes.

1 - Most python examples with a pop up window such as "helloworld" show a dialog that steals focus away from whatever XBMC was doing before so I can't use this method.
I thought about modifying dialog KaiToast xml but this is not an option because I want other notifications to continue to work normally in the way that the skin has defined them. Also I need a solution that others can use without having to edit files by hand.

2 - Other ideas I had included adding and removing controls from the "current window". This sort of works in my tests but it seems messy and problematic and if the user goes to a new window before my script removes the controls that it added, then they will reappear for a second when the user returns to the window.

3 - I also tried showing a notification, and then attaching extra controls to this notification window. Again it works but it is messy and I am still stuck with the original controls from that window and concerns about cleaning up my controls before the notification window disappears. I also would like to be able to show my message without audio because it will potentially be quite annoying otherwise.

Thanks in advance for any ideas how I can accomplish this! I can't help but feel like I am missing something really obvious in the XBMCGUI library.
Image
VoxCommando.com
Reply
#2
xbmcgui.WindowDialog() container does not steal focus per se. It propagates all unprocessed events down to core XBMC. And if you need to show you info window only temporarily, you can use show() methods instead of doModal(). In this case xbmcgui.WindowDialog() does not create an event loop, which means it does not catch any events, such as key-presses.
You can look into my PyXBMCt framework (http://forum.xbmc.org/showthread.php?tid=174859) if you need a ready-to-use pure Pythonic solution for your info-window.
Reply
#3
Good answer Smile

And I also can recommend using Roman's PyXBMCt for your task
My GitHub. My Add-ons:
Image
Reply
#4
Hi Roman. Thanks very much for your answer.

I am already using .show() and not .doModal since I do not want a modal window. Your post got me thinking though. Maybe it is not really stealing focus, but freezing xbmc somehow since I was calling xbmc.sleep. So I went ahead and created a thread in which I could pop up my window, sleep and then destroy the window. Unfortunately that doesn't seem to help.

If I execute this script when I am on the XBMC home window and then press the left and right arrow keys on my keyboard while my window is still open, I can hear the "swish sound" associated with arrow keys, but the selected item does not change. I can see though that label items like the rss ticker are continuing to roll. This tells me that the main window is not being frozen, and that XBMC is detecting my keypresses, but they are not getting to the main window which makes me think they are going to my window instead. Furthermore, if I use the mouse to click the XBMC window outside my window and then use the arrow keys, it continues to make swish sounds, without doing anything.

Here is the latest version of my test code.



Code:
import xbmc,  xbmcgui, sys, re
import urlparse, threading, time
    
class PopupWindow(xbmcgui.WindowDialog):
    def __init__(self):
        bx=350
        by=100
        self.addControl(xbmcgui.ControlImage(bx,by, width=600, height=275, filename="D:\\voxtools\\bkgosd.png"))
        self.addControl(xbmcgui.ControlImage(bx+12,by+10, width=50, height=50, filename="D:\\voxtools\\megaphone.png"))                
        lblTitle = xbmcgui.ControlLabel(bx+80, by+14, 500, 20, "this is a test", "font14", "0xFFFFFFFF")
        self.addControl(lblTitle)  

class myGui (threading.Thread):
    def __init__(self, threadID):
        self.threadID = threadID        
        threading.Thread.__init__(self)
        self.setDaemon(True)
  
    def run(self):
        window = PopupWindow()        
        window.show()
        time.sleep(4)
        window.close()
        del window    
        print "window has been removed."

print "================= VoxTools Script Execution Begins ===================="  

pollingthread = myGui(1234)
pollingthread.start()
print "myGui thread started"

Again, thanks very much for your attention. I really hope you can spot something.

By the way I have also done tests where I open a notification window and attach controls to it and it works perfectly, except that I am stuck with the origianl dialog Kai toast controls on it which I don't want to see.

Thanks also for the link to PyXBMCt. I am sure there is a lot of good stuff in there for me to learn from.
Image
VoxCommando.com
Reply
#5
Oh and by the way, in case it is relevant, I an starting this script using a JSON Addons.ExecuteAddon call from another program using the http service.
Image
VoxCommando.com
Reply
#6
You can also attach Python controls to an existing window using xbmcgui.Window class and providing it a current window ID. For example, the following code will attach a yellow clock label to the top right corner of the window:
PHP Code:
import xbmcgui

window 
xbmcgui.Window(xbmcgui.getCurrentWindowId())
time_label xbmcgui.ControlLabel(12002010050'$INFO[System.Time]',
                                            
font='font24_title'textColor='0xFFFFFF00')
window.addControl(time_label_video
To remove label use .removeControl() method. Note that you do not need to call show() or doModal() here, because the window with a given ID already exists.
This way all keyboard and mouse event are received by the parent window, and new controls do not steal focus, unless you use setFocus on them.

BTW, PyXBMCt does not support such scenario.
Reply
#7
(2014-02-21, 18:17)Roman_V_M Wrote: You can also attach Python controls to an existing window using xbmcgui.Window class and providing it a current window ID. For example, the following code will attach a yellow clock label to the top right corner of the window:

Thanks Roman, but I already mentioned this in my original post as an option that i had considered and dismissed, and I explained why.
Image
VoxCommando.com
Reply
#8
This was in my original post.

(2014-02-20, 23:04)jitterjames Wrote: 2 - Other ideas I had included adding and removing controls from the "current window". This sort of works in my tests but it seems messy and problematic and if the user goes to a new window before my script removes the controls that it added, then they will reappear for a second when the user returns to the window.

3 - I also tried showing a notification, and then attaching extra controls to this notification window. Again it works but it is messy and I am still stuck with the original controls from that window and concerns about cleaning up my controls before the notification window disappears. I also would like to be able to show my message without audio because it will potentially be quite annoying otherwise.

I am confused by your original statement that:
Quote:xbmcgui.WindowDialog() container does not steal focus per se. It propagates all unprocessed events down to core XBMC.
because this is not the behaviour that I am seeing. Is that because I am doing something wrong, misunderstanding what you are telling me, or something else? I have tested this on a number of systems running Frodo 12.2, Frodo 12.3, and a recent Gotham nightly from last week.

I think the only ideal, clean solution would be to create my own window, however that doesn't seem possible without interfering with user input. If you can think of a solution that makes idea 2, or 3 from my quote above workable, I am eager to consider any suggestions.

Thanks again for your effort to help me. This is a problem that stumped me 2 years ago. I had walked away from the problem, and revisited it a couple of times, but now I would really like to find a way to make it work!
Image
VoxCommando.com
Reply
#9
Oh well. I guess I was right 2 years ago when I determined that there was no solution for this problem.

It is a shame. Some method to display windows in XBMC without interfering with user input seems like a no-brainer necessity to me. I'm not sure why this isn't more of an issue for more developers.

It would not be so much of an issue if the notification popups were not so limited. I feel that the visual notification system for XBMC has been seriously overlooked. I don't think it has really changed since XBMC was running on the original XBOX console.
Image
VoxCommando.com
Reply
#10
(2014-02-21, 18:17)Roman_V_M Wrote: You can also attach Python controls to an existing window using xbmcgui.Window class and providing it a current window ID. For example, the following code will attach a yellow clock label to the top right corner of the window:
PHP Code:
import xbmcgui

window 
xbmcgui.Window(xbmcgui.getCurrentWindowId())
time_label xbmcgui.ControlLabel(12002010050'$INFO[System.Time]',
                                            
font='font24_title'textColor='0xFFFFFF00')
window.addControl(time_label_video
To remove label use .removeControl() method. Note that you do not need to call show() or doModal() here, because the window with a given ID already exists.
This way all keyboard and mouse event are received by the parent window, and new controls do not steal focus, unless you use setFocus on them.

BTW, PyXBMCt does not support such scenario.

(2014-02-24, 17:54)jitterjames Wrote: Oh well. I guess I was right 2 years ago when I determined that there was no solution for this problem.

It is a shame. Some method to display windows in XBMC without interfering with user input seems like a no-brainer necessity to me. I'm not sure why this isn't more of an issue for more developers.

It would not be so much of an issue if the notification popups were not so limited. I feel that the visual notification system for XBMC has been seriously overlooked. I don't think it has really changed since XBMC was running on the original XBOX console.

Thanks both, this advice helped me greatly.

Roman_V_M, extra thanks for you great PyXBMCt!
Reply

Logout Mark Read Team Forum Stats Members Help
Need help creating a "Toast" or "OSD" message.1