Difference between revisions of "DevelopWDTVExtPlugin"
Line 44: | Line 44: | ||
Now, let's start creating our first WDTVext plugin: '''Example.plugin.js''' | Now, let's start creating our first WDTVext plugin: '''Example.plugin.js''' | ||
− | + | == Example Plugin == | |
− | + | === Basic Plugin Skeleton === | |
Every Plugin strats with some basic plugin constructor: | Every Plugin strats with some basic plugin constructor: | ||
Line 79: | Line 79: | ||
All occurances of '''ExamplePlugin''' are of course to be substituted with the name of your plugin. | All occurances of '''ExamplePlugin''' are of course to be substituted with the name of your plugin. | ||
− | + | === Page Control === | |
− | + | ==== Global Page Methods ==== | |
− | + | ===== Page.Top.getParam() / Page.Top.setParam() ===== | |
This can be used in any function you create to read or write @@variables. The @@variables are referenced '''without''' @@! | This can be used in any function you create to read or write @@variables. The @@variables are referenced '''without''' @@! | ||
Line 91: | Line 91: | ||
</pre> | </pre> | ||
− | + | ===== Page.redraw() ===== | |
Call this with argument '''true''' to force a page redraw: | Call this with argument '''true''' to force a page redraw: | ||
<pre> | <pre> | ||
Line 97: | Line 97: | ||
</pre> | </pre> | ||
− | + | ==== onPageCreated ==== | |
This is called when a new page is created. This is the place where we add our extra content to display some cool output on the screen. So we are going to add two text lines to the menu page (fill this code into the above at the mentioned space). | This is called when a new page is created. This is the place where we add our extra content to display some cool output on the screen. So we are going to add two text lines to the menu page (fill this code into the above at the mentioned space). | ||
Line 123: | Line 123: | ||
'''@@exampleText''' and '''@@exampleKey'''. Since we haven't set those variables yet, we see... nothing! ;) | '''@@exampleText''' and '''@@exampleKey'''. Since we haven't set those variables yet, we see... nothing! ;) | ||
− | + | ==== onPageEnter ==== | |
Ok, having text elements we can't see isn't worth much... let's change that. | Ok, having text elements we can't see isn't worth much... let's change that. | ||
Line 144: | Line 144: | ||
Now we should see '''villa_home.xml''' as white text in upper left screen. | Now we should see '''villa_home.xml''' as white text in upper left screen. | ||
− | + | ==== onPageLeave ==== | |
Same as onPageEnter but when page is left. | Same as onPageEnter but when page is left. | ||
Line 164: | Line 164: | ||
</pre> | </pre> | ||
− | + | ==== onPageKey ==== | |
Things are starting to get interesting with this event now. | Things are starting to get interesting with this event now. | ||
Line 188: | Line 188: | ||
− | + | ==== onPageTimer ==== | |
The onPageTimer event gets called every ~500ms. You can use this to handle periodic events. | The onPageTimer event gets called every ~500ms. You can use this to handle periodic events. | ||
Line 218: | Line 218: | ||
</pre> | </pre> | ||
− | + | === Menu Control === | |
On for the menus. Here I will show you how to create new menu items and manipulate existing ones. First we will link the '''Video''' mainmenu item directly to it's childs ('''Local Drives''') child '''Folders'''. So on entering Video on main menu will bring up the movie brower instantly. (Note: you won't be able to access all other items under '''Video''' then, like youtube, mediaservers, etc...) | On for the menus. Here I will show you how to create new menu items and manipulate existing ones. First we will link the '''Video''' mainmenu item directly to it's childs ('''Local Drives''') child '''Folders'''. So on entering Video on main menu will bring up the movie brower instantly. (Note: you won't be able to access all other items under '''Video''' then, like youtube, mediaservers, etc...) | ||
− | |||
− | + | ==== doBuildMenus ==== | |
All the magic of creating new menu items happens in this function. So let's start with this. | All the magic of creating new menu items happens in this function. So let's start with this. | ||
Line 240: | Line 239: | ||
</pre> | </pre> | ||
− | + | ===== Menu.Top ===== | |
Globaly access menu item properties. These are accessed as shown in the the above example code. To find out the right title (they are case sensitive!), it's useful to write a some logging/displaying code as i've shown with the markup file name in the page section (using '''onMenuSelect()'''). | Globaly access menu item properties. These are accessed as shown in the the above example code. To find out the right title (they are case sensitive!), it's useful to write a some logging/displaying code as i've shown with the markup file name in the page section (using '''onMenuSelect()'''). | ||
− | + | ===== new Menu() ===== | |
Let's create a new menu item now. This is going to be a quite simple reboot option. | Let's create a new menu item now. This is going to be a quite simple reboot option. | ||
Line 255: | Line 254: | ||
the parameters are '''Menu( name, title, image, focusedImage, visible)'''. | the parameters are '''Menu( name, title, image, focusedImage, visible)'''. | ||
− | + | ===== addChild() ===== | |
Now we add a submenu item to which will actually reboot the wdtv when selected. | Now we add a submenu item to which will actually reboot the wdtv when selected. | ||
Line 274: | Line 273: | ||
− | + | ==== onMenuSelect ==== | |
− | + | ==== onMenuDeselect ==== | |
Revision as of 05:31, 10 July 2011
Develop - WDTVExt Plugins
WDTVExt is not available for firmware versions higher than 1.02.21!
WDTVExt allow to add custom plugins/extensions to WDlxTV 1.02.21 firmware.
These plugins are written in JavaScript.
Filename
To load your plugin, the filename of your plugin needs to end with .plugin.js.
Getting Started...
I will try to explain here how to start developing WDTVExt plugins. I'm by no means a 'programmer' and learned javascript just recently while discovering WDTVExt. So if I'm doing something wrong here, please correct me!
What can we do with WDTVExt? (v0.23.5)
- File [1]
- read and write files (can also be used to execute shell commands and retrieve the output)
- XML [2]
- parse/manipulate XML content
- Curl
- fetch web content with curl
- Page Control
- add extra XML content
- introduce new @@variables to page
- read all @@variables from page
- write all @@variables to page
- force redraw of page
- react to keys pressed on remote
- Menu Control
- add new menu items
- add new submenu item
- maniplulate menu and submenu items (title, image, focusedImage, handler, ...)
What can't we do with WDTVExt? (v0.23.5)
- create entire custom pages
- create menu items that link to a folder or file
- create setup pages
Now, let's start creating our first WDTVext plugin: Example.plugin.js
Example Plugin
Basic Plugin Skeleton
Every Plugin strats with some basic plugin constructor:
// all traces both trace and traceln will output in /tmp/dmaosd.log (or /tmp/wdtvext.log) traceln("Plugin.Example: Start loading Example plugin") function ExamplePlugin(path) { this.rootPath = path; traceln("Plugin.Example: base path is " + this.rootPath); } // chain ExamplePlugin with proper inheritance - classical in javascript ExamplePlugin.prototype = new Plugin(); ExamplePlugin.prototype.constructor = ExamplePlugin; // // our later to develop code and functions will // // go here, left blank for now // // create our plugin with baseParg pointing to current script path // global variables scriptName, scriptLocation and scriptFullPath are available, no need to do the following ExamplePlugin.instance = new ExamplePlugin(scriptPath); // register our plugin with WDTVext Plugin.registerPlugin(ExamplePlugin.instance); traceln("Plugin.Example: End loading Example plugin");
All occurances of ExamplePlugin are of course to be substituted with the name of your plugin.
Page Control
Global Page Methods
Page.Top.getParam() / Page.Top.setParam()
This can be used in any function you create to read or write @@variables. The @@variables are referenced without @@!
Page.Top.setParam("exampleVariable", "Hello World!") var exampleVariable = Page.Top.getParam("exampleVariable")
Page.redraw()
Call this with argument true to force a page redraw:
Page.redraw(true)
onPageCreated
This is called when a new page is created. This is the place where we add our extra content to display some cool output on the screen. So we are going to add two text lines to the menu page (fill this code into the above at the mentioned space).
ExamplePlugin.prototype.onPageCreated = function(page){ // villa_home.xml is the menu page we want our text only to show on this page... if(page.markupFileName == "villa_home.xml"){ // check for existing extraContent if(!page.extraContent) { page.extraContent = "" } // now we add our own extra content... page.extraContent += <wrapper> <text text="@@exampleText" x="50" y="50" w="768" h="20" textcolor="0xffffff" align="left" fontsize="18"/> <text text="@@exampleKey" x="50" y="80" w="768" h="20" textcolor="0xffffff" align="left" fontsize="18"/> </wrapper>; } }
This creates two lines of white text in the upper left area of the screen, which will display the contents of the two variables @@exampleText and @@exampleKey. Since we haven't set those variables yet, we see... nothing! ;)
onPageEnter
Ok, having text elements we can't see isn't worth much... let's change that. After the page is created the onPageEnter event is called, we use this to populate some content to our variables.
ExamplePlugin.prototype.onPageEnter = function(page) { // again we want this only to execute on main menu... if(page.markupFileName == "villa_home.xml"){ // set @@exampleText to the filename of the current xml page Page.Top.setParam("exampleText", page.markupFileName) // sometimes it's needed to redraw the page, we will do this just in case... Page.redraw(true) } }
Now we should see villa_home.xml as white text in upper left screen.
onPageLeave
Same as onPageEnter but when page is left. We delete the text again here.
ExamplePlugin.prototype.onPageLeave = function(page) { // again we want this only to execute on main menu... if(page.markupFileName == "villa_home.xml"){ // set @@exampleText to the filename of the current xml page Page.Top.setParam("exampleText", "") // sometimes it's needed to redraw the page, we will do this just in case... Page.redraw(true) } }
onPageKey
Things are starting to get interesting with this event now. This event is called everytime you press a key on the remote (or you use /tmp/ir_injection ;)). Let's add some code to display the last pressed key.
ExamplePlugin.prototype.onPageKey = function(page, key) { // again we want this only to execute on main menu... if(page.markupFileName == "villa_home.xml"){ // set @@exampleKey to key number Page.Top.setParam("exampleKey", key) // set @@exampleText to markup file name Page.Top.setParam("exampleText", page.markupFileName) // sometimes it's needed to redraw the page, we will do this just in case... Page.Top.redraw(true) } }
onPageTimer
The onPageTimer event gets called every ~500ms. You can use this to handle periodic events. If you want your funtion to be executed less often, you have to skip some calls like shown below. It will execute the code every 5th call, so every ~2,5s.
ExamplePlugin.prototype.onPageTimer = function(page) { // again we want this only to execute on main menu... if(page.markupFileName == "villa_home.xml"){ if (!this.skipCounter) { this.skipCounter = 0 } if (this.skipCounter < 5) { this.skipCounter++ } else { this.skipCounter = 0 // // here goes the code that should be executed every 2,5s // } } }
Menu Control
On for the menus. Here I will show you how to create new menu items and manipulate existing ones. First we will link the Video mainmenu item directly to it's childs (Local Drives) child Folders. So on entering Video on main menu will bring up the movie brower instantly. (Note: you won't be able to access all other items under Video then, like youtube, mediaservers, etc...)
doBuildMenus
All the magic of creating new menu items happens in this function. So let's start with this. The existing menu items are accessed by the title in this example.
ExamplePlugin.prototype.doBuildMenus = function() { // we access existing menu items by their names Menu.Top["$$Video"].handler = function(){ Menu.Top["$$Video"]["$$Local Drives"]["$$Folders"].handler() }; Menu.Top["$$Video"].title = "Movies"; Menu.Top["$$Video"].image = Menu.Top["$$Video"]["$$Local Drives"]["$$Folders"].image Menu.Top["$$Video"].focusedImage = Menu.Top["$$Video"]["$$Local Drives"]["$$Folders"].focusedImage }
Menu.Top
Globaly access menu item properties. These are accessed as shown in the the above example code. To find out the right title (they are case sensitive!), it's useful to write a some logging/displaying code as i've shown with the markup file name in the page section (using onMenuSelect()).
new Menu()
Let's create a new menu item now. This is going to be a quite simple reboot option. All the following code should also go into the existing doBuildMenus. It's gonna have the same icon image as the config item for now, you can change that.(3rd and 4th parameter in new Menu())
var topMenu = new Menu("Reboot", "$$Reboot", Menu.Top.$$Settings.image, Menu.Top.$$Settings.focusedImage, true)
the parameters are Menu( name, title, image, focusedImage, visible).
addChild()
Now we add a submenu item to which will actually reboot the wdtv when selected.
topMenu.addChild(new Menu("doReboot", "$$Reboot now", Menu.Top.$$Settings.image, Menu.Top.$$Settings.focusedImage, true))
So we have a new Menu created, let's add it to the main menu...
Menu.Top.addChild(topMenu)
...and add the actual reboot function.
Menu.Top.Reboot.doReboot.handler = function() { system("sync && reboot") }
onMenuSelect
onMenuDeselect
Reference
Menu Variables
- menuitem
- name - Menu name
- title - Menu displayed title
- image - Path to menu displayed icon
- focusedImage - Path to selected menu icon
- visible - Visible or not
- firstChild - first cild item
- parent - parent item
- next - next menu item
- prev - previous menu item
- childCount - submenu item count
Menu Events
YourPlugin.prototype.doBuildMenus = function() { }
YourPlugin.prototype.onMenuSelect = function(menuItem){ }
YourPlugin.prototype.onMenuDeselect = function(menuItem) { }
Menu Functions
var myMenu = new Menu(name, title, image, focusedImage, visible);
addChild(childMenu)
Page Variables
- page
- markupFileName - OSD XML Filename
- extraContent - XML Content to append the original XML File
- isMediaListPage
- selectedMedia
- name
- folder
- path
- setParam(paramName, value)
- getParam(paramName)
Page Events
YourPlugin.prototype.onPageCreated = function(page){ }
YourPlugin.prototype.onPageEnter = function(page){ }
YourPlugin.prototype.onPageKey = function(page, key){ }
YourPlugin.prototype.onPageLeave = function(page){ }
YourPlugin.prototype.onPageTimer = function(page){ }
Page Functions
Page.Top.redraw(true)
Page.Top.getParam("VARIABLE")
Page.Top.setParam("VARIABLE", value)
-- recliq 2010/05/23 --